PREMIERE ISSUE

Published by DesignWrite U.S. $7.99 AUG/SEPT2002 ISSUE 1.1

THE REALBASIC REVOLUTION Now ANYONE Can Program!

ANIMATION SECRETS THREE WAYS TO ANIMATE BY JOE STROUT REGEX EXPLAINED REVIEWS BY MATT NEUBURG UNIHELP WINDOWSPLITTER INTERVIEW MPCALC A CHAT WITH ANDREW BARRY, CREATOR OF REALBASIC PLUS Q&A, ALGORITHMS, BEGINNER’S CORNER, POSTMORTEM REALCHALLENGE, & DEVELOPING WRITER MORE! Peachpit Press has the help you need! Save Coming Soon! Sign up for a free PDF excerpt 20% from REALbasic for : SAVE 20% during Visual QuickStart Guide MacWorld NYC 2002. Stop by booth #631 Stop by booth #631 or go to: www.peachpit.com/forms/programming.asp to purchase these titles and more!

Adobe Illustrator Scripting Hot Cocoa for Mac OS X JavaScript for the World Wide XML for the World Wide By Ethan WIlde By Bill Cheeseman Web, 4th Edition: Visual Web: Visual QuickStart ISBN:0-321-11251-2 • $35.00 ISBN: 0-201-87801-1 • $44.99 QuickStart Guide Guide By Tom Negrino & Dori Smith By Elizabeth Castro AppleScript for Applications: HTML 4 for the World Wide ISBN: 0-201-73517-2 • $19.99 ISBN:0-201-71098-6 • $19.99 Visual QuickStart Guide Web, Fourth Edition: Visual By Ethan Wilde QuickStart Guide Perl and CGI for the World Wide Unix for Mac OS X: Visual ISBN: 0-201-71613-5 • $21.99 By Elizabeth Castro Web, 2nd Edition: Visual QuickPro Guide ISBN: 0-201-35493-4 • $19.99 QuickStart Guide By Matisse Enzer #: Visual QuickStart Guide By Elizabeth Castro ISBN: 0-201-79535-3 • $24.99 By Jose Mojica 2 for the World Wide ISBN: 0-201-73568-7 • $19.99 ISBN: 0-201-88260-4 • $19.99 Web: Visual QuickStart Guide By Dori Smith Python: Visual QuickStart Guide ISBN:0-201-74864-9 • $21.99 By Chris Fehily ISBN: 0-201-74884-3 • $21.99

Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 3 AUG/SEPT2002 ISSUE 1.1

THE MAGAZINE FOR REALBASIC ® U S E S REALbasic Developer is not affiliated with REAL Software, Inc. FEATURES 11 Postmortem: Writer by Daniel Kennett Pioneers get the arrows. Learn from the experiences of someone else. Postmortem 11 14 Interview: Andrew Barry REALbasic’s creator may no longer guide the software, but his vision still influences us all.

16 The REALbasic Revolution by Marc Zeedar What makes REALbasic so revolutionary?

18 Three Ways to Animate by Joe Strout Find out which animation technique is appropriate for your project.

Revolution 24 Regex Explained by Matt Neuburg 16 Understand the mysteries of powerful regex commands. COLUMNS Source Code ...... 5 The Topographic Apprentice. . . 38 REALchallenge...... 50 A word from the Publisher. Step-by-step 3D graphics. Test your programming skill and win prizes! Beginner’s Corner ...... 28 From Scratch ...... 40 Just getting started? This is your Follow a project from concept to Animate column! completion. REVIEWS, PROFILES, ETC. 18 Advanced Techniques ...... 30 AppleScript...... 42 REALbasic News ...... 6 Tips for professionals. Using AppleScripts in RB. Carbon Events Plugin 2.5 ...... 8 Ask the Experts ...... 32 Cocoa...... 43 Your questions, our answers. Cocoa lessons for the REALbasic CURLLinkButton...... 8 programmer. Algorithms ...... 34 MPCalc ...... 9 The core of all programming. Interface Design ...... 44 Stimulus ...... 9 Proper user interface design. Object-Oriented Thinking . . . . 36 UniHelp 1.1 ...... 10 Understanding OOP. Beyond the Limits ...... 46 Regex Advanced secrets. WindowSplitter ...... 10 24 Focus ...... 37 Tips for cross-platform compiling. REAL Ads...... 49

REALbasic Developer (ISSN 1540-3122) is the ultimate source for tutorials, tips, and advanced techniques for programming with the REALbasic language. REALbasic Developer is published six times per year and is distributed in print and PDF (electronic) editions. Subscription Rate: Standard print and PDF subscriptions for U.S. addresses are $32 and $16 respectively. To subscribe, or for other subscription options, visit our website at . Postmaster: Send address changes to REALbasic Developer, PO Box 66831, Scotts Valley, CA 95067-6831. Customer Service: For changes of address, send both old and new address to or write to us at REALbasic Developer, PO Box 66831, Scotts Valley, CA 95067-6831. Please include your account number with all correspondence. Back Issues: Previously published issues may be ordered from our website at .

Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 3 REAL LETTERS OPINION & FEEDBACK is published by DesignWrite, P.O. Box 66831, Scotts Valley, CA 95067-6831 and has no affiliation with REAL Software, Inc.

Publisher & Editor GOOD LUCK! ONE CLICK Marc Zeedar [email protected] Good luck with the launch of REALbasic On the front page of the RB Dev Mag Developer magazine. I’ll be looking forward site, there’s a calendar image with a week Editorial Board Joe Strout, REAL Software [email protected] to reading it. circled, talking about when the first issue Matt Neuburg, Author [email protected] Michael Swaine will come out. By any chance, is the calendar Erick Tejkowski, Author [email protected] Author, REALbasic QuickStart Guide shown in the image one of the One Click (forthcoming) calendars? News Editor Kevin Ballard Chris Willis [email protected] MASCOT GREETINGS Review Editor I just wanted to thank you for the honor Yes, it is! We’re big One Click fans here Brian Jones [email protected] of being named as the official mascot of at RBD: http://www.designwrite.com/ REALbasic Developer! My family is so oneclick/ Copy Editors Toby Rush [email protected] proud of me. Now I have something up Tim Lisauskas [email protected] on my second cousin, Max! (He works for MacAddict.) Advertising Coordinator Arby Marc Zeedar [email protected] [email protected] Webmaster Sylvain Le Borgne [email protected] CAN’T WAIT Send your Letters to the Editor to Thank you so much for launching this [email protected]. You must Layout & Design magazine. I can’t wait for my first issue include your full name and valid Marc Zeedar [email protected] to arrive! email address, but we will withhold Artwork Frank Palayaman publishing either on request. All Scott Melchionda (Cover) [email protected] New York letters may be edited for content Lloyd Colbaugh (Arby) [email protected] or length, and become the property LONG LIFE of REALbasic Developer. Columnists Didier Barbas [email protected] Long life to this new magazine! Sean Beach [email protected] Colin Cornaby [email protected] Thomas Cunningham [email protected] Dean Davis [email protected] Will Leshner [email protected] Joseph Nastasi [email protected] Matt Neuburg [email protected] Thomas Reed [email protected] How to Download Source Code Toby Rush [email protected] Article resources available at: Christian Schmitz [email protected] Seth Willits [email protected] http://ww.rbdeveloper.com/subscriber/ Charles Yeomans [email protected]

Every article in REALbasic Developer includes an “RBD number” at the end About the Mascot presented like this: Arby™ is the official mascot of REALbasic Developer magazine. He’s an amateur RBD# 1234 but determined REALbasic programmer, spending late nights trying to make nthField a few milliseconds faster. He’s To retrieve an article’s resoures follow these steps: your guide for all things REALbasic. Watch for him in the magazine and on the RBD website. Step 1: Go to the password-protected RBD subscriber website (at www.rbdeveloper.com/subscriber/). REALbasic® is a registered trademark of REAL Step 2: Log in using username: subscriber and password: yogurt. (This Software, Inc. It and other trademarks used within password changes for each issue of RBD. Please do not share this password this publication are the property of their holders and with non-subscribers.) are used only for editorial purposes with no intent Step 3: In the Get Article search field, type in theRBD number of the article to infringe. REALbasic Developer, the REALbasic Developer logo, and the Arby mascot name and you need. All resources for that article — source code, graphics, demo projects, are trademarks of DesignWrite. etc. — will be available for instant downloading. Contents Copyright © 2002 by DesignWrite. All Rights Reserved

4 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 5 Source Code by Marc Zeedar

Welcome! A dream becomes reality

hen I first began using REALbasic, volunteers were not always reliable and That may not be much to an Adobe, but WI was amazed: how long had this I was working a full-time job myself; I for me it was a windfall, and it was the tool existed without me knowing about couldn’t make up the slack. first step toward REALbasic Developer it? It seemed cruel I hadn’t discovered It was a difficult decision, but I put the becoming a reality. it earlier. magazine on hold. The last thing I wanted The step was the launching of I’d always longed to program my was to launch and immediately fold, REALbasic University, a weekly tutorial Macintosh, but I hated the tedious business damaging the credibility of the concept series I wrote for the Applelinks website of learning the Mac’s complex Application in the process. starting in February 2001. I figured writing Programming Interfaces (APIs). I spent I had no intention of abandoning those columns would be good practice and hundreds of dollars on massive program- REALbasic Developer permanently. I would draw attention to REALbasic and ming books and Inside Macintosh volumes, hoped at some point in the future I’d be REALbasic Developer. only to watch them become obsolete before in a position to afford to quit my day job I had time to learn them! and launch the magazine properly. A Revolution is Launched REALbasic was the answer. REALbasic hasn’t made me a millionaire, But despite its simplicity and elegance, but it has certainly changed my life. I’m not REALbasic is a true programming envi- a programmer by training, but with RB I ronment. It can be obtuse, especially for The Mac brought computers to was able to accomplish a dream. larger projects. That’s why I chose “Revolution” as the The Internet is an invaluable resource people who weren’t (and didn’t theme for this first issue. REALbasic is a for RB users, but I still longed for a single revolutionary product in the same sense source for all things REALbasic: a regular the original Macintosh was revolutionary. magazine, professionally designed and want to be) computer literate. The Mac brought computers to people who written, with all the quality of Macworld. weren’t (and didn’t want to be) computer That dream is finally a reality. REALbasic brings programming literate. REALbasic brings programming to people who aren’t (and don’t want to A Magazine’s Journey to people who aren’t (and don’t be) computer scientists. In August 1999 I had the idea for It’s a match made in heaven. REALbasic Developer. I was thinking want to be) computer scientists. solely of a subscriber-based PDF “ezine.” Give Me Feedback I posted a survey on my website and the I hope you enjoy REALbasic Developer. results showed that people would be I wish this were a venture that could be willing to pay for a quality REALbasic REALbasic to the Rescue done for free, but producing a magazine publication. During this time, I’d been working on is expensive. Your support means a great With a budget of zero dollars, I assembled a of couple novels, and I’d been horribly deal to everyone involved. It’s a statement a team of volunteers and began making frustrated by the complex task. With a spurt to us, to Apple, and to the world that Mac plans for the first issue. It soon became of inspiration, I wrote a little program in programming is for everybody, not just clear, however, that the project was more REALbasic which I called Z-Write. It was those with computer science degrees. Your complicated than I’d anticipated. The a word processor designed to help me keep subscription will ensure that REALbasic all the snippets of text associated with my Developer is around for a long time. hen RBD publisher Marc Zeedar novels organized. Z-Write worked so well, I want this to be your magazine, W was a kid he used to create I decided to try selling it. so let me know what you want to see! magazines just for fun. Now he’s doing To my astonishment, Z-Write proved Write to [email protected] or it for a living! You may contact him at popular: it brought in over $2,000 in the [email protected]. . first month of release! I’d love to hear from you! RBD# 1000 4 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 5 REALBASICNEWS EVENTS & RELEASES REALBASICNEWS EVENTS & RELEASES

REALBASIC 4.5 www.quantum-meruit.com/ the new file. http://ljug.com/ project. http://www.mac-x- PRE-RELEASES RB/SortLibrary.sit.hqx sw/resploder.html software.com REAL Software is working on the next release of REAL- BARCODE AUTOMATOR 1.0 . Version 4.5 adds sheet Intelli Innovations, Inc. has support, the PagePanel Control released Barcode Automator (which works like an invisible 1.0, a barcoding suite specifically TabPanel), virtual volumes, designed for bulk generation parent and child controls for and AppleScript automation. better organization of controls, Barcode Automator supports 9 lots of database additions and different symbologies, includes DRAW CONTROL fixes, sounds for tips, new vectorized EPS and TIFF export PLUGIN V1.0 method and properties dialogs, capabilities, and comes bundled DrawControl is a plugin which a new build settings dialog, a with a set of OCR fonts. Barcode adds new OS X controls — such new icon compositor dialog to Automator is now available for as the small check box, the small add your icons more easily, a $329.95; a full-featured demo radio button, the ArrowButton, brand-new prefs window, an version is also available. XCHAR 2.0 and round BevelButton — and “Open Recent” menu, listbox http://www.intellisw.com/ XChar 2.0 is a new version of other functionality such as icon enhancements, a splitable barcodeautomator the OS X utility that allows you and arrow support. http:// code editor, a huge number to use uncommon characters www.mac-x-software.com of changes to the Quicktime even if you don’t remember the support, a huge number of correct key combination. This MOVIEWORKS PLUGIN V1.1 changes to the 3D Classes, new version adds compatibility This new plugin from Alfred Van vector graphic support, Pref- for applications which do not Hoek enables more powerful erences menuitem (in the support Drag and Drop and also features to be used with the Application menu) support on allows to copy the font and style QuickTime Movie Player. Mac OS X, folderitem enhance- along with the character. More- http://homepage.mac.com/ ments, new icons for the code over, lots of bugs were fixed and vanhoek/#movieworks editor and menus, and all those interface was improved. http:// little bug fixes and little new DRAG PROMISE EXAMPLE www.ziksw.com/software/ DATABROWSER features too. REAL Software is This example project creates xchar.html PLUGIN V0.5.1A trying to make this release the a DragItem from within a This plugin implements the most stable version ever, with canvas, and when dropped DataBrowser control in Carbon a long beta testing period. If into the will create a for Mac OS 9 and Mac OS X. you want to test out prerelease file at that location. http:// It is a more advanced listbox versions of REALbasic, join the www.freaksw.com/ than REALbasic’s own control RB Developers List. Informa- rb-examples.html and provides more control and tion on this list is available at more features to use. http:// http://www.realbasic.com/ RESPLODER www.webprofitable.com/RB support/internet.html. ResPloder explodes the resources of a file into folders. SETH WILLITS SORT LIBRARY 1.8 The resource types become CARBON DECLARE LIBRARY CLASSES/PLUGINS SortLibrary is a free, open- folders and the resources This is a handy collection I updated my REALbasic section source REALbasic library become files that can be of enhancements available and added a lot of my plugins, providing robust, optimized edited with any hex editor. through the Declare feature classes, modules, and examples implementations of several Some resource types are auto- of REALbasic. The library is I have neglected to put up for standard sorting algorithms matically saved in popular file mainly for Carbon applications a while. A total of 16 in all. I for use by REALbasic devel- formats. The data fork of the but includes support for Classic also uploaded version of opers. The major change in original file is also preserved. and maybe Windows too. http: FSSinceWhen which I forgot to version 1.8 is a substantial ResPloder can also implode a //kevin.sb.org/Files/CarbonD do on the initial release. http:// rewrite of quicksort which ResPloded folder back into a eclareLibrary.sit www.freaksw.com/rb.html implements the three-way file — drop a “ResPloded” folder partitioning method of Bentley onto ResPloder and a new file CUSTOM ICON PLUGIN V1.0 DOCK MENU PLUGIN V1.0 and McIlroy. This yields with exactly the same struc- Custom Icon is a plugin which Dock Menu Pro allows users substantial improvements in ture as the original file will be adds new OS X icons — such to create dynamic hierar- performance in the presence created. If any of the resource as the alert icon, the note icon, chical Dock tile menus for of equal keys. In addition, files in the ResPloded folder the stop icon and other system their REALbasic applica- quicksort is now implemented have been modified, then the icons — to any REALbasic tions running under Mac OS using recursion. http:// changes will become part of X 10.1 or higher. Dock Menu

6 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 7 REALBASICNEWS EVENTS & RELEASES REALBASICNEWS EVENTS & RELEASES

Pro implements virtually all URLAccess . The menu, standard alert sheet, including an ultra-fast MSR Menu Manager functions to new version of the plugin alert dialog support, Ask Save (multi search replacement) allow users to customize their allows setting and getting of Changes, Discard Save Changes object, and FastReplaceAllB Dock menu anyway they feel URLproperties and supports sheet support, Put File dialog method for doing replaceAllB fit. It also allows users to add HTTPURLMethods such as sheet support, full service at speeds up to 267 times custom data “tags” to each “GET,” “SET,” “POST” and menu support, access to usable faster than ReplaceAll. http:// menu item for added flexibility. others. You can post searches, screen size (for respecting the www.elfdata.com/programmer/ Dock Menu Pro plug-in costs and above all it works flawlessly Dock), Quit event notifica- downloadindex.html $10 and is royalty free. http:// with the Van Hoek’s HTMLren- tion, complete proxy icon www.everydaysoftware.net/ dering plugin. The versatility support with icon dragging ROUND BUTTON & code/index.html of URLAccess Plugin leads to and window’s path menu, the ROUNDED BEVELBUTTON numerous new possibilities, ability to get any folder by type PLUGINS including development of a and domain, the ability to set These plug-ins allow users to light-weight web browser appli- and get long file names, and create real round navigation cation that may compete with access to the current theme buttons and rounded bevel other web browsers. URLAccess identifier. Cost: $15. http:// buttons under Mac OS X; the plugin requires MacOS 8.5 or www.everydaysoftware.net/ buttons are compatible with OS FSPLAYQTMOVIE — MIDI higher. Users may purchase a code/index.html 8.5 and higher. http://www. FSPlayQTMovie can be used professional license for building everydaysoftware.net/code/ to play a QT compatible commercial products ($39), an RBULK BUILDER 1.2.6 index.html movie file without using a academic license for building RBulk Builder is a Batch MoviePlayer control. Because products you cannot sell Building companion for it doesn’t have a movie control, ($12), or an amateur license REALbasic. With it, you can it is only useful for hearing the to get you going (free). http:// automatically launch different sound track. This plugin will be homepage.mac.com/vanhoek builds, changing the name, the most useful for developers that platform, the language and even want to use MIDI files in their REALDB TOOLS constant values for each one. It applications. MIDI files are REALdb Tools gives you the is designed for people that need CALENDAR CLASS required to be opened by REAL- ability to manipulate REAL to build many different binaries Calendar Class is an easy- basic as a QuickTime movie database files in ways that the (different platforms, localized, to-insert calendar for your and played by a MoviePlayer. built-in database engine does demo/light versions...) from a projects. Simply drag the class http://homepage.mac.com/ not provide at this time. With single source project file. into your next project to add a freaksoftwarerb/ REALdb Tools you can compact Version 1.2.6 provides compat- customizable calendar. Change a database to make it smaller ibility workarounds with font, button color, background SPEECH RECOGNITION after records have been deleted, REALBasic versions 4.0 and color and more for a customized PLUGIN V1.1.2 drop any table or column from above when building carbon look for every project. http:// The Speech Recognition plug- a REAL database, change table applications. The program is www.colourfull.com/å in allows simple support names, change column names free and open-source. http:// for Speech Recognition and and data types, and add new www.liane.net/rb/rbulk Speech Synthesis. It also tables and columns. http:// allows users to install speech www.realsoftware.com/ STRING STUFF PLUGIN 3.1.1 help in the Speech Commands realbasic/about/ The String Stuff Plugin can window under Mac OS X. It REALdbTools.html return a MemoryBlock pointing works on PPC and Carbon a string, allowing a REALbasic with Speech Recognition 1.5 program to alter the string “in or higher. http://www.every place” by altering the memo- daysoftware.net/code/ ryblock. The plugin allows the index.html use of REALbasic text func- tions, such as AscB and InStrB with drastically improved CARBON EVENTS performance and provides PLUGIN 2.5.2 CharacterSet searching. String This new version of the Carbon Stuff contains “FastString,” a Events Plugin provides a wealth class that can increase the speed URL ACCESS PLUGIN V2.0 of functionality to Carbon appli- of string appends by tens or Alfred Van Hoek’s URLAccess cations: access to a toolbar hundreds of times compared plugin allows REALbasic appli- button, scroll wheel support, to REALBasic strings. The cations to upload and download live window resizing, access plugin includes a huge range Internet files using the system’s to the application dock tile of UTF32 handling methods, RBD# 1025 6 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 7 REAL REVIEWS TOOLS & PLUGINS REAL REVIEWS TOOLS & PLUGINS

Carbon Events Plugin 2.5 Daniel Howard IN BRIEF Product ou use REALbasic because it is A Sheet is an OS X dialog box that in makes that as easy as adding two Carbon Events Ythe easiest Rapid Application is attached to a window. They can be lines of code! Plugin 2.5 Development tool for the Macintosh. translucent or opaque and make it Although this plug-in has a lot of Manufacturer However, it is limited when it comes easier for the user to distinguish what great features, it still has some minor Everyday Software to OS X (Carbon) events, features, window the dialog box is related too. drawbacks. For instance, it does support Price and controls. That is where the Although it is possible to create a sheet Live Window Resizing, but if you do $15 Carbon Events Plug-In comes in. It in REALbasic, without this plugin you this, no controls can be locked to any System Requirements takes over where REALbasic leaves cannot use sheets to display Save/Open of the windows sides (which limits the Mac OS X 10.1+, you stranded. dialogs. usefulness of Live Window Resizing). REALbasic 3.x The Carbon Events Plug-In adds The following may sound like trivial Also, Translucent sheets will not work if Contact Info several key features for Carbon builds: features; however, they are very useful. anything else in the window is redrawn. [email protected] Scroll Wheel support, Quit events, The first is the inclusion of Proxy Icons. These problems are REALbasic-related homepage.mac.com/ Sheets support, useable screen space, Proxy Icons are displayed in the title and are not controllable by the creator everyday Proxy Icons, and a lot more! bar of a window and have become of this plugin. Pros The Quit event is essential for OS X widely used in OS X. Their inclusion Besides these few minor drawbacks, Inexpensive; Easy to use; Gives essential builds. It enables you to use the Quit in this plugin allows programmers to the Carbon Events Plug-in is a must OS X controls menu item that is found under the make their applications follow OS X have for all OS X developers. Hopefully Application menu. REALbasic quits appearance conventions. The plugin REALbasic will add these features in Cons Live Window Resizing when this menu is selected, but you can’t also allows users to keep track of the future releases, but until then this is limited; scrollwheel add any code to the event. (i.e. when usable space on their screen. Under Mac plugin will do the trick. support doesn’t work a user quits your word processor you OS X, the user’s desktop will usually all the time would usually want to make sure that have a Dock on it, in any of a number Rating (1.0 - 5.0): 4.5 any open files have been saved. With of positions. Users will expect that your REALbasic 4.0.2 and lower, this was not application recognize the position of an option. The application would quit their Dock. While nearly impossible without warning when Quit was selected in REALbasic, Carbon Events Plug- from the Application menu.) RBD# 1024

CURLLinkButton Mike Richards IN BRIEF Product t one point in time or another, Several methods let you customize user can use CURLLinkButton. In other CURLLinkButton almost all REALbasic developers the appearance of your new link. You words, anyone with a Quadra and A Manufacturer will want to integrate a clickable URL can set a special cursor when the mouse REALbasic v1.1 up to an OS X machine Catalunya Disseny inside of their application. And thanks is hovering over the link, change the with REALbasic v4.0.2 can use it. The Informàtic to REALcode’s CURLLinkButton font and size of the text, and more. price, you ask? Entirely free. Price control, anybody can do this! You can even change the text that’s However, the total control freak Free CURLLinkButton is simple to use: displayed to something other than the might not like CURLLinkButton. The Contact Info you need to drag the class into your URL, and it still works perfectly. text is highlighted when you click on Pablo Iglesias project window first, then you create You can use any URL with the link, rather than the text simply 63 Local 4 a canvas control, set its “super” class CURLLinkButton, including http, changing colors, as you are probably 08302 Mataró (Barcelona), Spain to CURLLinkButton, type a few lines ftp, telnet, or any other URL type that’s used to in a web browser. There’s [email protected] of code (documented in the Read Me), properly configured in your Internet no way to alter the text color either, catdis.com/realcode/ and run the program. Not only does settings. No declares are used at all, without editing the class yourself. Bold realcode.htm it resize itself to the exact size of your meaning it can work on any REALbasic- and italic support would have been nice, Pros link, it also handles drawing and going supported platform (68K, PPC, Carbon, although would probably not have been Easy to use; supports to the URL that you indicated. Win32), and it comes as a REALbasic v1 used much anyway. But as I mentioned, every version of REALbasic; format project, meaning any REALbasic the class is open source, and you can customizable; free revise and edit it as you please. There’s no revolutionary code Cons No longer supported; here. Just a simple class that does slightly strange a simple job: create a clickable link in appearance your REALbasic application. Anyone Rating (1.0 - 5.0): 3.6 can use it, and it does the job well.

RBD# 1023

8 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 9 REAL REVIEWS TOOLS & PLUGINS REAL REVIEWS TOOLS & PLUGINS

IN BRIEF MPCalc Plugin Jim Rodovich Product MPCalc Plugin hances are if you need to do some The MPCalc plugin operates using to the simple method names that are math calculations with REALbasic, what is known as the Reverse Polish easy to remember. Manufacturer C Dr. Robert Delaney doubles can hold numbers as large or Notation (RPN). This is somewhat MPCalc gives programmers access to small as you’ll require. However, if different from what you’re probably a wide array of mathematical functions. Price Free you need to get very precise answers, used to, but it’s a small adjustment. It supports basic arithmetic operations, in some cases a double might not be In an expression written in RPN, as well as exponential, trigonometric, Contact Info sufficient. Typically, numbers repre- both numbers are written before the hyperbolic, and logarithmic functions. [email protected] sented by doubles are accurate for about operator. For example, instead of It also supports several more obscure Pros the first sixteen digits. Anything to the writing 1 + 2, you would write 1 2 + in functions, including the Beta and Very high precision; Free right of the sixteenth digit is most likely RPN. It’s a different way of thinking, Gamma functions, Bessel functions, inaccurate. This means that if you’re but with a little practice, even expres- and Fresnal Integrals. Cons Adds about 700k to using a double to store a number that’s sions with several operations are easy Additionally, MPCalc has four filesize; uses RPN in excess of one quadrillion, you can to state in RPN. storage registers for remembering math expect any values after the decimal Unfortunately, instructing MPCalc the results of previous calculations. The Rating (1.0 - 5.0): 3.8 point to be incorrect. to execute various calculations isn’t as registers prove quite valuable since the Fortunately, you won’t need to simple as performing arithmetic on inte- only other way to store multiple-preci- forsake modern technology and resort gers or doubles in REALbasic. Instead, sion values is by using strings. to using paper and a pencil when you’re you’ll need to enter a few commands to Overall, MPCalc is a solid plugin that dealing with highly precise numbers. tell the plugin to do anything. Adding is fairly well documented. Because of Instead, you can use MPCalc, a freeware two numbers requires five commands: its flexible precision and wide variety of REALbasic plugin that can perform two to enter the first number, one to scientific functions, the MPCalc plugin calculations on numbers with up to enter the second number, another to is a worthy addition to your REALbasic thirty thousand digits. You can even tell MPCalc to add the numbers, and a toolbox if you do any serious math set the precision yourself, so if you just fifth to read the result. Even though it calculations. need twenty digits, your program won’t takes five lines of code to perform such be chugging along calculating 29,980 a simple calculation, it’s still very easy RBD# 1021 unnecessary digits. to issue commands. This is in part due

IN BRIEF Profile: Stimulus 2.0 Greg Fiumara Product Stimulus 2.0 f you think the tools that the in your application. This application This new release of Stimulus has REALbasic environment gives also takes advantage of the famous CD amazing new error handling techniques, Manufacturer I Electric Butterfly you to work with digital media are Control by Toby Rush, which powers thanks to REALbasic version 4. The new too few, think again. Stimulus 2.0, its Audio CD playback. release of REALbasic includes a new Price $12 Electric Butterfly’s image viewer and If it were not for custom classes and event called “Unhandled Exception.” audio/video player, is out. the sub-classing made available in the This allows programmers to not have to System Requirements Stimulus is an all-in-one digital REALbasic IDE, REALbasic would add “exception” lines to each object in Mac OS 8.6+, Mac OS X 10.1+, Quicktime 4+ media viewer. If you are tired of probably not have survived. Sub- their program to prevent from crashes. (Classic), Quicktime switching through tons of applications classing is one of the more powerful Instead, the programmer can add in just 5+ (OS X), 6 MB RAM to view your media files (Photoshop for features in REALbasic, and, clearly, a few lines of code to the Unhandled Contact Info your pictures, iTunes for your MP3’s Stimulus 2.0 shows that. From its Exception event and if there is a crash, it [email protected] and iPod, QuickTime Player for your amazing color bevel buttons that also triggers the code in that event. Because www.ebutterfly.com/ videos), Stimulus is for you. This version have 32x32 icons to the WindowSplitter of this, Stimulus can also have very light stimulus of Stimulus has many new features, control, Stimulus 2.0 would not have memory requirements to compliment including the ability to play back from been released or have been successful its small file size. your iPod. (Didn’t know you could do without the help of sub-classing and If the user happens to like this that with REALbasic, did you?) third party class developers. shareware program, as long as they Stimulus supports over fifteen file Electric Butterfly has found an have their credit card handy, they can formats, from Audio CD to WAVE, interesting and very clever use for a order it without getting out of their and still more formats are planned timer control in Stimulus 2.0. This new chair. Stimulus makes perfect use of for inclusion in the 3.0 release of the version of Stimulus has a slide show the eSellerate plugin for REALbasic software. feature. This feature activates a timer for convenient online ordering. Stimulus has a built-in help system, that, every few seconds, scans through Stimulus 2.0 shows off the power which is more or less a simple emula- the built-in file browser for media files of REALbasic in many impressive tion of the Language Reference built that it can open. It then displays the areas. into REALbasic. The help demonstrates files that it finds one at a time for a RBD# 1022 a good way to use HTML rendering slide-show effect.

8 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 9 REAL REVIEWS TOOLS & PLUGINS

UniHelp 1.1 Brian Jones IN BRIEF Product hen it comes to help systems, panied by a print button at the top of of the options revolve around the display UniHelp 1.1 the task of recreating the help the window. colors of the graphical elements such W Manufacturer information in the several different Including UniHelp in a project as buttons and list icons. It also allows Electric Butterfly platform-specific formats can occupy is simple. In the Project window, the user to set the default language of Price important resources in the finishing the user must import the UniHelp the user interface elements to one of $49 out process before application release. module and the UniHelpGraphics the following: English, French, Italian, UniHelp from Electric Butterfly makes folder. A short clipping of code which Spanish, German, or Portuguese. System Requirements REALbasic 3.5.2 or these problems a thing of the past with has been supplied in the UniHelp UniHelp provides a simple, multi- 4.0.2, Mac OS 8.6+, its universal, multi-platform help documentation should be inserted at platform solution. However, UniHelp Mac OS X 10.1+, interface. Configuring the impressive the Help menu event handler which costs $49. At this price, it is likely to Windows 98+, Quicktime (for image array of customizable attributes for the will create the window. A segment of be worthwhile for more serious devel- and multimedia UniHelp interface is quick and creating this code can be adjusted so that certain opers, but hobbyists may not be able to features only) the content is as simple as working in properties of the UniHelp object can be justify the expense. It does make things Contact Info your favorite text editor. set to customize the UniHelp interface. incredibly simple, but other than its [email protected] UniHelp, when included in a user’s All of the text clippings displayed in powerful search features, it does not www.ebutterfly.com application, manages a self-contained the help window are written to disk provide much functionality that could Pros help window with a simple interface. On in a directory entitled “Help.” The not be replicated by developers with Slick; powerful; takes the left side of the window is a ListBox user creates plain text or HTML files the necessary time on their hands. care of tedious work that can be hierarchical if needed. Each and names them according to an Cons element in the ListBox corresponds to easy-to-learn naming convention May be too expensive a different text clipping which will be that determines their display in the for anyone not using it displayed in the scrollable EditField UniHelp window. to its full potential on the right side of the window. The The customizations available are Rating (1.0 - 5.0): 3.8 help items can be browsed in this list, simple, but they are effective in or the user can search for key words. incorporating UniHelp into the overall Easy navigation butttons are accom- look-and-feel of your application. Most RBD# 1020

WindowSplitter 4.0 Brian Jones IN BRIEF Product here are many applications in which ListBox and EditField controls. This and the position of the separator for the WindowSplitter 4.0 a lot of information needs to fit in simplicity is a result of a great design purposes of saving interface settings to T Manufacturer a small window. A perfect solution for decision made by Einhugur in a recent a preferences file. Also, some special Einhugur Software this problem is the use of a bar that can version of WindowSplitter. It used to events allow the developer to control the Price be dragged to resize different areas of be that a developer had to respond to drawing of the separator and to define $49, for Einhugur the window. Users can expand areas as an event and resize the appropriate the clickable region of the separator. subscription they need them and then shrink them controls himself; however, now WindowSplitter 4.0 provides a well- System Requirements in order to conserve window real WindowSplitter maintains a list of polished solution to easily including REALbasic 2.1+ estate. It is precisely this solution that controls that it will resize as needed. an important interface element preva- Contact Info Einhugur Software’s WindowSplitter Controls are added to this list using lent in many commercial applications. [email protected] plug-in makes exceptionally easy to the AddControl method. The boolean One deficiency is the lack of a catch-all www.einhugur.com implement. value passed as the second parameter documentation file. The included docu- Pros WindowSplitter 4.0 can achieve of the AddControl method refers to the mentation accessed with Einhugur’s Simplicity; surprising basic functionality using just one relative position of the control to the Plunger software is useful, but should flexibility method. Imagine creating a window WindowSplitter. Controls given values be supplemented with traditional Cons with a ListBox control on the left and of true are understood to be on top of a documentation. The program is paid Expensive unless an EditField control on the right with horizontal bar or to the left of a vertical for (as are other Einhugur products) you’re interested a WindowSplitter control in the middle control, while those given a false value through their subscription service. For in other Einhugur products; some (similar to UniHelp’s window above). are understood to be below a horizontal $49 US, users have access to all of their drawing quirks In the WindowSplitter control’s Open bar or to the right of a vertical one. The REALbasic add-ons including a year of event simply type these lines: old resize event has also been retained upgrades. Those developing applica- Rating (1.0 - 5.0): 3.8 for developers using custom-defined tions for which this kind of interface me.addControl(myListBox, true) controls and for the purposes of back- solution would be appropriate would me.addControl(myEditField, false) wards compatibility. do well to let Einhugur handle it for Several properties allow developers them. That’s it. Now, when the application to set things such as minimum sizes for is run, dragging the bar will resize the the areas on either side of the separator RBD# 1019

10 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 11 REAL REVIEWS TOOLS & PLUGINS Postmortem by Daniel Kennett

Writer: Behind the application

riter was my first REALbasic baby. the most stable, good-looking program I to make a nice interface. Controls are WIt started off in the REALbasic 2 could. Now, at version 2.6, it is a successful snapped to their proper places when you days, and I learned to program writing and popular program that I am proud to drag them to your project’s windows, and it. It slowly evolved until it got to version show off to everyone I can, especially at all you have to do it to set the right font, 4.5, when I decided to change the name work. “Hey, my program can do that much text size, and size of the control to fit its from “KennettText” to “Writer,” relabel more elegantly!” In the next few pages, I caption or contents. it version 1.0, and throw it out to the big will share my learning experience with you, After you have made your interface bad world. going through the most important aspects look right, the next things to consider are Back then it was really poor. There were of creating a successful program and what icons. Nicely done icons that are used for no exception handlers at all, and if you happens when you screw up. your application’s main, document, and tried to open the wrong kind of file it would (if appropriate) toolbar icons add the throw an exception and quit. Despite this, Interface extra sparkle and polish that is needed to Writer did quite well. Now, I realise this The first thing people judge your program make your product shine. However, badly was because the “Made with REALbasic by is its interface. Even if your program is done icons are worse than no icons at all! = piece of crap” era hadn’t yet started. stable, fast, and the most useful thing on If you really want icons, but don’t have a As Writer slowly developed, I began to the planet, not many people will use it if it drop of artistic talent (like me), you may see more and more REALbasic programs looks ugly. You really have no excuse not want to consider getting a specialist to do on VersionTracker, and I tried many of to do this, as REALbasic makes it simple it for you. This isn’t cheap, and should them to see what others had done. I wasn’t impressed with many; they either looked horrible or looked beautiful but weren’t programmed well, and threw exceptions everywhere. At first, the “Made with REALbasic” bashers were other program- mers who worked with complicated languages such as C, and weren’t too happy at seeing how quickly and easily you could make programs in REALbasic. They looked through the programs and blamed every single bug they found on this wonderful development environment. To this day, I see silly mistakes I make blamed on REALbasic by everyone. By this time, Writer looked fairly decent, was virtually exception-proof, and had started to mature into a fairly useful piece of software. I learned from other people’s mistakes and made Writer

aniel Kennett has written several D small programs with REALbasic, and successfully released a few of them to the public. Figure 1: Writer About Box

10 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 11 Figure 2: Writer toolbars for Mac OS 9 and Mac OS X

only be considered if you are making a they’re particularly evil, a small cash sum bin after a few months and start something big product and expect to get a consider- or a present. (See Figure 1.) new. Due to this, I didn’t comment my code able income from it, or if you are dirty Writer’s initial interface was absolutely or make it future-friendly. There was only stinkin’ rich. My experience with such terrible. Badly spaced canvases with one way to save a document, which was companies isn’t very good, as after much icons stolen straight from the system or from the menu bar, so I put the save code thought and consideration I invested in REALbasic lined the top of the window, into the FileSave menu handler which was spiffy icons from Acorn Creative, only to which when clicked on could not be fine at the time. Now, there are four ways find that they were unable to complete cancelled — releasing the mouse button to save a document — from the menu bar, my project due to “funding issues,” and outside the canvas still performed its opera- the toolbar, the “Save Changes?” dialog, I lost my icons and my money. However, tion. Now, in the Mac OS X version, the and via AppleEvents. Each of those four don’t let that put you down. Take a look toolbars mimic the beautiful toolbars that has its own save code, so when I update at http://www.iconfactory.com/. They are are used in Cocoa applications such as Mail the save code in one I have to change it one of the industry’s best, but are pricey. If and OmniWeb. They aren’t customizable in all four. Now, even when creating the you do consider them, bear in mind they yet, but that’s something I’m working on. tiniest of programs, I make the effort to designed the icons for the popular MP3 (See Figure 2.) comment my code and to use the wonderful player Audion, and the (not-so-popular It is important to tailor the interface for invention of global methods. Using these, among Mac users) operating system the system on which it runs. Mac OS X you can have your save code in one place Windows XP. Much as I dislike Windows, applications use slightly bigger fonts and only, and have your menus and toolbars I love its icons. If I had the money, I’d go controls than their Mac OS 9 counterparts, (or anything else) call it. My save methods for IconFactory in a flash. so they need a little more room to breathe. usually take the parameters: One more thing to consider is a logo Icons are also expected to be bigger, and for your program. Again, you could get a these large icons look out of place on Mac File as folderitem, askforlocation as Boolean, data as variant specialist to do this, but doing it yourself is OS 9, especially if they have been designed much more fun. Play around with the tools to fit in with Mac OS X’s Aqua look and feel. Then, I can simply call “SaveFile in Photoshop (if you have it), or another In the case of Writer, the interfaces are (document, false, editfield1.text)” graphics program. Often, your program’s so different I have split the program into and the code in that method saves my name with a few effects on it (make sure it’s two separate source files, one for “Classic” file, and it works from wherever I call tasteful) will be fine. If you want something and one for Mac OS X. It is more work to it. This is invaluable for all applications, fancier, the best thing to do is sit down update, but the effort is worth it as I have and absolutely necessary for larger ones. with a pencil and paper and draw. Once a program that looks great in both Mac OS Commenting code is important, too. It takes you have something good, scan it in and 9 and Mac OS X. a bit of extra time and you may think, “I touch it up in your graphics program. The know what my code does, I don’t need to third option is to look around while you Coding comment it!” but it is a godsend for when are with friends or colleagues, especially The code that makes Writer work is things go wrong, especially in lengthy or if one of them is artistic. Writer’s logo is terrible. Awful. I’m ashamed of it. It is complex pieces of code. Commenting makes based on a piece of art my friend Emily difficult to update, adapt, and to under- it a breeze to tell exactly what your code is drew, which I spotted when she brushed stand, especially after I haven’t looked at doing, where, and when. past me on her way home — it was really it for a while. Another important thing to do, especially that quick! Most friends will let you use When I started Writer, it was to learn how when performing lengthy operations, is their work if you give them credit, and if to program. I thought I’d chuck it in the to give user feedback. For example, the

12 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 13 Internet Dictionary in Writer used to do do choose to keep it free, never, ever do (http://www.versiontracker.com/), tell all its stuff in a loop, with no user feedback. what I did and decide to start charging your Mac-owning friends, and put a big If the operation took a long time, the user for it. People will get used to having it for sign on top of your house telling everyone would think that my program had crashed free, and will complain bitterly when you about it. Do whatever it takes to get word and would force quit it, complaining bitterly start to charge. I managed to get away with out! Once people know about your program as much as they could. Now, it works in a and start using it, you have something else thread so the user can do other things while to do: customer support. the word is being looked up, and provides feedback in the form of a progress bar, a Write a press release and Handling your Users chasingarrows control, and a small static- Your users can be very helpful and text that informs the user what is going on. e-mail it to all the big news polite, rude and abusive, and others can The operation now takes about three times be complete novices who need their hands longer, but the user knows what is going on. sites, create an entry at held to do even trivial things. It is important I’m sure 95% of your users will prefer that that you remain calm, helpful, and polite something take longer but know what is at all times. When you reply politely, help going on, rather than it happening quicker Version Tracker, tell all your users as much as possible, and generally with no feedback. This applies especially to be a nice guy, people will treat you with novice computer users, who rely on their Mac-owning friends, and respect. Listening to people who use your computer telling them what it is doing. program often is vital to making a successful The last and maybe most important thing put a big sign on top of your product. If you fix a bug or add a feature to consider is exceptions. Things can go that someone has requested, you’ll often wrong quite easily when programming, house telling everyone about get a very nice thank you from that person, and if you miss a potential problem that and possibly a donation or registration for a user runs into he or she will be presented your program. Do whatever your program. That person will then tell with a rude box informing them that your people what a nice guy you are, and more program has performed an illegal excep- it takes to get word out! people will use your program. tion and must shut down. If there was Feel free to ignore abusive people, as any unsaved work, it will be lost and you replying to a message that states “Your will have an angry user. More often than program sux! Make it better!” is usually a not, exceptions can be caught, fixed, and it, but only by the skin of my teeth. The waste of time. However, computer novices your program can merrily carry on as if things that saved my hide were charging a should get help and attention, as they will nothing had happened. For example, if your ridiculously small amount for it ($5), and appreciate it and you will get the same posi- program is instructed to open a corrupt not disabling or restricting the program tive image as you would when listening file, a nilObject exception may be thrown, in any way for unregistered users. The to bug reports and feature requests. Even which would cause the program to quit. best way to go if you want money for a if you don’t have time to write a lengthy However, after adding these lines to the free program is to politely ask for a small tutorial there and then, reply to the person very bottom of your file opening code, the donation toward the development of your and tell them that you don’t have time, but user will understand what has happened program, and to let your users decide what will contact them in a few days with better and will be able to try again. they want to pay. instructions. Oh, and don’t forget to do so, If you want to distribute your master- as broken promises are bad. Customer rela- Exception nilobjectexception piece as shareware, I recommend using tions are what people judge you and your Msgbox “An unexpected error has occurred. The the service provided by eSellerate (http: company by, so don’t let it slip. It can be a file you selected may be corrupted. Please try again.” //www.esellerate.net/). They don’t charge chore, but it is an important one. much for their service (10% of each sale to Other possible uses for the exception begin with) and provide a web store and Overview handler are writing to a log file that an error an amazing REALbasic plugin that allows There we have it. How Writer rose occurred, or giving the user information people to register from within your program from a pathetic little project to a popular about where to report what happened so without having to touch a web browser. and profitable program. If you follow you can have a go at fixing it. Users that get It can then automatically register your the advice here, you should be able to listened to are very happy users indeed! software once payment has been cleared, produce a program that avoids the “Made and a typical transaction takes less than with REALbasic = crap” myth, and keep Selling/Distributing five minutes. To see it in action, download people happy once you’ve got your program You have your beautiful, fast, excep- my program Writer and take a look (you going. Oh, I have one more piece of advice, tion-proof application sitting on your don’t have to purchase it too see what it which is to take your time! Writer is well hard drive waiting to be used and abused does). made, but only because I’ve had years by your adoring public. Now what? The Once you have your payment options set to work on it. Its bigger brother, Writer first thing to do is decide what to charge up, go ahead and upload your program to PRO, is more powerful, but has been a for it, if anything. If it is a simple app your website. If you don’t have one, you flop due to the fact that I rushed it and it that you have enjoyed making and think can use a free service such as Apple’s isn’t well built at all. Take a look at http:// others will like, I advise distributing it as iDisk to put your creation online. Once www.kennettnet.co.uk/software/ and see freeware. People will love you for it, and it’s up, tell everyone. Write a press how to make a good program, and how you’ll get a warm fuzzy feeling for helping release and e-mail it to all the big news not to. out the Mac community. However, if you sites, create an entry at versiontracker.com RBD# 1001 12 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 13 Interview by Marc Zeedar

Andrew Barry: The inventor of REALbasic speaks with RBD

Tell us a little of your background. plished dilettante. Numerous projects were course, I wanted to make some improve- How did you get into programming? started, the clever coding completed, and ments while I was at it.... Were you always a Mac fan or did then the project would be dropped since that come later? it was just too uninteresting to bother to Were you wanting CrossBasic to I started programming approximately complete it. I always enjoyed doing things be able to run code 23 years ago at the age of nine on my that pushed the limits. For example, in the or was that even a consideration? father’s TRS-80. It originally came with post-Doom era I was experimenting with Why are there syntax differences 4k of memory. writing texturing engines (of course every- between the languages? Were you My parents purchased me an Amiga when body else was doing the same). I came up ever worried about Microsoft being I was 17 — I finally had a real computer with with a clever technique that did full screen upset at you for making a similar a C compiler — and I taught myself C by texturing 640x480 at 30 fps, which was product? looking at sample programs. I wrote my around 3x faster than anybody else was Full source compatibility wasn’t much first true compiler that year. managing on a 6100/60. It never got of a consideration. I wanted to maintain But the Amiga slowly stagnated — and I developed past the proof of concept. some degree of similarity to the BASIC started learning to program the Mac on a One day I realized that I was just wasting standard, which Visual Basic was by default friend’s machine. I wrote my first program my time. What was the point of writing the — but I wasn’t looking for a pushbutton on my friend’s IIci — a mandelbrot gener- software if it was never completed? I then recompilation. ator — I didn’t know anything about the resolved to carefully pick my next project This is one of the things that I’m not sure Toolbox, but in true Amiga fashion I figured and to follow through, no matter how much I made the right decision about — though out where the screen buffer was located, tedious code had to be written. if I’d aimed for 100% VB compatibility and just drew the calculated mandelbrot As mentioned before, I’ve always had a this would have brought its own range of values directly to the screen. Wheeee! soft spot for development environments, problems. If something is meant to be 100% Once I’d finally managed to afford my and previously I’ve always had some form VB compatible, and somebody buys it on own Mac (the just released IIsi), I started of compiler project, or ideal, that I’d been that basis, they are going to be upset about writing my first larger scale Mac applica- experimenting with. They made perfect anything that gives them trouble. tion with my friends — we released the well sense to me, but it would be a steep learning Contrast this with a product that only received Mac shareware game “Prince of curve for anybody else to pick up. aims to be somewhat similar — since it’s not Destruction.” This was followed up with a Then one day it struck me — people didn’t being marketed/conceptualized as 100% Windows version, since I was also becoming want clever innovative development envi- VB compatible, then people realize they’re a capable Windows programmer. ronments — they wanted something that going to have to do some work. But on the whole, I’ve always enjoyed was approachable and that they could get Perhaps it could have been intentionally developing for the Mac far better than working with as soon as possible. Visual more compatible. developing for Windows — there’s always Basic for the Windows platform was a I did have some worries that Microsoft been far fewer cases of pulling my hair out very handy tool with no real equivalent would chase me with a litigation stick, but and screaming obscenities when writing tool available on the Macintosh platform even though I am not a lawyer the legal Mac programs. The crashing and instability — and I believed there was an entire market precedents didn’t seem to indicate that I was the only real downside, but that’s why segment that wasn’t being served by the would have a problem. On the other hand, I love Mac OS X. available environments. all Microsoft had to do was keep me in court So that evening at my favorite Chinese and bankrupt me that way. I was still single REALbasic was originally called restaurant I resolved to create a develop- back then, and so I wasn’t really risking CrossBasic. What inspired you to ment tool for the Macintosh that was that much by going forward. create it? What were your goals? similar to Visual Basic — to empower a Like many young programmers writing whole new generation of programmers. Of stuff in their spare time, I was an accom-

14 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 15 What was more significant about What are you doing now? etc.). CrossBasic and then REALbasic were CrossBasic: that it was a Mac Putting up with my wife’s remodeling created out of the altruistic need to help version of Visual Basic or that it of our house, getting used to living in people (sounds corny, but true). I wasn’t could cross-compile? Australia again, and changing diapers in it for the money. I am proud of the fact The most important thing about on real babies!!! I have three daughters, that what I did has helped people; not CrossBasic was targeting Mac applications. who are beautiful, fun, and challenging. changed the world, but in some small way The original feature of cross-compiling to Unlike applications there is no way to has made a difference. That’s all I really Java was a ‘cool’ side-project. Two things “fix” them! ;-) wanted. I hope to make that difference led to the Java cross-compilation being I also own my own company in Australia again in the future. dropped. One, Java really sucked. Two, and we do a lot of custom apps and plugins. continuing to support the Java cross- You are welcome to check out our company’s Did you ever imagine REALbasic compilation was limiting the development website http://www.barrysoftware.com for would be as popular as it is today? of CrossBasic. Oh, and the fact that only current news on our projects, or send an I don’t think I really envisaged it — it’s one percent of my user base was interested email to say “Hi.” one thing to imagine and develop the soft- in cross-compiling to Java, and even those ware. It’s another thing to go into a local people were just dabbling. What do you think of the current bookstore and see REALbasic program- In fact, a company approached me to buy version of REALbasic? What are the ming books. the product in the early days — but it was weakest and strongest points of the made clear from the outset that all they product? What do you think of Mac OS X? were interested in was the BASIC cross- I think RB is maturing nicely — though I love it. Once I installed it I’ve never compiling to Java technology and the Mac Imust admit that I only use a small core looked back. It strongly reminds me the targeting would be dropped. This might of the product’s features. I’m really happy first time I installed Windows NT after sound stupid, but I felt strongly about about the progress of the Mac OS X port. having used Windows 3.11 — everything providing Mac programmers with a devel- That is the future of the Macintosh and it’s just becomes “smoother.” I’d played around opment tool and so I didn’t bother to find good to see RB take a strong role. with in the past, but Mac OS X just out how much money they were offering. The strongest point of the product felt like home. has always been the ability to whip up a What led to CrossBasic becoming quick utility program that has a first class How would you compare the Cocoa REALbasic? interface. RB has a lot of nice touches to programming tools (Interface Geoff Perlman approched me because he help the user make sure that their user Builder, etc.) to REALbasic? liked the product. I knew my limitations interface elements are properly aligned, There is a whole mystique about Interface (documentation was scant, and I had no something which can be really fiddly under Builder that dates back to the NeXT days, time for marketing, etc.). There were a Visual Basic. when it was substantially better than the couple of other interested parties. They As far as weak points are concerned, this other types of tools available — but it really seemed more interested in taking over really just applies to the sort of work you’re hasn’t advanced much, and I believe that complete control, and I was not comfort- doing. For my purposes, it really doesn’t the REALbasic user has a far superior able with that. I felt that originally Geoff have any weak points. To different people experience. and I shared a similar vision. I then turned with different requirements, there might be Apart from the tight integration between over the intellectual property and RB was areas that could use further development the UI editor and the code editor, and a created out of CB. — but REALbasic has to cover such a broad cleaner interface, REALbasic also boasts range of features they can’t always make all better support for visually binding objects. You left REAL Software in 1999 of the people happy all of the time. It’s a pity that nobody uses this feature, right as REALbasic was gaining since it can take a lot of the irritation out popularity. Any regrets in leaving? REALbasic’s ease-of-use has of generating internally consistent UIs. (If Leaving REAL was difficult because RB spawned tons of new software on you don’t know what I’m talking about, try was my “baby.” Suffice to say I consider the market. Are there any particular shift-command dragging between a push myself an artist in many ways. That left RB programs that stand out as being button and a listbox). me open to creative differences with the most impressive? new parent. I suppose I regret giving up Alas, I must admit to being insular. I don’t Is there an exciting new product my “baby,” but in the end it has been a real use much software outside CodeWarrior, you’re working on you’d like to learning experience and one that I have REALbasic, Mail, and iTunes (got to have tell us about? Programming via taken valuable lessons from — I won’t make my tunes while I work). But when I do my telepathy, perhaps? those mistakes again. So I have no regrets morning web surf, seeing software that’s For the most part my Australian company in that respect. I do, however, miss the RB been written with RB brings a smile. has kept me busy with a lot of contracting community and having relationships with work (kids are expensive), but I’ve recently the end users. There was something glori- What aspect of REALbasic found enough spare time to develop Bug ously fun about being able to fix end user gives you the biggest sense of Spray — a killer debugging app! It will be problems and giving them a fix in a short accomplishment? ready for a standard release soon. amount of time rather than the extended Knowing that in some small way I Development environments are my process that most bugs go through with accomplished what I had set out to do forte and my love. I would like to move most applications. — make the lives of people easier in some back to that end of things when I am able way. REALbasic accomplished that in more to because I feel that is where my greatest than one way (ease of use, cross compiling, contribution lies. RBD# 1002 14 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 15 Cover Story by Marc Zeedar

The REALbasic Revolution Now anyone can program

s a child, my favorite toy was my Lego this was standard. Big mainframes arrived Aset. I had no brothers or sisters, and empty and dumb: you had to program them growing up overseas, I often had to entertain to make them do something useful. Every myself. I’d spend hours with those Legos, personal computer shipped with a version building entire towns, creating strange BASIC, a fairly ease-to-use programming new vehicles, and inventing mechanical language. devices that worked via a kludgy mixture As computers became more mainstream, of rubberbands and pulleys. I never had however, writing your own software became the fancy sets with battery-operated motors less and less important. The average and special parts; I was forced to make do consumer today has about as much interest with generic pieces. This spurred my imagi- in learning to program their computer as a nation and increased my problem-solving screwdriver owner wants to know how to skills. I had disdain for my U.S.-resident build a house. Programming computers, cousins who always had the special kits like house-building, is complicated and and unique pieces. Where was the chal- time-consuming. lenge in that? At least, it used to be. Years later, I discovered computers. Now REAL Software has created Computers in the early- and mid-eighties REALbasic, the most amazing develop- were a lot like Legos. They could be made ment environment the Macintosh has to do anything you could imagine, with the ever seen. Fans of Apple’s innovative only catch being that you had to figure out HyperCard might protest that statement, how to control them. but HyperCard hasn’t been updated in years It was during those heady days of and never really took advantage of modern discovery that I realized the true beauty capabilities like QuickTime, or supported and power of a computer. A computer With REALbasic, your destination is the Internet. wasn’t a single device like a typewriter only limited by your imagination. or . It was hundreds of devices, Why You Should Care thousands, millions. By simply running a If you’re used to buying shrinkwrapped different program the computer became a program. You need to retouch photo- software packages you might wonder why a different device. What a fantastic graphs? Send Adobe your money. Sure, you’d want to bother learning how to concept! there’s some learning overhead and the program. Isn’t that something better left I fell in love with computers not because program can’t always do exactly what you to the experts? they let me rewrite my stories or because of want, but overall, the major work has been Absolutely not. Programming is some- a cool game or some neat graphics I saw, done for you. thing everyone should learn. Programming but because of their infinite potential. But where’s the challenge in that? What skills will enhance every aspect of your Today’s computers are more like today’s if you need something unique? What if you life. Legos: there are special kits for all sorts of want to do something no one else has ever First, programming your computer to do projects. You need something to organize done? Perhaps your needs are so specialized something it couldn’t do before is one of your videotape collection? Bingo, buy there aren’t any mass-market solutions for the most satisfying things in the world. It’s your situation. like teaching your dog a new trick — you want to demonstrate it to everyone. Except, arc’s dream project is a virtual The Custom Solution of course, a computer program is more MLego set. Just think — no more The solution is simple: write your own obedient (and generally more useful). In missing pieces! software. In the early days of computers

16 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 17 short, programming, despite the ominous known as the freeware Internet Config), ambitious Bill Gates clones. The fact is, connotations of the word, is fun! Stuffit Expander and Dropstuff (based on any time you use your computer you are Second, programming expands your the popular Stuffit compression standard programming it! A computer does nothing mind. The only limits are your imagina- invented by a 15-year-old student), plus without specific instructions. Programming tion. Want to invent a new computer game? , Windowshow, Boomerang, Apple is simply a form of instructing the computer. Have an idea for a simple utility that would Menu Options, Launcher, and dozens of Double-clicking an icon to open a file is a enhance your real estate business? Need form of instruction. to analyze gobs of data you’ve collected In the past decade programming has over the years? Hate how a scheduling The software industry and become much easier. Scripting languages program forces you to work? Write your like AppleScript have made basic program- own software! There are no rules when ultimately the world will be ming techniques commonplace. People who you’re in charge. never thought of themselves as program- Third, learning to program teaches you changed by non-programmers mers have suddenly found themselves to think logically. No longer can you tell writing for the web, or using someone “Organize these files.” Instead Lingo in Director. it’s, “Sort these files alphabetically by last being given the freedom to But scripting systems are always limited. name, putting any duplicates in chrono- They are slow, don’t let you fully access the logical order, and trash any obsolete ones.” program. power of your computer, and rarely provide Precision helps with all forms of commu- you with the tools to create true Macintosh nication — people will understand you others. The arrival of Mac OS X is starting applications with standard interfaces. better, you’ll understand yourself better, this whole process over again. REALbasic is different. It’s revolutionary and your whole life will improve. If you go to any of the popular down- not because it’s easy to use (HyperCard Fourth, you can save yourself time and load sites or open a MacAddict CD you’ll was easy to use) but because it creates money. Let’s use a car analogy. Learning find thousands of free or practically free Mac applications indistinguishable from a little bit about how your car works, how programs. Most of these are programs that programs written in high-level languages to change your own oil, and even how to would never succeed commercially — not like C++ and Pascal. In fact, if you don’t replace a few parts, is invaluable. No longer because of poor quality, but simply because tell, chances are people will never know you are you dependent on the price-gouging they appeal to a tiny, vertical market. How wrote your program in REALbasic! mechanic up the street. No longer do many people need a ciceros-to-centimeter Because of REALbasic, thousands of you shudder when your car makes that calculator or a soccer statistics database? people who never thought of themselves strange pinging sound when going up Those that do, of course, are incredibly as programmers are programming. hill, wondering if you’re in for another grateful. But if it weren’t for hobbyists or Traditional programmers are embracing $1,000 repair bill. Learning programming people donating their spare time, many of RB because of its power and speedy is the same thing: you’re more confident those programs would never be written. development. Teachers are using it as an in your computer knowledge, less likely to Sixth, programming can make you educational tool. Corporations are writing waste money on consultants or expensive money! Perhaps not much money, unless utilities in-house instead of hiring expen- one-shot programs. Sure, there’s an initial you start your own business and go to sive consultants. High school students are investment of time and energy, but the pay- work full-time, but many people who starting their own shareware companies, off is life-long. originally wrote a program just for them- creating useful and innovative solutions Fifth, your software enhances the selves discovered others were willing to to rare problems. Scientists, graphic community. How much of your computer pay $10 or $20 for it. Get a few hundred designers, artists, musicians, and others experience is made more positive by caring, users and we’re talking about some serious in non-programming fields are using generous people who donated their time mad money. Programming skills could lead REALbasic in creative and unexpected and skills to make your life easier? Even to new responsibilities at work or even a ways. if you’ve never installed a shareware or new career! Who knows where this will lead? freeware program in your life, the Mac Perhaps the next Tetris will be created by operating system is full of ideas and Get Started Now someone fooling around with REALbasic. technology donated to the Mac community. Don’t think that programming’s some- Perhaps interface innovations first seen in There’s the Internet control panel (formerly thing esoteric and complex and only for REALbasic programs will be adopted by Apple or Microsoft, revolutionizing the way we use our computers. I believe the software industry and ultimately the world will be changed by non-programmers being given the freedom to program. Instead of suffering silently at the mercy of monolithic corporations who tell us “This is the way it is!” we can take the helm and set our own destination. After all, we’re the users — we know how things should work, just not how to make them that way. Until now. Figure 1: The logo for Z-Write. Doesn’t it make sense that a writer, not a Welcome to the Revolution. Welcome programmer, should write a word processor? to the future. RBD# 1003 16 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 17 Feature by Joe Strout

Three Ways to Animate Choosing the best animation technique for your program

early every software developer has need a mask; we’ll put that into the same display a bunch of stars, but apart from Na need to generate some animated source picture too. the rocket and the smoke puffs, it’s graphics sooner or later. Animation is the The three source pictures are shown completely done. bread and butter of game developers, but it in Figure 1. If you’re creating your own The next step is drawing a rocket. can be used effectively in many other places images in order to follow along at home, Thinking ahead a bit, we’re going to have as well, from an eye-catching About Box to be sure to use the same names and sizes a timer or a loop that periodically updates a custom progress indicator. REALbasic or else you’ll have to make some adjust- the display. So make an “UpdateCanvas” provides several different ways to produce ments to the code. subroutine within Window1. That will animation, each with pros and cons. All three solutions to this problem will have code to grab the size of the rocket In this article, we’ll pose a moderately involve these pictures, and the easiest way and compute its X (horizontal) position simple animation problem: an image of to access them is to simply drag them into within the Canvas: a rocket flying over a starry background, your project and refer to them by name. trailing little puffs of smoke. Then we’ll So start with the default new project and Dim x, w, h As Integer solve this in three different ways: using add the pictures. The rocket image is a simple Canvas, using a SpriteSurface, designed for white areas to appear trans- x = CanvasDisplay.width / 2 and using an Rb3DSpace. By the end, parent, so select RocketImg in the project w = RocketImg.width you should be well-equipped to use the window and in the Properties window set

right tool for any animation job. Transparent to 1. h = RocketImg.height The downloadable project associated and then draw the rocket into the Canvas’ The Problem with this article will demonstrate all three graphics property: For the sake of this article, assume you techniques in one application, but to keep it need to make a rocket fly over a background simple you might want to use three separate CanvasDisplay.graphics.DrawPicture RocketImg, of stars. Every now and then the rocket projects. In any case, your project window x, 200, w, h, 0, 0, w, h emits a little puff of smoke which should should look like that in Figure 2. move in the direction opposite that of the Of course, this method won’t do any rocket, expand a bit, and then disappear. If The Canvas Solution good if we don’t call it. So let’s go ahead possible, the smoke puffs should be trans- Let’s first tackle this problem by using and add that Timer. Drag a Timer control lucent (because translucency is cool). that Swiss Army knife of all things graph- onto your window, and via the Properties So we’ll be working with basically three ical, the Canvas. A Canvas is basically just window, set its Period to 10 (i.e. 10 milli- images: the rocket itself, the background, a rectangular area of a window where we seconds, which is about as fast as a Timer and the smoke puff. The smoke puff actu- can draw things, and that’s just what we can go). Double-click it, and in its Action ally requires a series of images, so we can want to do here. event type: make it expand and grow more diffuse. Start by dragging a Canvas from the To reduce the number of files we have to toolbar onto your window, and via the UpdateCanvas work with, we’ll combine all the smoke puff Properties window, set its Backdrop to images into one picture. Since we want BackgroundImg. You could set the width Now run the program again. We now the smoke puffs to be translucent they also and height to 400 here or do it in code (the have a rocket drawn against a field of stars. sample project does the latter, so we can That’s definite progress, but the article see all three solutions while working in the title says “animation,” so we’d better get IDE). In either case, the Canvas should it moving. oe Strout is a senior software now look like a starry square. Create a new property of the window, J engineer at REAL Software, and At this point, I’d be tempted to hit “mShipY as Integer.” This will be the Y likes to dabble in making games with command-R to run the program. It (vertical) position of the ship within the REALbasic. works! It doesn’t do anything except display. Now return to the UpdateCanvas

18 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 19 updating the ship position, insert this code:

// Consider adding a smoke puff if Rnd < 0.1 then mPuffAge.Append 0 mPuffY.Append mShipY + h - 24 end if This code has a 10% chance of generating a puff of smoke on each frame. When it does add a puff, it’s given an initial age of 0 and a position that is related to the ship position. Next, we’ll need code to update and draw the smoke puffs; insert this right before we draw the ship:

Figure 1: Images needed for the flying-rocket demonstration. // Update and draw the smoke puffs for i = UBound(mPuffY) downTo 0 puffNum = 3 - mPuffAge(i) / 5 if puffNum < 0 then code. The DrawPicture call that draws the little pictures. So start by declaring a new mPuffY.Remove i rocket needs to be replaced with a few lines property, “mPuffPics(3) As Picture” (allo- mPuffAge.Remove i that erase the old rocket (by drawing a cating space for four pictures, numbered section of the background where the rocket 0, 1, 2, and 3). Then add code like the else used to be), update the rocket position, and following to the window’s Open event: mPuffAge(i) = mPuffAge(i) + 1 draw the new rocket, like so: mPuffY(i) = mPuffY(i) + 3 Dim i As Integer g.DrawPicture mPuffPics(puffNum), x + 8, Dim g As Graphics mPuffY(i) // prepare the smoke puffs end if g = CanvasDisplay.graphics for i = 0 to 3 next // Erase the ship at the old position mPuffPics(i) = NewPicture(32, 32, 32) This code appears a little complex, but g.DrawPicture BackgroundImg, x, mShipY, w, h, mPuffPics(i).graphics.DrawPicture PuffImg, x, mShipY, w, h 0, 0, 32, 32, i*32, 0, 32, 32 it’s not doing too much. First we find the mPuffPics(i).mask.graphics.DrawPicture puff image number (puffNum) based on // Update the ship position PuffImg, 0, 0, 32, 32, i*32, 32, 32, 32 the puff age, dividing by five so that the image changes every five frames. The mShipY = mShipY - 4 next image number is going to be 3 for brand if mShipY < -h then This copies square 32-by-32 pixel new puffs, and go down to 0 for old puffs; mShipY = CanvasDisplay.height sections of the original PuffImg into four if it gets beyond 0, then we remove the puff end if separate images that include masks, so entirely. Otherwise, we increment the puff they’ll be translucent when drawn. age, move the puff downward (+3 in Y), // Draw the ship in its new position Now we have the images we want to and draw the chosen puff image. g.DrawPicture RocketImg, x, mShipY, w, h, 0, draw, but we need some more properties If you run the project at this point, you’ll 0, w, h to keep track of where to draw them and see pretty dense smoke as we’ve neglected what state they’re in. So declare two more to erase the smoke puffs once they’re drawn. Note that to avoid typing properties: “mPuffY(-1) As Integer,” and “CanvasDisplay.graphics” multiple times, “mPuffAge(-1) As Integer.” Both of these I’ve also declared a new local variable “g” are arrays which are initially empty (upper and set it to mean the same thing. This bound of -1). The first, mPuffY, will be used will become even more convenient as our to keep track of the Y (vertical) position of animation gets more complex. each puff of smoke. The second, mPuffAge, The program at this point should display will keep track of how long each puff has a rocket that flies up the screen, and when been around so we can make it change it disappears off the top, it reappears at the shape and eventually disappear as it ages. bottom. The problem is nearly solved; all We’ll keep these two arrays in parallel, so that’s left is the puffs of smoke. that mPuffAge(i) is always the age of the The smoke puffs require a little more puff to be drawn at mPuffY(i). bookkeeping because there may be several Now we can add a smoke puff by of them, and they change shape as well appending to these arrays. In the Figure 2: Sample project window, as move. We also need to carve up that UpdateCanvas method, right before showing elements needed for this PuffImg composite picture into separate project.

18 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 19 So finally, we need to add a bit of erasing Then, in the UpdateCanvas method, The SpriteSurface Solution code right after erasing the ship: we want to draw to this picture instead of The SpriteSurface is a control specifically to the Canvas itself. I added a checkbox designed for doing 2D animation. As such, // Erase the smoke puffs called “DoubleBufChk” to the demo project it’s often the first (and sometimes the only) for i = Ubound(mPuffY) downTo 0 so that double-buffering could be toggled approach many RB users think of when g.DrawPicture BackgroundImg, x+8, mPuffY(i), at runtime; the graphics-selection code considering an animation problem. As 32, 32, x+8, mPuffY(i), 32, 32 looks like this: we’ll see in this section, the SpriteSurface next imposes some limitations on what you can if DoubleBufChk.value then do, but within those limitations the anima- The logic here is exactly the same as for g = mCanvasBuffer.graphics tion is considerably easier to code. erasing the ship, except that we’re doing it else The initial set-up is very similar to that in a loop to make sure we get all the smoke g = CanvasDisplay.graphics for the Canvas approach. Start by dragging puffs. (Note that for this particular case a SpriteSurface onto the window from the we could instead erase the entire column end if controls palette. Name it SpriteDisplay, of ship and puffs with a single DrawPicture Finally, after all the drawing is done, we and set its background to BackgroundImg — this may or may not be faster than erasing need to copy from the buffer to the Canvas. using the Properties window. Notice that each shape individually, depending on how This will be rather slow if we copy the whole unlike the Canvas, the background is not many shapes there are and how much they thing, so it’s important to copy a smaller drawn while in the IDE; as soon as you overlap). region if possible. This particular anima- run your project you should see the field At this point, you should have a rocket tion takes place in a narrow column that of stars. that flies over a starry field and emits little encloses the rocket and smoke puffs, so We’ll need the same preparation of animated puffs of smoke. But you may we’ll copy just that: mPuffPics in the Open event (although notice that in addition to flying and puffing, in this case you could skip building the your display is doing a fair bit of flickering, if DoubleBufChk.value then mask since it will be ignored). In addition, too — at least, if you’re not running in OS CanvasDisplay.graphics.DrawPicture we need to create a sprite to represent the X. That’s because we’re erasing and then mCanvasBuffer, x, 0, w, 400, x, 0, w, 400 ship, as shown below. redrawing right on the screen, where end if everybody can see it (except in OS X, // prepare the smoke puffs which automatically buffers all drawing). That’s pretty much it for Canvas anima- for i = 0 to 3 This flicker can be eliminated through a tion. There is one remaining snag, which mPuffPics(i) = NewPicture(32, 32, 32) process called “double buffering." affects you only if you’re running on OS mPuffPics(i).graphics.DrawPicture PuffImg, Double buffering means that you do X and animating directly from a program 0, 0, 32, 32, i*32, 0, 32, 32 your erasing and redrawing in an off- loop rather than from a timer. Recall that next screen picture first where it can’t be seen; OS X automatically buffers all drawing for then you copy this picture to the screen. you; when you think you’re drawing to the // initialize the sprite display This eliminates flicker because the screen screen you’re actually drawing to an invis- mShipSprite = SpriteDisplay.NewSprite(RocketImg never appears in the “erased” state. Start by ible window buffer. The system normally , 200, 200) declaring a new property, “mCanvasBuffer “flushes” this buffer to the screen during As Picture.” In the Open event we’ll need moments, such as in between Timer Here, “mShipSprite” is a new window to initialize this to have the same size and firings. But if you’re animating from a tight property of type Sprite. The last line creates background as the display: loop there’s no idling until the loop is over. a sprite at position X=200, Y=200, using So you may not see the animation at all; RocketImg as its shape. Now if you run // initialize the canvas display instead, you’d only see the last frame. again, you should see a rocket stationary mShipY = 200 To fix this, you might try to call against a field of stars. mCanvasBuffer = NewPicture(400, 400, 32) CanvasDisplay.Refresh. But the Refresh To make it animate we’ll again use a mCanvasBuffer.graphics.DrawPicture method of any control tells it to erase Timer, but have that Timer call a method BackgroundImg, 0, 0 and redraw itself in its entirety, which called “UpdateSprites.” Initially, we’ll have is exactly what we don’t want to happen that method simply move the ship: here. So instead, we can use Declare statements to access the GetWindowPort // Move the ship and QDFlushPortBuffer function calls in mShipSprite.Y = mShipSprite.Y - 4 CarbonLib. These tell the system to flush if mShipSprite.Y < -RocketImg.height then the window buffer to the screen immedi- mShipSprite.Y = SpriteDisplay.Height ately, instead of waiting for some later end if opportunity. Note that the call works but

does nothing if running under Carbon in OS 8/9, so it’s safe to call whenever // Update the display TargetCarbon is true. SpriteDisplay.Update Listing 1 shows the UpdateCanvas method in its entirety. You’ll also find this Run the program now and the ship in the demo project on the RB Developer should be moving smoothly over the starry Figure 3: The rocket, flying in an web site. background. That’s it — no erasing, no Rb3DSpace. buffering, no flushing. Just change the X

20 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 21 or Y property of a sprite, call Update on mPuffSprites.Append sp Code Listing #1: the display, and repeat; sprite animation end if Window1.UpdateCanvas is as simple as that. Sub UpdateCanvas() Let’s finish the job by adding smoke Running at this point should produce Dim g As Graphics puffs. First, we must note that the puffs that periodically appear behind the SpriteSurface control does not support ship, but don’t move or disappear. To Dim x, w, h As Integer masks. Sprites are transparent where the animate the puffs we’ll use a loop which Dim puffNum, i As Integer image pixels are white, and opaque where again is very similar to that used by the the image pixels are non-white; the mask Canvas. The main difference is that we x = CanvasDisplay.width / 2 is completely ignored. This means our now need to update the mPuffSprites array w = RocketImg.width smoke puffs are going to look more like as well as mPuffAge. h = RocketImg.height solid balls of cotton than diffuse clouds // Update the smoke puffs if DoubleBufChk.value then of smoke. Having accepted that, let’s get to the code. for i = UBound(mPuffSprites) downTo 0 g = mCanvasBuffer.graphics We’ll use the same concept of puff “age” mPuffAge(i) = mPuffAge(i) + 1 else as we used for the Canvas. So creating a mPuffSprites(i).Y = mPuffSprites(i).Y + 3 g = CanvasDisplay.graphics new smoke puff involves appending a “zero” puffNum = 3 - mPuffAge(i) / 5 end if to an array of puff ages, and creating a new if mPuffAge(i) mod 5 = 0 then sprite on a parallel array of sprites (which if puffNum < 0 then // Erase the ship at the old position we’ll imaginatively call “mPuffSprites"). In mPuffSprites(i).Close g.DrawPicture BackgroundImg, x, mShipY, addition, we want to set the priority of the w, h, x, mShipY, w, h puff sprites to -1; this causes them to be mPuffSprites.Remove i drawn behind the ship, which by default has mPuffAge.Remove i // Erase the smoke puffs a priority of 0. The code to be added to the else for i = Ubound(mPuffY) downTo 0 UpdateSprites method looks like this: mPuffSprites(i).image = mPuffPics(puffNum) g.DrawPicture BackgroundImg, x+8, // Consider adding a smoke puff mPuffY(i), 32, 32, x+8, mPuffY(i), end if 32, 32 if Rnd < 0.1 then end if next mPuffAge.Append 0 next sp = SpriteDisplay.NewSprite(mPuffPics(3), mShipSprite.x+8, mShipSprite.Y + 24) // Consider adding a smoke puff sp.priority = -1 So, on every frame we move each puff if Rnd < 0.1 then down 3 pixels and increment the age. mPuffAge.Append 0 On every fifth frame we pick a different mPuffY.Append mShipY + h - 24 // If double-buffering, copy from the buffer to the screen shape, or if we’ve run out of shapes, we end if if DoubleBufChk.value then delete the puff by closing the sprite and removing the corresponding entries from // If possible, copy only the part // Update the ship position that has changed — the two arrays. mShipY = mShipY - 4 // though in a less trivial animation, And that’s all there is for this solution. The complete UpdateSprites method is if mShipY < -h then this can be difficult: shown in Listing 2. mShipY = CanvasDisplay.height CanvasDisplay.graphics.DrawPicture mCanvasBuffer, x, 0, w, 400, x, 0, end if w, 400 The Rb3D Solution The third control we’ll consider for this // Update and draw the smoke puffs // If necessary, copy everything — problem is the Rb3DSpace. This control is this always works, for i = UBound(mPuffY) downTo 0 a view onto a virtual 3D world. “But wait,” // but it can be quite a bit slower: puffNum = 3 - mPuffAge(i) / 5 I can hear the reader saying, “This is a 2D ’CanvasDisplay.graphics.DrawPicture problem, so of what use is a 3D control?” if puffNum < 0 then mCanvasBuffer, 0, 0 As it happens, an Rb3DSpace can mPuffY.Remove i end if be set up to do very nice 2D sprite-like mPuffAge.Remove i graphics. The trick is to move the virtual else // Finally, in Carbon (OS X), we need to camera very far away from the scene, and mPuffAge(i) = mPuffAge(i) + 1 flush the port buffer set the field of view to a very narrow angle. mPuffY(i) = mPuffY(i) + 3 #if TargetCarbon This is equivalent to looking across town g.DrawPicture mPuffPics(puffNum), Declare Function GetWindowPort Lib with a telescope, and under these condi- x+8, mPuffY(i) "CarbonLib" (window as WindowPtr) tions there is very little perspective effect. as Integer end if This provides a nice undistorted view for Declare Sub QDFlushPortBuffer Lib displaying pictures — but as a bonus, we next "CarbonLib" (port as Integer, region as Integer) also get to treat them as 3D objects for special effects like scaling or rotation. // Draw the ship in its new position QDFlushPortBuffer GetWindowPort(self), 0 Let’s start by dragging an Rb3DSpace g.DrawPicture RocketImg, x, mShipY, w, h, 0, 0, w, h #endif control from the controls palette onto the End Sub window. Name it Rb3DDisplay and set

20 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 21 the SkyColor to a deep blue, matching If you run your application at this point, the corresponding puff picture. Note the background color of the star field. you should have a rocket in the middle of that we don’t pass mPuffPics(i) directly Also set the FieldOfView to 10 (meaning the screen against a field of stars. Not very to AddShapePictureWithMask. The mask ten degrees), and prepare the lighting by exciting yet, but you know that under the used with Rb3D acts a bit differently than setting AmbientLight to 100 and FloodLight hood that’s a 3D rendering, and that lets us it does in other contexts; the color pixels to 0. do some things that would be very difficult have to be pre-multiplied by the mask. To In the Open event we’ll finish preparing with the other approaches. For starters, do that, we draw the image on top of a black the Rb3DSpace as follows: let’s make the rocket fly in a circle instead background, and then pass this composite of a straight line. image on to Rb3D. Dim degrees, angle, distance As Double Start by adding a new property, Finally, we need some additional code Dim bg As Object3D “mShipAngle as Double.” This will hold in the UpdateRb3D routine to add, move, the angle the ship is currently facing, which and delete the puffs. I’ll just point out a if Rb3DDisplay.objects <> nil then also corresponds to the ship’s position few highlights and refer to Listing 3 for the degrees = 0.0174532925 // (radians per along its circular path. Then make an degree) UpdateRb3D subroutine, with code like angle = Rb3DDisplay.fieldOfView * degrees * the following: Code Listing #2: 0.5 Window1.UpdateSprites Dim radius As Double distance = 200 / sin(angle) Sub UpdateSprites()

Rb3DDisplay.camera.position.Z = distance Dim sp As Sprite radius = 100.0 Rb3DDisplay.hither = distance - 10 Dim i, puffNum As Integer mShipObj.position.X = radius * cos(mShipAngle) Rb3DDisplay.yon = distance + 10 mShipObj.position.Y = radius * sin(mShipAngle) // Move the ship mShipObj = New Object3D mShipObj.orientation.SetRotateAboutAxis 0, 0, 1, mShipAngle mShipSprite.Y = mShipSprite.Y - 4 mShipObj.AddShapePicture RocketImg, 1.0 if mShipSprite.Y < -RocketImg.height then Rb3DDisplay.objects.append mShipObj Rb3DDisplay.Update mShipSprite.Y = SpriteDisplay.Height

end if bg = New Object3D mShipAngle = mShipAngle + 0.05 bg.AddShapePicture BackgroundImg, 1.0 // Consider adding a smoke puff bg.position.Z = -1.0 This simply does a bit of trigonom- if Rnd < 0.1 then Rb3DDisplay.objects.append bg etry to find the ship position, and uses mPuffAge.Append 0 end if SetRotateAboutAxis to rotate the ship. sp = SpriteDisplay.NewSprite(mPuffPic We then increment the ship angle by s(3), mShipSprite.x+8, mShipSprite.Y + 24) This requires a new property, “mShipObj 0.05 radians on each frame, which drives sp.priority = -1 As Object3D.” Note that we check to make the animation. Run your app now and sure Rb3DDisplay.objects is non-nil before you should see the ship flying smoothly mPuffSprites.Append sp attempting to use any 3D methods. This in a circle — a feat that would leave the end if is important, because the Rb3D classes SpriteSurface or Canvas dumbfounded. require a system library (Quesa or Let’s complete the task by adding some // Update the smoke puffs QuickDraw 3D) to be installed. If it is not smoke puffs. We’ll have to keep track of a for i = UBound(mPuffSprites) downTo 0 installed most 3D methods will fail and bit more data in this case because each puff mPuffAge(i) = mPuffAge(i) + 1 most properties of the Rb3DSpace will can be moving in a different direction now, mPuffSprites(i).Y = mPuffSprites(i).Y be nil. So a check like the above serves to rather than all the puffs moving downward. + 3 handle that case gracefully. Also, we’ll want to prepare a prototype 3D puffNum = 3 - mPuffAge(i) / 5 The calculations after the check deter- object representing a smoke puff, which if mPuffAge(i) mod 5 = 0 then mine how far away the camera should be we can then clone for each new puff we in order to make one unit of 3D space need to display. So add two more proper- if puffNum < 0 then come out to one pixel on the screen. The ties, “mPuffPrototype As Object3D” and mPuffSprites(i).Close camera is then positioned accordingly, and “mPuffVelocity(-1) As Vector3D.” Now add mPuffSprites.Remove i the Hither and Yon values are set to bracket some code to the Open event as follows: mPuffAge.Remove i that distance (see the RB language refer- else mPuffPrototype = New Object3D ence for more info on these properties). mPuffSprites(i).image = Next, we create the ship and the back- for i = 0 to 3 mPuffPics(puffNum) ground using the AddShapePicture method p = NewPicture(32, 32, 32) end if to convert our 2D pictures into objects in p.graphics.FillRect 0, 0, 32, 32 end if a 3D world. The final parameter to this p.graphics.DrawPicture mPuffPics(i), 0, 0 next call is the scaling factor — by specifying mPuffPrototype.AddShapePictureWithMask p, 1.0, we’re making one pixel in the picture mPuffPics(i).mask, 1.0 correspond to one unit of distance in the // Update the display 3D space; a great convenience for this sort next SpriteDisplay.Update of animation. This initializes the puff prototype with four different shapes, each created from End Sub

22 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 23 full code. First, we get a puff’s initial velocity by transforming a vector by the ship’s orientation: Code Listing #3: Window1.UpdateRb3D Sub UpdateRb3D() v = New Vector3D // Let’s make the ship fly in a circle (because we can!). v.y = -3.0 Dim radius As Double v = mShipObj.orientation.Transform(v) Dim i, puffNum As Integer mPuffVelocity.Append v Dim grp As Group3D We start out with a velocity of -3 in Y, which would move the Dim pos, v As Vector3D puff 3 units downward per frame. But then we transform this by Dim obj As Object3D the ship’s orientation so that this direction rotates to match the ship. We could have instead done some trigonometry like we did // Move the ship for the ship position, but this approach is simpler. radius = 100.0 Next, notice the line “obj.position.z = -0.1” where we create the mShipObj.position.X = radius * cos(mShipAngle) smoke puff. There is no notion of “priority” in a 3D rendering; instead, if you want one object to appear behind another, you mShipObj.position.Y = radius * sin(mShipAngle) move it further away. Our camera position has a positive Z, and mShipObj.orientation.SetRotateAboutAxis 0, 0, 1, mShipAngle the ship is at Z = 0, so by putting the smoke puffs at Z = -0.1 we ensure that they’re drawn behind the ship. // Consider adding a puff Finally, it’s worth pointing out how the if Rnd < 0.1 then puff animation works. It’s so simple that mPuffAge.Append 0 you might have missed it: [No method] v = New Vector3D v.y = -3.0 obj.shape = puffNum is clearly v = mShipObj.orientation.Transform(v) This line tells Rb3D that of all the superior for mPuffVelocity.Append v shapes that have been added to this object, obj = mPuffPrototype.Clone “puffNum” (a number from 0 to 3 in our all situations; obj.position.x = mShipObj.position.x case) is the one that should be displayed. obj.position.y = mShipObj.position.y This is different from the SpriteSurface, you’ll want obj.position.z = -0.1 where you attach a new image, or the to select the Canvas, where you decide what to draw Rb3DDisplay.objects.Append obj at drawing time. With Rb3D, you attach right approach end if all the images (shapes) you might need to the object when you’re setting it up and for each job. // Update the puffs then just flip between them by assigning // (which we’ll assume are all objects in the Rb3DSpace from 2 on) to the Shape property. for i = UBound(mPuffVelocity) downTo 0 With the code as shown in Listing 3, you should now have a puffNum = 3 - mPuffAge(i) / 5 rocket that travels in a circle emitting translucent puffs of smoke if puffNum < 0 then that move and dissipate believably, as in Figure 3. mPuffVelocity.Remove i Which to Use? mPuffAge.Remove i We’ve explored the three main approaches to animation in Rb3DDisplay.objects.Remove(i+2) REALbasic. None of them is clearly superior for all situations; else you’ll want to select the right approach for each job. Here are obj = Rb3DDisplay.objects.Item(i+2) some of the considerations to keep in mind. obj.shape = puffNum First, simplicity of code. The SpriteSurface generally requires v = mPuffVelocity(i) the least code to make things move around over a background without flicker. The Rb3DSpace generally requires a bit more pos = obj.position set-up, and a Canvas requires more work to make smooth anima- pos.x = pos.x + v.x tion. The Canvas also requires, under OS X, a Declare to force pos.y = pos.y + v.y the window to update; the SpriteSurface and Rb3DSpace handle pos.z = pos.z + v.z that automatically. mPuffAge(i) = mPuffAge(i) + 1 Next, consider features. The Canvas and Rb3DSpace can both end if do scaling and translucency; an Rb3DSpace can also do rotation. A next SpriteSurface supports none of these. However, we didn’t consider collision detection in this article. SpriteSurfaces have easy pixel- level collision detection; with a Canvas or Rb3DSpace you’ll have // Update the display and ship angle to detect your own collisions if you need them. Rb3DDisplay.Update Performance is harder to quantify because it varies a great deal mShipAngle = mShipAngle + 0.05 with the details of the task. Canvas animations can outperform End Sub other approaches when the area that changes on each frame is

Continued on page 27

22 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 23 Feature by Matt Neuburg

Expressions of Delight REALbasic’s regex class

he Regex class, along with the s = // some text with HTML tags Example 1: Regex removal TRegexMatch, RegexOptions, and of HTML tag RegexException classes, is the gateway starting = inStr(s, "<") dim s as string, r as regex to REALbasic’s implementation of regular if starting > 0 then r = new regex expressions. Regular expressions are a way ending = inStr(starting, s, ">") s = // some text with HTML tags of expressing a textual find or find-and- if ending > 0 then replace that’s too complicated, or too vague, r.options.greedy = false // disable greediness leftPart = mid(s, 1, starting - 1) for a function like InStr or Replace. To see r.searchPattern = "<.*>" rightPart = mid(s, ending + 1) what I mean, let’s take an example. r.replacementPattern = "" Suppose you’ve got a string representing s = leftPart + rightPart s = r.replace(s) some HTML, and you want to remove all end the HTML markup from it. An HTML tag end I hope the cleanliness and elegance of starts with a left angle-bracket and ends that example feels sufficiently compel- with a right angle-bracket; the tag consists That’s not horrible — I purposely chose a ling that you’re encouraged to want to of both angle-brackets, and everything in simple example to start with — but it’s not learn more — because, make no mistake, between, like this: “”. The trouble very pleasant either. The code is fairly illeg- there is a learning curve to using regular is, of course, that you don’t know in ible, and it feels like we’re working much too expressions. The good news, though, is that advance what “everything in between” hard. The notion “a left angle-bracket, the regular expression syntax has achieved near consists of. following right angle-bracket, and every- universality in the computer world, and So how would you find and remove an thing in between” seems simple enough. REALbasic’s implementation of regular HTML tag using just InStr? You’d have Yet we can’t express it with InStr, so we’re expressions is based on a widely used to take a piecemeal approach. First you’d having to implement it as a succession of freeware code library called PCRE (Perl- have to find a left angle-bracket, and finds plus a sort of brute-force replacement, compatible regular expressions). Once remember where it is. Then you’d look for all of which is ugly, error-prone, tedious, you’ve learned how to use regular expres- a right angle-bracket that comes after the and not very general; imagine having to sions in REALbasic, you’ve also learned left angle-bracket, and remember where it extend this into a loop where we remove how to use them in BBEdit, JavaScript, Perl, is. Then you’d have to break up the string every HTML tag! Not much fun. Using Python, and PHP; regular expressions are into three pieces — what precedes the tag, regular expression syntax, however, we can also used (with a slightly different syntax) in the tag itself, and what follows the tag express it, very simply, like this: <.*> Nisus Writer and Microsoft Word. So they — and reassemble it without the middle Regular expression syntax uses some are certainly worth learning about. piece, thus deleting the tag. Here’s some symbolism that may at first be strange to This article can’t teach you all about actual code. you. But you can probably guess what’s regular expressions; the subject is huge. I going on in this particular expression. strongly recommend Jeffrey Friedl’s book, dim s, leftPart, rightPart as string The angle-brackets mean angle-brackets, Mastering Regular Expressions from dim starting, ending as integer and the dot-asterisk means “everything in O’Reilly and Associates, and REALbasic’s between.” That’s all there is to it. To demon- online help for Regex provides a complete strate this expression in action, here’s some guide to the syntactical details. What I’ll do actual code for removing an HTML tag from here is introduce you to regular expressions, a string using the Regex class. and explain how you use them through REALbasic’s Regex-related classes. att Neuburg first learned about M regular expressions while using Search Expression the Nisus word processor in 1990, and There are two kinds of regular expres- hasn’t had a good night’s sleep since. sions: the search expression, describing

24 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 25 the text you want to look for; and the is still rather tedious when a character set is You consult this instance to learn about replace expression, describing the text (if very frequently used, so the syntax defines the results of the find. If the find failed, any) that will replace the found text. The some character sets for you in advance. For the RegexMatch instance will be nil. If search expression is far more powerful example, instead of [0-9] you can just say the find succeeded, the RegexMatch’s and, since you’ll always need one, more \d and instead of [0-9a-zA-Z_] you can SubexpressionString(0) property will important. say \w. And a dot (.) means any character contain the matched substring, and its Before we start, I have to tell you the at all. Now let’s turn to vague quantities of SubexpressionStart(0) property will basic rule of how regular expression syntax characters. To specify that a character can contain the index (zero-based again) of works. In a regular expression, certain char- occur a vague number of times, you put a the first character of the matched substring acters, such as the dot and the asterisk in metacharacter after the character that is within the original string. You’re probably Example 1, have special meaning. The to be repeated. For example, a plus sign wondering what the “(0)” means here, basic rule of regular expressions is that if (+) means that the preceding character but don’t worry about it for now; just a character has no special meaning, it just must appear at least once but can occur trust me. represents itself in the normal way, like more times than that, in succession. Note To illustrate, here’s a code snippet that the angle brackets in Example 1. If a char- that this doesn’t mean that the very same counts the number of runs of vowels in a acter does have special meaning and you character has to appear several times in string. We do this by finding vowel runs in want to use it to represent itself, without succession, because the character to be successive iterations of a loop until the find that special meaning, you “escape” it by repeated might be a vague character. For fails. Each time through the loop, we use the putting a backslash (\) in front of it; for example, [aeiou]+ means any stretch of start position and length of the previously example, \* means an ordinary asterisk. any vowels, and will find the “eau” in “beau- matched substring to determine where to Also, if a character does not have special tiful.” A question mark (?) means that the start the next search. meaning, you can sometimes give it special preceding character may appear once or meaning by putting a backslash in front of perhaps not at all, and an asterisk (*) means Example 2: Successive searches it. For example, r is just a normal “r”, but that the preceding character may appear dim s as string, r as regex, m as regexmatch \r means a return character. I know this once, not at all, or any number of times in dim i, count as integer sounds confusing, but it will be clearer succession. Now you can understand how when we look at some more examples, we found an HTML tag with the expression r = new regex and if I don’t tell you about it up front we <.*> earlier; it means a left angle-bracket, can’t get started at all. a right angle-bracket, and any characters s = “beautification” The best way to approach an under- in any quantity between them. // has 5 vowel runs: “eau”, “i”, “i”, “a”, “io” standing of regular expressions is to When specifying vague quantities, you consider that when we use InStr, every must be concerned about “greediness.” r.searchPattern = "[aeiou]+" character in the search expression repre- A greedy search is one that matches the sents an exact match, whereas the power largest stretch it can find. Recall that in do of a regular search expression lies largely Example 1, we disabled greediness before m = r.search(s,i) in its ability to be deliberately vague about starting the search. To see why, imagine what we’re looking for. There are two main searching a string with two HTML tags in if m <> nil then kinds of things you get to be vague about: it. A greedy search finds everything from count = count + 1 what individual characters to look for, and the start of the first HTML tag to the end i = m.subExpressionStart(0) how many characters to look for. We’ll take of the second HTML tag. A non-greedy i = i + len(m.subExpressionString(0)) these in turn. search finds just the first HTML tag, as end We begin with vague individual charac- desired. loop until m = nil ters. What we want here is to make a single character in the search expression stand Performing the Search for more than one possible character to To perform a search you need three msgbox str(count) look for. To do so, we list the acceptable things: a string to look inside, a regular // result is 5, the right answer possibilities inside square brackets. This search expression, and an instance of the is called a character set. For example, Regex class. You hand the Regex instance It seems wasteful to have to supply the [aeiou] means a single character that the search expression as its SearchPattern search string as a parameter to the Search might be a or e or i or o or u. This nota- property, and then send the Regex instance message every time through the loop when tion would get tedious if there were lots of the Search message. If you provide just that string isn’t changing. To save us from acceptable possibilities, so you can invert one parameter for the Search message, that having to do this, the Regex class permits a it by making the first character inside the parameter is the string to look inside, and different way of using the Search message. square brackets a caret; now you’ve got the search will start at the first character of Having performed the search once, so that a list of all the unacceptable possibilities. the string. If you provide two parameters, the Regex instance knows what the search So, [^aeiou] means any single character the second parameter is the index of the string is, we set the starting position for that isn’t a or e or i or o or u. character where the search should start. the next search using the Regex instance’s Also, a range of characters, using ASCII The character indexing is zero-based! This SearchStartPosition property and send it order, can be specified by putting a hyphen contrasts unfortunately with InStr, where the Search message with no parameters between the first and last characters of the character indexing is one-based. at all. We can rewrite Example 2 to use range; so [0-9] means any numeric digit, The value returned when you send a this syntax. and [0-9A-F] means any character that Regex instance the Search message is might be used as a hexadecimal digit. This an instance of the RegexMatch class.

24 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 25 Example 3: Successive searches, Example 4: Subexpression Example 5: Search-and-replace alternate syntax dim r as regex, m as regexMatch dim r as regex, s as string dim s as string, r as regex, m as regexmatch r = new regex r = new regex dim i, count as integer r.searchPattern = “anti(\w*)” s = “This is a *very* important message.” r = new regex m = r.search(“The antithesis of synthesis.”) r.searchPattern = “\*(.*)\*” s = “beautification” msgbox m.subexpressionString(1) r.replacementPattern = “\1" r.searchPattern = “[aeiou]+” // result is “thesis” r.options.greedy = false m = r.search(s) s = r.replace(s) while m <> nil You can now understand what the “(0)” // result is "This is a very important count = count + 1 is for in Examples 2 and 3. In a RegexMatch message." i = m.subExpressionStart(0) instance, subexpression 0 is the entire match result. Any other subexpressions Example 5 is very typical of a regular i = i + len(m.subExpressionString(0)) are parts of the result demarcated by expression search-and-replace. We look for r.searchStartPosition = i parentheses in the search expression. a stretch of text consisting of two asterisks m = r.search() The rule for how they are numbered is and everything in between, using syntax wend simple: just count left-parentheses from we’re now very familiar with (Notice the msgbox str(count) left to right. So, for example, if the search use of a backslash to show we mean an expression were ((anti)(\w*)), then actual asterisk.). But we’re only interested Parentheses and Subexpressions the material following the “anti” would in what’s between the asterisks; we want to In a regular search expression paren- be subexpression 3. throw away the asterisks themselves. So in theses have two functions. One is simply to Another interesting use of subexpres- the search expression we demarcate what group things. For example, you might want sions is to refer to them within the search comes between the asterisks as a subex- to use a plus-sign to indicate a repetition, expression. This is done by number, pression. That way we can refer to it in the not of a single character, but of a more preceded by a backslash; so, \3 means replace expression, which consists of “” extended regular expression. To do so, subexpression 3. You use this to search and “” surrounding whatever turned you’d group what precedes the plus-sign in for material containing repetition at a out to be between the asterisks. The result, parentheses; the plus-sign would then apply distance. For example, the expression in this particular case, is the replacement to the group as a whole. Thus the expres- \w*(\w)\w*\1\w* looks for a word string “very”. That whole replace- sion (p+e)+r would match “pepper”: first containing the same character twice; it ment string then replaces the whole found we match the single “p” and the “e” that matches “metre” which contains two e’s, string in the original string; thus, we end follows it; then we try to do it again, and but it doesn’t match “metric” where no two up with just what we started with except we succeed, matching the double “p” and letters are the same. that the asterisks are gone and the HTML the “e” that follows it; then we try to do it markup is inserted. again, and we fail; so we look to see if an Search and Replace We can take this even further, finding “r” follows, and it does, so we stop with a To perform a search-and-replace, you and replacing with HTML all asterisked successful match. assign a regular replace expression to the expressions in a string that contains The other use of parentheses in a search Regex instance’s ReplacementPattern several of them. It’s simply a matter of expression is to demarcate a substring of property and send it the Replace message. inserting one line before performing the whatever the search expression finds. This Regular replace expressions can refer to replace, specifying that the replace should is useful, for instance, when you have to subexpressions, using the same \3 nota- be global: make a search expression where what tion we just talked about; otherwise they interests you about the result is not the are pretty much just ordinary strings. The Example 5a: Search-and-replace, entire found string but only a certain part syntax of the Replace message is just like global of it. For example, suppose you want to that of the Search message. The result is ... find a word starting with “anti,” but you a string where the replacement has been s = “This *is* a *very* important message.” don’t care about the whole word; you’re inserted into the original in place of the ... interested in what’s being opposed, so what found match. you really want to know is what follows Example 1 has already provided an r.options.replaceAllMatches = true the “anti.” The regular search expression illustration of search-and-replace. Here’s ... anti(\w*) will perform the search; but another, using a subexpression reference. // result is “This is<.B> a what do the parentheses do here? They Suppose we’ve got a string from an email very important message." allow us to refer to the relevant substring of message where the author indicated whatever is found. The stuff found by what’s emphasis by surrounding words with Another way to do a replace is to perform in the parentheses of a search expression asterisks. We want to turn this to HTML; a search and then send the Replace is called a subexpression of the result. In we will find a stretch surrounded by aster- message to the resulting RegexMatch this case, it is subexpression 1, and you can isks and replace the asterisks with “” instance. You can use a regular replace extract it from the resulting RegexMatch and “”. expression as parameter, or omit the instance with the SubexpressionString(1) parameter if you already set the Regex property and get its position with the instance’s ReplacementPattern property. SubexpressionStart(1) property. The result is the replacement string alone, not the replacement string inserted into the original. In this example, we look for

26 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 27 a seven-digit phone number in any of to study these properties. Besides greedi- Three Ways to Animate several forms — “555-1234,” “5551234,” ness and whether a search-and-replace Continued from page 23 or “555 1234” — and render it into canonical should be global, there’s a setting for form using a hyphen. case sensitivity. There are also a number of very small (and you’re able to update just settings having to do with the treatment of that part of the frame). As the anima- Example 6: Search-and-replace, line endings. The reason for these is partly tion gets larger or more complex, Canvas extracted that different platforms use different line- animation will suffer. SpriteSurfaces and dim r as regex, m as regexMatch ending characters, and partly that regular Rb3DSpaces hold up better under more dim s, canonical as string expressions were developed in a context of complex jobs, though with enough objects being applied to just one line (or paragraph) they will both slow down. In the case of a s = “The phone number is 5437890.” of text at a time, which might or might not SpriteSurface, it’s the number of objects r = new regex be the behavior you want. that are actually moving or changing shape r.searchPattern = “(\d\d\d)([- ]?)(\d\d\d\d)” that counts; with an Rb3DSpace it’s the m = r.search(s) Exceptions total number of visible objects (and their canonical = m.replace(“\1-\3”) If you supply a search expression that complexity), even if they are unchanging // result is “543-7890” can’t be parsed as a valid regular expres- from frame to frame. sion, REALbasic will throw an exception Finally, consider system requirements. Since the search result remains sitting when you send the Search or Replace Canvas animation and SpriteSurfaces will in the RegexMatch instance, you can now message. This will be an instance of the work on pretty much any system that RB proceed to perform a different replacement RegexException class, and you can learn runs on. The Rb3DSpace requires support without performing the entire search over more about the details of the problem from a system library, either QuickDraw again. through its Message property. Of course, 3D (on classic Mac OS) or Quesa (on any you can also get a NilObjectException by system). These are free, but many users will Example 6a: Search-and-replace, trying to extract property values from not have them by default (except perhaps extracted, repeated a nil RegexMatch instance generated in classic Mac OS) so you might need to dim r as regex, m as regexMatch by an unsuccessful search; and trying ship your application as an installer that dim s, canonical, noncanonical as string to extract a SubexpressionString or a includes the appropriate library. SubexpressionStart using an index too s = “The phone number is 5437890.” high for the number of subexpressions Conclusion r = new regex in the search expression will generate an The project associated with this article r.searchPattern = “(\d\d\d)([- ]?)(\d\d\d\d)” OutOfBoundsException. includes all the code shown here, plus a few m = r.search(s) extra perks that were omitted for brevity. It canonical = m.replace(“\1-\3”) Expression Yourself lets you change among the three animation // result is “543-7890” This discussion has not enumerated methods, do some extra tricks like scaling noncanonical = m.replace("\1 \3") every aspect of regular expressions, but the view when rendering with Rb3D, and it has introduced the high points, and measure the maximum attainable speed. // result is "543 7890" you now know enough to get started This lets you compare the three approaches You can also take advantage of the Perl with REALbasic’s implementation of very directly. Do keep in mind that details operators $` and $’ as metacharacters in regular expressions. You shouldn’t have (especially performance) will vary greatly a regular replace expression; they stand much difficulty understanding the list depending on the particulars of the task for the part of the original string respec- of metacharacters in the online help for and on your system (e.g. whether you’re tively preceding and following the found Regex, and you’re well prepared, with a using Quesa or QuickDraw 3D for the string. little study, a little thought, and a little Rb3DSpace). experimentation, to do much of what can If you’re looking to explore these anima- Example 7: Prematch operator be done with regular expressions. tion techniques in more depth, I would dim r as regex, m as regexMatch Here are a couple of warnings. First, suggest you generalize the code to support dim s, prematch as string regular expressions take practice. The multiple rockets. This will let you see how subject is a deep one, and adepts pride each approach scales up with an increasing s = “The phone number is 5437890.” themselves on their ability to construct number of moving objects. Or, if you’re r = new regex long, powerful, incomprehensible search interested in game development, you might r.searchPattern = “(\d\d\d)([- ]?)(\d\d\d\d)” expressions. Second, don’t imagine that any try connecting each of the update methods m = r.search(s) single regular expression can solve every to the keyboard state and see which one is prematch = m.replace(“$`”) search problem. There’s nothing wrong most pleasant to “fly.” // result is “The phone number is “ with breaking down a problem into several There are certainly other approaches to searches, and often that’s the best solution. animation in REALbasic, especially when Options Neither of these matters has anything to plug-ins are involved. But this covers the We had occasion in the preceding do with REALbasic itself! Remember, most important ones; with a good under- examples to refer to the Options property REALbasic simply implements a standard standing of these you’ll be well prepared of a Regex instance. This is an instance of form of regular expression syntax. Now get to handle any animation task. the RegexOptions class, which has various out there and search some text! properties whose values determine the REFERENCES behavior of subsequent searches. You can Quesa: http://www.quesa.org/ examine the online help for RegexOptions RBD# 1005 RBD# 1004 26 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 27 Beginner’s Corner by Thomas J. Cunningham

Introducing REALbasic For those just getting started

his column is targeted for the new or someone else. Our computer does not (see Figure 1). You would type in your code Tcomputer programmer. I program with comprehend our human language. We need instructions, line after line, and when you REALbasic (RB) as a hobby. I have tried something to take our human desires and were finished, you ran the program. This many other Mac programming applications interpret these in a language that our Mac interpreter would then read in, line-by-line, and RB is far and away the most satisfying. understands. REALbasic is our interpreter. each instruction, “printing” its answers in It is a perfect development and learning Programming a computer can be described another display window. REALbasic does platform for beginners, students, and expe- by two principles: logic and math. not use this approach, but instead inte- rienced programmers. Don’t let the BASIC Now, it would be cool if we could just grates several windows in to what is called in REALbasic fool you: there is plenty of tell RB, “would you please have my Mac an Integrated Design Environment (IDE) power to write a wide assortment of fun, balance my checkbook for me?” Sorry, (see Figure 2). useful, and professional applications. RB is awesome, your Mac is the best, but REALbasic also has a very different I assume that if you have made the they are not that good. No, in order to have code execution approach than most BASIC commitment to this magazine, that you RB help us program our Mac, we need to compilers. Yes, we will be writing code, are a proficient Mac user and that you learn the language that RB understands. telling RB what we would like it to do, but have at least spent a few hours going over The RB language is not French, German, not in a singular code window. Instead, RB the QuickStart.pdf and word processing or even English. It is a version of BASIC, reads and runs code segments from Events. tutorials that come with RB. an acronym that stands for Beginner’s This event-driven method is a very intuitive This column will back up a bit from the All-purpose Symbolic Instruction and powerful way to program, especially for tutorial and explain a few of the begin- Code. REALbasic is just one of perhaps beginners. It does add a level of complexity, ning computer science issues introduced hundreds of different variations of the since we have to learn what these events in these guides. It is intended to be a BASIC language. Please note that the “B” are and when they happen, but in the end gentle course that will keep you inter- in BASIC” stands for beginners, which is this is a very good approach to program- ested in programming. Make no mistake good for us, right? ming. And luckily, most of these events about it: programming, for most, does We give our instructions to RB via code. are intuitive to Mac users. not come naturally. It is a discipline that Code can be thought of as a recipe of sorts. So what is an RB event? Some examples takes time. Like trying to learn to play a Like baking cookies: “mix 1 cup of flour, include: a mouse click, a mouse moving, musical instrument, it takes patience, a bit add sugar, bake, etc.” The computer science a window opening or closing, or a button of dedication, and lots of practice to obtain word for this recipe is algorithm. When we pushed, to name just a few. Each event is a certain level of fun and proficiency. tell our program to “run” (command-R), RB associated with a particular item in your passes our instructions to the computer, program. So when this event occurs, then An Overview Of Programming with translating it into the language our Mac and only then, is your code executed. The REALbasic understands: machine code. specific events occurring with each item Programming a computer. What does In the past, most BASIC interpreters are easy to find, since they are listed in the this mean to you? The purpose of program- used a “one window” coding approach code editor associated with that particular ming is to tell our computer what we want it to do. We want it to do certain tasks for us in a manner that we, as the programmer, think would be useful to a user, either ourselves

homas has been enthusiastically T learning to program his Mac using REALbasic since July 1999. Figure 1: This is what a programming window looked like on an Apple IIe.

28 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 29 a tool in Window1, you Appearance area the “text” property we can position it where you want displayed. would like it to be, make Pretend the jet company has given you it bigger or smaller, or a picture they want in the ad. All you have otherwise change certain to do is drag and drop the picture file in to characteristics of the tool. our project window, from your desktop, to These characteristics are have access to the picture in your program. called properties. A class We set our Window1 BackDrop property to has certain properties the name of the picture from the drop down associated with it. Most list. The picture will now be displayed when of these properties can be we run our project (Command - R). changed, via code, while We run this little project and see your application is oper- that it looks just like we want. We quit, Figure 2: REALbasic’s user interface is referred ating (during “runtime”). returning to our Integrated Development to as the IDE. This is how your program Environment (IDE) to add one feature that appears to interact with a print magazine can not offer. We drag its user in a (hopefully!) a pushbutton class tool (the “OK”) from control item. Not all of these items have intelligent manner: by changing certain the tools menu to Window1 and change its the same events, but many do share properties as various events occur. Caption property to read “Push me for more common events. Most of these events are For example, when a user places his or info.” We adjust the button’s size proper- self explanatory, but some will take a bit her mouse cursor over a certain word, it ties so we can see this caption and place of time to understand. This is part of the turns red; when it moves away, the word it where we want. Now, while still in the learning process of becoming familiar with returns to black. IDE, double-click the pushbutton, which RB, so be patient. by default is named “pushbutton1”. This Another excellent difference in RB from reveals pushbutton1’s code editor. line-by-line interpreters is the ability to In the action event of this pushbutton’s design what your user’s screen looks code editor (“action” means when the user like in your program. This is referred to presses this button), we write code that as your User Interface (UI). Most all of will be executed when the user pushes your programs will have a main window. this button. I won’t bother with the actual Much like the words you are now reading code here, but it will launch our user’s web need to be printed on a once blank sheet of browser, taking them to this advertiser’s paper, your program will need to place the web page. We now have a dynamic adver- items you want to show in a main window. tisement with easy access for our user to The items that you can add include text, this product. Very cool, and it took little buttons, edit boxes, and pictures, to name time and effort, with RB’s help of course! a few. You have seen these control items This is how events and code execution (See Figure 3). many times in all of the Mac programs you interact in RB to make your application I hope this brief overview of the RB currently use. They help to define the Mac more engaging to the user. Also note that development experience has helped you! experience. RB takes care of a lot of the gory details Next issue we will go in to more depth with So where do these control items that here, like what defines the area of the word specific details of the coding process. we place in a window come from? What and the redrawing of the text. are these control items? Again, think of Let me describe an example. Say we this magazine as a real world example. want to create an application that dupli- REALbasic comes with a plethora of built- cates an advertisement page in a magazine. in “tools” for you to use in creating your Lets assume the page has some words, or programs. They are conveniently listed in text with the product’s corporate byline, a Tools Palette within the IDE. By “built- and a picture in the background of the in,” I mean they each have certain jobs or product, BackYard Jets. Launch RB and tasks that they perform automatically for open Window1 (the default name of the us. They have already been programmed main window) from the project window by by RB and are ready to use. These tools are double clicking on its name. Once open, in computer science parlance referred to we drag a StaticText class (represented as Classes. Think of these tools as the raw by the “Aa” icon) from our tools palette materials, or building blocks, you will use (which is on the left side of the screen). to construct an application. This class tool building block will display You use the tools (classes) just like a our text. We readjust its position within drawing program. You select one from the window, resize its width and height, the tools palette and drag it into your and enable its MultiLine property (using main design window. This window name the properties window located on the right is, by default, “Window1.” You can drag side of the screen). Enabling the MultiLine Figure 3: Our fictitious advertisement multiple copies of the same class in to your property will allow the text to be shown on program. main application window. Once you place more than one line. We type into the Text RBD# 1006 28 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 29 Advanced Techniques by Thomas Reed

Using the Declare Statement It’s not as difficult as you think

Declare Function GetSysBeepVolume Lib he Mac OS has always been nice to look Once you have decided which routine “InterfaceLib” (byref level as integer) Tat, but many folks don’t know about to call, you need to translate the C func- as Short Inline68K(“203C02240018A800”) the power under the hood. REALbasic tion declaration into a REALbasic Declare #endif sometimes suffers from the same miscon- statement. Let’s start with a fairly simple ceptions, but like the Mac OS, the power example: suppose you want to call the REALbasic 4.5 will introduce the ability is there. In this column I’m going to talk GetSysBeepVolume function. Its C func- to use an OS-specific string constant to about one way to get “under the hood” in tion declaration is: specify the library, trimming the above REALbasic: using Declare statements. five lines of code down to one. A Declare statement allows you to call OSErr GetSysBeepVolume(long *level) Next, the parameters are defined. Since system routines, enabling you to do things FOURWORDINLINE(0x203C, 0x0224, 0x0018, GetSysBeepVolume takes a pointer to a for which REALbasic doesn’t have built-in 0xA800); long integer, you can handle this one of two support. For example, a Declare statement The corresponding REALbasic Declare ways. The easy way is to make REALbasic can call Process Manager routines from statement for a 68K or PPC build will be: pass the parameter by reference using the the Mac Toolbox to get information about byref keyword and to define the parameter currently running applications. This infor- Declare Function GetSysBeepVolume Lib as an integer. The hard way is to define “InterfaceLib” (byref level as integer) mation is not available through any native as Short Inline68K(“203C02240018A800”) that parameter as being of type Ptr. We REALbasic classes or methods. will discuss how to determine parameter Instead of repeating the information To understand how I arrived at this types and what kind of variables to pass found in the REALbasic documentation result, let’s start at the beginning of the as parameters in a moment. regarding Declare statements, I’ll assume C declaration, which in this case is the If the routine has been defined as a throughout this article that you’re familiar keyword OSErr. This is the return value, function, the next thing you need to do with it. The discussion will also be limited and an OSErr is just a short integer. Thus, is define a return type. In the example to accessing Mac Toolbox routines; using it needs to be defined as a Function in the of GetSysBeepVolume, the return type Declare statements to access system Declare statement. In C, a return value is OSErr. If you look in the Universal routines under Windows is beyond the of void means the routine doesn’t return Interfaces or the documentation on scope of this article. anything. In that case, it would instead Apple’s web site, you will learn that OSErr Building a Declare statement is the first be defined as a subroutine in the Declare is a fancy name for a short, which is a 2- step in calling a Toolbox routine. To do statement, using the keyword sub. this you first need to know which system Next, we need to specify in which library routine you want to call and how it’s called. the routine is found. For almost all Toolbox RB Declare type RB variable type You can find documentation for the various routines for PPC or 68K builds, this will Toolbox routines on Apple’s web site at be InterfaceLib; while for Carbon builds OSType String http://developer.apple.com/techpubs/. it will be CarbonLib. Note that you can Short Integer Raw C function declarations can be found use preprocessor directives to include the PString String in the “CIncludes” folder of the Universal appropriate Declare statement for your CString String Interfaces. The Universal Interfaces can build. Here’s an example that will work WindowPtr Window be found at http://developer.apple.com/ properly for all Mac OS builds (68K, PPC sdk/index.html. or Carbon): Ptr MemoryBlock

#if TargetCarbon Table 2: Some data types used with homas Reed has been program- Declare Function GetSysBeepVolume Lib Declares can’t be used in variable “CarbonLib” (byref level as integer) as T ming as a hobbyist for more than Short declarations. This shows how these 20 years, and fell in love with the Mac “Declare-only” data types map to #else in 1984. regular REALbasic variable types.

30 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 31 long parID; RB Declare type Toolbox/C type Str63 name; Integer long, int, SInt32, UInt32, Size, Handle, Ptr }; Short short, SInt16, UInt16 Single float If you know your Toolbox data types, you’ll know this is 70 bytes. However, if Double double you’re not so sure, the size can be found Boolean boolean in the header files Color same as Integer that are part of the Universal Interfaces. WindowPtr† WindowPtr, WindowRef The structure definition in these headers includes offsets for each field and the total PString ConstStr255Param, Str255, Str63 size of the structure. Consider the example † CString char * of an FSSpec: OSType† OSType, ResType, DescType FSSpec RECORD 0 Ptr Handle, Ptr, any pointer type vRefNum ds.w 1 ; offset: $0 (0) † only to be used in parameters, not as return types parID ds.l 1 ; offset: $2 (2) Table 1: This table shows which data type to use in your Declares to represent name ds StrFileName ; offset: $6 (6) some common Toolbox/C data types. sizeof EQU * ; size: $46 (70) ENDR byte integer. So, we define the routine as Let’s return to the issue of how to Because it’s 70 bytes long, you would returning a Short. translate Toolbox and C data types into use a MemoryBlock 70 bytes in size to pass This is sufficient, unless you also want to REALbasic data types. Table 1 lists the an FSSpec to Toolbox routines. Here’s an support 68K code, in which case you need to types available for use with Declares in example that creates an FSSpec from a include the Inline68K value. (As of version REALbasic and shows how they map to FolderItem: 4.0, RB no longer supports 68K builds.) some common Toolbox/C data types. You Look back at the Declare statement should note that some of these data types dim f as FolderItem for the GetSysBeepVolume routine and are interchangeable. For example, Integer, dim fsspec as MemoryBlock you’ll find a long hexadecimal number in Color, OSType, and Ptr are all 4-byte values, dim err as integer the Inline68K parameter. This number is so technically you could use OSType where dim fname as string derived by concatenating the numbers a Toolbox routine uses UInt32. Your choice Declare Function FSMakeFSSpec Lib "CarbonLib" found in the FOURWORDINLINE param- depends on how you will use the value. (vRefNum as Integer, dirID as Integer, eter of the C function definition. (Note that For the most part, the types you use in a fileName as PString, spec as Ptr) as Integer the C definitions of other routines may Declare statement are the same as regular have a ONEWORDINLINE parameter, REALbasic variable types. However, there TWOWORDINLINE parameter, etc.) are some differences. For example, what Continued on page 48 Building Declare statements this way kind of variable do you pass to a routine may seem difficult, but fortunately, you that expects an OSType? OSType isn’t a Unsigned longs can get some help from an excellent REALbasic variable type! Table 2 shows Since REALbasic doesn’t have an program called TBFinder, available at how some of the Declare types map to unsigned long integer type, it may be http://homepage.mac.com/everyday/ REALbasic variable types. difficult to get such a value from an OS code/downloads/TBFinder.sit. TBFinder Looking at Table 2, we see that if you routine. When you put a large enough will look up the C function definition and want to call a Toolbox routine that takes unsigned long in a REALbasic Integer, build the Declare statement for you. an OSType as a parameter, you can just it will inaccurately be represented as Now that you know how to build a pass in a REALbasic string. It will be trans- a negative number. Declare statement, you need to know how lated into a 4-character OSType before the The only way to represent a full to use it: how to call it, what data types Toolbox routine is called. unsigned long integer is to store it in you can use (yes, we’re not done with that More complex data types offer other a Double, which is an 8-byte value. yet), and how to interpret complex data challenges. You may notice that there are However, a little number crunching is structures. Calling a Toolbox routine is a LOT of Toolbox data types missing from needed to get the real unsigned number simple, as long as you remember a few Table 1! You’ll want to use REALbasic’s from the signed REALbasic Integer: simple rules. First, note that you must MemoryBlock class for most of these. enclose the parameters in parentheses For example, suppose you want to create dim i as integer when calling functions while you should an FSSpec, which is the OS equivalent of dim d as double omit the parentheses for subroutines. the FolderItem class in REALbasic. You’ll i = DoSomethingToGetAnUnsignedInteger() Otherwise, the REALbasic compiler will need to create storage in memory for the if i < 0 then complain. Second, don’t try to use the result FSSpec, which requires that you know how d = BitwiseAnd(i, &h7FFFFFFF) of a function call directly as a parameter to large it is. An FSSpec’s structure definition d = d + 2147483648.0 the Declared routine. You will first need to in C looks like this: store the value somewhere. Properties of else REALbasic objects should be considered struct FSSpec { d = i function calls. short vRefNum; end if

30 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 31 Ask the Experts by Seth Willits with Thomas Reed & Sean Beach

In a program I’m writing, I’d like to I have a few fields in my program inlude a menu where the users can // Hide the index that should only contain numbers. add their own AppleScripts and ScriptItem(0).visible = false Unfortunately REALbasic doesn’t execute them. How can I implement offer a simple checkbox like for this? // Delete all items password fields so I have to write A fully implemented Scripts menu is If ScriptItems > 0 then my own. How should I go about seemingly involved, but easily imple- this? for i = ScriptItems downto 1 mented through the use of available third party plugins and modules. The two main ScriptItem(i).close Number-Only fields simply filter parts of a Scripts menu are handling the next out keystrokes from keys other than dynamic menu items, and executing the end if numbers, arrows, and the delete key. In script as it is selected from the menu. To REALbasic we can do this filtering inside add a little flavor, we can also add icons // Add items of the KeyDown event of an editfield to the menu title as well as the individual scriptItems = 0 by returning true if the key is one we menu items. do NOT want to appear in the field. As if UBound(scripts) > -1 then you can see in the code listing I chose to Dynamic Menu Items for i = 0 to UBound(Scripts) use the InStr function instead of using This portion of the menu is by far the si = New ScriptItem a series of conditions on the ASCII most involved step in creating a working si.text = Scripts(i).name value for simplicity (using InStr will not Scripts menu. The idea is to create a menu si.enabled = true noticably slow down the speed of typing that can hold a variable number of menu ScriptItems = ScriptItems + 1 in the field unless it contains hundreds items pointing to scripts. The menu itself next of characters). will have one menu item called ScriptItem In this implementation, the field allows which will have an index value of 0. With end if the numbers 0-9, the delete, return, enter, this menu instated we can create two prop- tab, and arrow keys to pass through. Letting erties in the Aplication class; Scripts(-1) Executing the Scripts the tab key pass through prevents the inter- as folderitem and ScriptItems as integer. Executing the scripts is a simple matter. ruption of tabbing from field to field. Just Next we can use the code in the listing We will use Doug Holton’s AppleScript make sure that you don’t have the Allow to dynamically create the menuitems in plugin (http://www.geocities.com/d_ Tabs property of the field enabled, other- the EnableMenuItems event. The code h_l_h/) to do this for us. By examining wise the tab will appear in the field! depends on folderitems in the Scripts array the code in the EnableMenuItems event that point to the scripts themselves. You you will see that the lower bound of the Function KeyDown(Key As String) As Boolean can choose how to handle adding those ScriptItem menu item is not used. This if InStr(“0123456789” + chr(8) + chr(13) + folderitems on your own. means we’ll have to subtract one from chr(9) + chr(3), key) > 0 then the menuitem’s index property (in the return false dim si as MenuItem ScriptItem menu handler) to get the elseif asc(key) > 27 and asc(key) < 32 then dim i as integer correct Scripts() folderitem. return false Once we have the folderitem pointing else // Scripts Menu to the script we can determine if it return true is compiled or not by its Mactype. A ScriptsAddScript.enable end if MacType of “TEXT” means the script has not been compiled while a MacType of End Function eth Willits, the President and Head “osas” means that it has. An uncompiled SDeveloper of Freak Software, is script keeps the script code in the datafork My son is into racing go-karts and slowly working his way to becoming making it easy to simply open the file in I’d like to write a program to keep a distinguished programmer for the a text input stream, read everything, and track of all of his lap times and Macintosh. Thomas and Sean are execute it using the RunScript method of other race specific information. columnists for REALbasic Developer. the AppleScript plugin. If the AppleScript Since each race or practice session Send your “Ask the Experts” questions has been compiled we need to extract the can have a different number of to [email protected]. Due to the data from resource 128 of type “scpt” laps the difficult part of writing the volume of email, personal responses and pass that as the parameter to the program is how to handle those are regretfully not possible. RunCompiledScript method. lap times. The only way I can think

32 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 33 of is to have a separate folder for belong to which race event. For examle, the To extract all of the information from every race or practice session longest lap time is a 01:49:58 which has the database at one time we’ll need to which contains separate text files a RaceID of 001. In the RaceInfo table we use an instance of a custom class for each for lap times and race info. While search for the record with the RaceID of race event. You can define the class as this would work, it would be very 001 and that’s the race that the lap time follows: messy. What is a more elegant belongs to. The slowest lap time occurred solution? at the California track on 01/02/02. The table schemas for the database are Event This is a problem that arises and is as follows: LapTimes(-1) as string solved everyday using a relational Track as integer database. If you have not yet learned to RaceInfo ( RaceDate as String use REALbasic’s built-in database tools I RaceID integer, highly recommend that you do. Not only Track varchar, will it enable you to write an elegant Date varchar, solution to this problem, but it will help Primary Key(RaceID) The code to read the data is as follows. you with many other similar problems in ) the future. dim e as Event To learn about databases in REALbasic, I dim curs, lapcurs as DatabaseCursor would recommend that you read the REAL LapTimes ( dim rid as integer Database guide written by Seth Willits of ID integer, Freak Software. The instructions below RaceID integer, // Select all race dates in the database assume that you know how to create a LapTime varchar, curs = Database.SQLSelect("Select * from database and understand how to use it. Primary Key(ID) RaceInfo") The general concept of the solution // For every race event to this problem is to have two tables in ) do a database. One table (RaceInfo) will hold the race specific information (track, Note that the RaceID field for the e = New Event date, etc.) and the other (LapTimes) will RaceInfo table is the primary key, but in e.Track = curs.Field("Track").getString only hold lap times. Each record in the the LapTimes table it is not. Every record e.RaceDate = curs.Field("Date").getString RaceInfo table will have an ID number in the RaceInfo table will have a unique which is specific to that race event. Each RaceID but in the LapTimes table several // Get the RaceID of the event record of the LapTimes table will contain records will have the same RaceID. rid = curs.Field("RaceID").integerValue an ID number which is the same as the ID Adding records to the database can be // Select every lap time with the RaceID of number of the race that the lap time was handled anyway you’d like. Just keep in this event recorded on. mind that when you add lap times to the lapcurs = Database.SQLSelect("Select LapTime Take a look at Figure 1. By matching the LapTimes table they must have the same from LapTimes where RaceID = " + RaceID from a lap time to a record in the RaceID as the corresponding record in the str(rid)) RaceInfo table with the same RaceID or vice RaceInfo table. do versa we can determine which lap times // Add the lap time to the laptimes array of the event’s Event class instance e.laptimes.append lapcurs.field("LapTime") .getString lapcurs.moveNext loop until lapcurs.eof lapcurs.close // Add Event class instance to the global Events array Events.append e curs.moveNext loop until curs.eof

curs.close lapcurs.close

REFERENCES REAL Database Guide: http://www.freaksw.com/rb-papers.html Figure 1: This is a graphical representation of the two tables that will be in your Race Example Project: http://www.freaksw.com database. Top: RaceInfo. Bottom: LapTimes.

RBD# 1008 32 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 33 Algorithms by Matt Neuburg

Linked Lists Mind your stacks and queues

he term “algorithm” can mean instruc- Ttions for carrying out some typically ... hey ho ha ... useful operation, but it can also mean a typi- cally useful data structure and the methods Figure 1: A linked list for working with it. A linked list is often one of the first data structures treated in books on algorithms, and it makes a good subject for this first Algorithms column. Let’s implement this in REALbasic. In The last two lines, (a) and (b), perform A linked list is a simple data structure REALbasic, object references are pointers. the disconnection and reconnection of that’s useful chiefly because it’s dynamic. (See pp. 94-104 of my book for much more pointers that we talked about earlier. This means you don’t have to set aside about that.) So the problem is solved if After (a), for an instant, both the new item’s storage for the data beforehand; instead, each piece of data is an object, and consists NextItem and the target’s NextItem point the linked list grows and shrinks as the of two things: the value to be stored, and at the same thing; then in (b) we repoint program runs, as when data is added or a reference to the next piece of data. An the target’s NextItem at the new item. removed. In REALbasic this fact is not object consisting of two things is merely The order of operations is important! If very compelling, though, because arrays an instance of some class that has two (b) precedes (a), then after (b), the target’s are dynamic already! You can add data properties. Let’s call the class ListItem, NextItem no longer points at what was the with Insert or Append, and remove it with and let its two properties be called Value, next item in the list — in fact, nothing at Remove. Nevertheless, you can also very a variant (for generality), and NextItem, all points to it, the item is lost, and the easily implement a traditional linked list another ListItem. It’s easy to see that, with list is ruined. in REALbasic, and it’s instructional to see appropriate values for the properties of In REALbasic, an object reference that how. The principles involved are applicable each instance, we end up with a linked has never been set explicitly is nil. This to more complicated and powerful data list (see figure 3). fact makes it easy to obtain the last item in structures, such as binary trees, that we We can now implement Insert, handing the list, by following the chain of pointers can examine in future columns. a ListItem the Value we want attached to item by item until we come to one whose The chief characteristic of a linked list is a new ListItem that will follow it. NextItem is nil. This approach works no that from each piece of data it is possible matter what item of the list we target to reach the next piece of data. The pieces ListItem.Insert: initially. Following the whole chain of of data are connected by pointers; to reach Sub Insert(v As variant) pointers in this way is called traversing the next piece of data, follow this piece’s dim newItem as ListItem the list, and can be neatly expressed in pointer (see Figure 1). REALbasic. newItem = new ListItem To see why this is dynamic, consider how you’d insert a new piece of data, “hi,” after newItem.value = v ListItem.LastItem: newItem.nextItem = self.nextItem // (a) “hey”: just disconnect the pointer from Function LastItem() As ListItem self.nextItem = newItem // (b) “hey” to “ho”, and make it run to “hi” dim x as listItem instead, and connect the pointer from End Sub x = self “hi” to “ho” (see Figure 2).

hi att Neuburg is the author of MREALbasic: The Definitive Guide, ... hey ho ha ... and a member of the editorial board of REALbasic Developer. Figure 2: Insertion into a linked list

34 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 35 single property, MyArray, a variant array Value: Value: Value: initially dimmed to size -1. We’ll treat the hey ho ha end of the array as the top of the stack. So NextItem: NextItem: NextItem: Push just means Append...... Stack.Push: Figure 3: Linked list made of REALbasic objects Sub Push(v as variant) MyArray.append v End Sub As an exercise, implement Pop. while x.nextItem <> nil the case of an EditField, every time the To the programmer, you’ll observe, it x = x.nextItem EditField changes, you could Push its doesn’t matter whether Stack is imple- wend current state (its text and style) onto the mented as a linked list or an array. This return x stack; to Undo one level, just Pop the stack is in keeping with the principle of abstrac- End Function to retrieve the previous state. tion: lower-level manipulation of data is A stack is easily implemented as a linked hidden inside a controller object. As much As an exercise, implement Append. This list. We might, indeed, have a class Stack as possible, you should try to program this accepts a value and adds it at the end of that is a subclass of ListItem. Suppose we way. For one thing, other objects in your the list, no matter what item of the list maintain somewhere a property or variable program have no need to concern them- we target initially. Hint: combine LastItem called TheStack, which is a Stack. TheStack selves with the underlying implementation and Insert. represents the entire stack; Push and Pop details; they just say Push or Pop and every- Finally, we implement RemoveNext. are sent only to it. But in reality it is the start thing simply works. This greatly reduces When sent to an item of the list, it removes of a linked list, and points to the topmost the chances for error. Also, you could the next item from the list. We first check item of the actual stack. change your mind about the underlying for a NextItem value of nil, since the target implementation, changing it from a linked might be the last item already; in that case, Stack.Push: list to an array for example, and all the calls obviously, we do nothing. Otherwise, we Sub Push(v as variant) to Push and Pop throughout the program just point the target’s NextItem at the self.insert v would go right on working. next item’s NextItem (see figure 4). The End Sub instant we do this, nothing points at what Queues used to be the next item, whose existence A queue is a data structure where access is promptly terminated by REALbasic’s Stack.Pop: to the pieces of data works like patrons delightful memory management system. Function Pop() as variant lined up to enter a movie theater: the first dim v as variant patron to get on line will be the first patron ListItem.RemoveNext: to enter the theatre, and so on. A queue is if self.nextitem <> nil then Sub RemoveNext often described as FIFO (first in, first out). v = self.nextitem.value // (a) if self.nextItem <> nil then The fundamental operations on a queue are self.deleteNext // (b) called Queue (append an item to the tail of self.nextItem = self.nextItem.nextItem return v the queue) and Dequeue (retrieve an item end end from the front of the queue). End Sub End Function Queues often arise in threaded situa- tions, where pending tasks can pile up Stacks Again, order of operations is important. while a previous task is being performed. A stack is a data structure where access to We use a local variable to capture the value For example, in an email client program, the pieces of data works like a pile of plates: to be returned, in (a), before deleting the we might allow the user to press the Send you can add or remove an item only at the item that contained it, in (b). If (b) were button at any time, but we won’t actually top of the pile. Items can thus be retrieved performed before (a), the value would be perform any new sending until we finish only in the reverse of the order in which destroyed before it could be returned; there with whatever message we may be sending they were added; for this reason, a stack would be nothing to return. at the moment. is often described as LIFO (last in, first Since, as mentioned earlier, a REALbasic Implementation of Queue and Dequeue out). The two fundamental operations on array is already a dynamic data structure, are left as an exercise to the reader; do it a stack are called Push (add a new item at Stack could just as well be implemented by both ways, with a linked list and with an the top of the stack) and Pop (remove the wrapping a variant array. Let’s start over. array. topmost item from the stack and return Stack now has no superclass, and has a its value). Under the hood, stacks are fundamental to many computer operations, such as calling subroutines. They also come in ... hey ho ha ... handy during certain kinds of parsing operations, and wherever backtracking is involved. For example, a stack would be Figure 4: Deletion from a linked list a good way to implement an Undo list. In RBD# 1009 34 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 35 Object-Oriented Thinking by Charles Yeomans

Favor Composition Over Inheritance Designing a validating editfield

The Problem duce small but annoying variations in the like Listbox, can also implement this inter- You are writing a Quicken-killer in interfaces of several similar subclasses. face; having the interface explicitly defined REALbasic. You need to do a lot of input There are two actors here, TextValidator helps to document the design. validation — dates, currency input, names, and ValidatingControl. Our next task is Also, a window can maintain references etc. You think, “Ah, RB has made it easy for to specify their roles; that is, we need to to ValidatingControl objects it contains, me — all I need to do is slap some validation declare their interfaces. instead of needing to loop through controls code in the LostFocus event handlers of the The main task I want to ask of a looking for ValidatingControls to test. editfields.” But writing a Quicken-killer is TextValidator is to tell me whether a a big job, and cut-and-paste is especially string I pass it is valid. It would also be ClassInterface ValidatingControl efficient at propagating errors. It occurs to nice to be able to ask a TextValidator for Methods you that you can subclass Editfield. So you an error message; if users enter invalid AddValidator(validator as TextValidator) define DateEditField, NumberEditField, data, they’ll want feedback more informa- RemoveValidator(validator as TextValidator) CurrencyEditField, NonEmptyEditField, tive than a beep. Any class implementing IsValid() as Boolean TextLengthAtMostNEditfield, and other TextValidator can supply a default error ValidationErrorMessage() as String subclasses. But as the subclasses begin message (“Invalid Date”), but it would piling up — for instance, you need an probably be nice to be able to set an The associated project contains an EditField subclass that accepts valid error message more appropriate to the implementation of a ValidatingEditField currency input and must be nonempty context. and some TextValidators. — the project begins to crumble under its own weight. Then you decide that some Class Interface TextValidator The Buzzwords editfields must be able to change the valida- Method We’ve illustrated two principles of object- tion method at runtime. Next, you need to IsValid(text as String) as Boolean oriented design: write an editable listbox requiring valida- SetErrorMessage(msg as String) Favor object composition over class tion. And then Real Software introduces inheritance; and Program to an interface,

a Text class.... GetErrorMessage() as String not an implementation. It’s easy to see that probably every class By looking first to composition, our The Solution implementing TextValidator will have a design is built from objects focused on The common theme of this problem is property holding the error message, and clearly defined tasks. But composition the need to validate text input. This is a task the implementations of SetErrorMessage only works if we are careful to minimize that can be handed off to an object whose and GetErrorMessage will be the same. the extent to which these objects depend sole purpose is to validate text. In other So we’ll define a class (AbstractValidator, on each other. The use of class interfaces words, we can create validating editfields in the associated project) imple- allows us to specify how these objects by composing an editfield and a validator menting basic functionality and let our can communicate; this allows us to make object; the editfield delegates the task of TextValidators inherit from it. For special internal changes to one class without validating input to a validator object. cases we can choose not to inherit from affecting others. We’ll still need to use inheritance to AbstractValidator; this is an advantage of write an EditField subclass which can use factoring the validators into class interface Further Reading validators. But it will be just one subclass + abstract class + concrete classes. Design Patterns: Elements of Reusable requiring simple coding and offering a We’ll use the same idea for the editfield Object-Oriented Software contains an consistent interface; it’s very easy to intro- subclass; that is, we’ll define a class inter- excellent discussion of inheritance v. face ValidatingControl which a subclass composition starting on page 18. ValidatingEditField will implement. Using harles Yeomans is a software devel- a class interface here is mostly for reasons C oper in Lexington, Kentucky. of clarity and convenience. Other controls, RBD# 1010 36 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 37 Intel Focus by Christian Schmitz

REALbasic Windows Support What works and what doesn’t

msgbox “This application runs on Mac OS!” About Windows Versions then blocks. Table 1 describes the target In this column we will discuss #endif constants. REALbasic’s capability to create applica- tions for the Win32 platform. Windows As you can see, this looks like a normal AppleEvents and AppleScript 95, 98, ME, NT4, 2000, and XP all imple- if-then block but with the number sign This first thing to note is that the ment a growing subset of the Win32 API (“#”) in front of the keywords. Everything AppleEvent object on Windows is (Application Programming Interface). But which is not for the current platform will be completely non-functional. REALbasic will these different implementations of Win32 ignored by the compiler, which can reduce compile it but it will just waste memory are not equal, so you’ll find functions in application disk space (for example, an icon and it does nothing for you. This is a good Windows 2000 which are in NT4 but not for Windows is not compiled into the Mac case where the #if TargetMacOS directive in the newer 98 version of Windows. version). You can even build larger blocks can be used to prevent the code from being We’ll mostly discuss functions which with nested #ifs like this one: compiled on Windows. are available in Windows 95 and newer. You can add compiled AppleScripts into Windows NT4 misses some of these #If TargetWin32 then your project and call them from inside your functions but Windows 2000 (which is a msgbox “This application runs on Windows!” applications using their name like in the renamed NT5) has all the functions from #else example below... but use #if TargetMacOS 95 and 98. #if TargetCarbon then to hide this from the Win32 compiler. If readers request it, we can even discuss msgbox “This application runs on Mac OS using a Win32 subsystem on Linux (named Carbon!” #if TargetMacOS Wine) or Windows 3.11 (named Win32s). #else dim result as string If you use one of these versions of #if targetPPC then result = MyAppleScript(“some value as Windows, send me an e-mail at cschmitz@ parameter”) msgbox “This application runs on Mac OS Classic rbdeveloper.com and let me know. on PPC!” #endif #else REALbasic’s Mac-Only Features Resource Forks #if target68k then Using REALbasic version 2.0 or later, All functions to open a resourcefork msgbox “This application runs on Mac OS Classic you can compile applications for Win32, on 68k!” will refuse to work. Depending on your but obviously you need the Professional REALbasic version, they will crash, return #else version if your applications need to run nil or won’t even compile, so you should msgBox “Mac OS on something other than 68k or longer than five minutes. PPC? Can’t be!” again use a #if TargetMacOS directive. People often ask for a list of functions and #endif objects in REALbasic which are Mac-only Type and Creator codes and won’t compile for Windows. Before #endif As a means of being user friendly, getting to this, however, we need to learn #endif Macintosh applications will sometimes how to handle Mac-only features. #endif find files by their type and creator code combination. For example, the Finder finds #if target Sadly there is no #elseif and REALbasic in Mac OS Classic by it’s creator Using the keyword #if, you can tell doesn’t indent the lines like in normal if- code. However, creator and type codes REALbasic to use conditional compiling. are not supported on Windows and any For example: function which returns a code will return hristian Schmitz has written several an empty string. This may force you to #If TargetWin32 then C articles for the German magazine rewrite code to use a file to find msgbox “This application runs on Windows!” Macwelt and has made many cross-plat- the files. #else form applications using REALbasic. Continued on page 48

36 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 37 The Topographic Apprentice by Joe Nastasi

Welcome Three-dimensional graphics for everyone

efore you can raise your hand to Rb3D Architecture you use Rb3D within a REALbasic thread, Bknock, the wooden door creaks open. Rb3D is not a stand-alone 3D engine, it causes a crash. This has been traced to The ancient one nods. “I’ve been expecting but a programming interface (API) that the OpenGL/OS X combination. you.” The dark chamber is filled with dozens runs on top of several 3D technologies. The good news is that, since both Quesa of geometric objects: spheres, cubes, pyra- Under Rb3D is Quesa, which is an open- and OpenGL are open source, they are mids; all spinning and changing color. “The source version of Apple’s now-defunct 3D unlikely to be orphaned. Additionally, road to real-time 3D can have a treacherous engine, QuickDraw 3D (QD3D). Under even if a different rendering engine (e.g. topology, my young apprentice,” he warns. Quesa is OpenGL, a low-level 3D engine. Microsoft’s Direct3D) is needed, Quesa can “But I have faith in you.” Rb3D objects, methods, and properties make use of that with no changes required Welcome to the Topographic Apprentice. are mapped to equivalent Quesa objects. to either REALbasic or your code. The goal of this column is to provide a Quesa handles a lot of the organization, painless introduction to real-time 3D math, and other high-level issues associ- Rb3D Components programming for games and other appli- ated with real-time 3D and then calls the Rb3D contains five classes and one cations. I (otherwise known as “the ancient appropriate routines to actually draw the control. If you are familiar with REALbasic, one”) will make the assumption that you scene. Quesa can draw using a variety of you’ll feel right at home with the syntax. are a REALbasic beginner and have never rendering engines, but the most common Right out of the box, Rb3D does not worked with real-time 3D before. one is based on OpenGL. Unlike Quesa, have the large feature set of commercial QD3D handles both the high-level functions 3D engines. However, with additional A Bit of History and low-level drawing routines (drawing REALbasic programming, more deluxe When I started to use REALbasic to build is via RAVE), so nothing else is required features like a particle generation system my spacecraft simulator, A-OK! The Wings (see Figure 1). (great for smoke and explosions) can be of Mercury, I had no idea how I would In order to use Rb3D, you will need added. In fact, there will be some feature handle the requirement for real-time 3D one of two sets of software libraries. Even articles right here in REALbasic Developer graphics. After trying an as-yet-unreleased though Apple has decided not to support over the coming year that will discuss the plugin and struggling to work directly with QD3D, it is actually the best option for advanced techniques you’ll need to turbo- the OpenGL libraries, I discovered Rb3D, a Mac OS Classic. With QD3D nothing else charge Rb3D! plugin that was written by REAL Software is required. QD3D comes with QuickTime developer Joe Strout. and can be installed by doing a Full or Rb3DSpace While Rb3D had (and still has) limi- Custom QuickTime 5 install. The basic control of Rb3D is called tations, it was the fastest and easiest Unfortunately, QD3D does not work Rb3DSpace. It exists on the REALbasic way to create real-time 3D applications on OS X and does not provide support for Controls Palette (called the Tools Palette with REALbasic. A small but active user hardware accelerator boards on Windows. prior to Rb 4.5) and is dragged on to the community rallied around Rb3D and Quesa is a call-by-call replacement for window of your choice, as you would the REAL Software decided to make it an QD3D that runs on Mac OS and Windows canvas control. An Rb3DSpace functions as integrated feature with the release of (and other platforms as well). It works, but a window that your 3D world will be drawn REALbasic 3.5. has not been optimized yet, so it is slower into and also provides basic camera, light, than QD3D. However, it is the future, so and environment controls. drop a line to the Quesa folks and let them oe Nastasi is the developer of a space- know that it is important to you. Initial Properties J craft simulator, A-OK! The Wings Because Quesa doesn’t handle drawing, All of Rb3DSpace’s Initial Properties of Mercury, created with REALbasic. you need the latest version of OpenGL which can be set in the IDE or under program Joe, who has been a programmer since is available from Apple. Note that at the control. Note: properties marked with an 1977, has been a full-time REALbasic time of this writing, there is a serious bug asterix (*) are new to RB 4.5. consultant since version 1.0. in OS X concerning OpenGL and threads. If

38 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 39 Hither and Yon - These properties define In a shooting game this method can be used how close and how far away an object can Rb3D Rb3D to verify if a target has been hit. be from the “camera” inside Rb3DSpace Translates REALbasic Translates REALbasic FindPoint - This method is similar to syntax to Quesa/QD3D syntax to Quesa/QD3D and still be visible. You can save lots of FindObject: pass it an X,Y coordinate and it processing time by making this range as will return the equivalent 3D point. Useful Quesa QuickDraw 3D small as possible for your application. More High Level Functions for 3D editors as you can know the 3D posi- importantly, Hither and Yon affect rendering High Level Functions tion the user is pointing to. & quality; if the yon/hither ratio is too large, Low Level Drawing Update - This method redraws an you get unwanted visual effects. OpenGL (drawing via RAVE) Rb3DSpace without erasing or triggering FieldOfView - This property defines the Low Level Drawing a Refresh event. This is what you call to “camera” lens. A lower value will narrow update a change you’ve made to the 3D the viewable field, acting like a telephoto environment. lens. Conversely, a larger value will create Figure 1: Rb3D Architecture a larger viewable field, simulating a wide- Vector3D Class angle lens. How does one know where an object is SkyColor - This property allows you to Camera is affected by the Hither, Yon, and in a 3D world? The Vector3D class contains set the background color for this particular FieldOfView properties. that information. You can assign it any 3D Rb3DSpace. This is sufficient for simple Object - This property is basically a group location by setting its X, Y, and Z properties. games and object editor applications. to which you can add objects. Every object Other Rb3D classes use the Vector3D class AmbientLight and AmbientColor* - that you append to Rb3DSpace’s Object to define their position in 3D space or their These properties set the intensity and property will be visible in that Rb3DSpace, vector. I’ll explain this in the future. color of the global non-directional lighting provided that the object’s Visible flag is source. true and it is in the Rb3DSpace’s camera’s Quaternion Class FloodLight, FloodDirection*, and field of view. Which way is an object facing? A FloodColor* - These properties set the Background - This object works exactly Quaternion is a way of representing an intensity, direction, and color of the global like the Object property except for two differ- object’s orientation. There are other directional light source. Like the Sun, the ences: the Ambient and FloodLights do not ways of representing orientation: matrix, FloodLight is an infinitely strong light affect any object in the Background group Euler angles, etc., but the quaternion is the source that is infinitely far away. and the Background’s position relative to most stable. As with Vector3D, other Rb3D FogVisible and FogStart - These prop- the camera is fixed. These characteristics classes inherit the Quaternion class. erties toggle the fog effect on and off, and are useful for things like a sky box; you don’t define how far away from the camera the fog want shading on air, nor do you want the Object3D Class will start. The fog gets progressively thicker camera to go through your sky! Object3D is the core class that most of until Yon, where it is completely opaque. Rb3D is built upon. As stated before, an Wireframe - This is a boolean property Events Object3D has a Vector3D (the Position that allows you to toggle how the models Rb3DSpace can handle all the usual property) and a Quaternion (the Orientation get rendered by Rb3DSpace: shaded or events directly. MouseUp, MouseDrag, property) associated with it. Other properi- wireframe. Wireframe is sometimes useful MouseDown, MouseEnter, and MouseExit ties allow you to scale, control visibility, for a 3D object editor or to create a “Sci can be used to select and move objects or as etc. Several methods are provided to load Fi” 3D look. a way of implementing camera movement. a model, rotate, move the object, etc. DebugCube - This boolean property The Open and Close events can handle the creates a background with all the axes initial loading of objects and any cleanup Group3D Class marked. When you move objects or rotate when an Rb3DSpace is closed. The next Rb3D class is Group3D. As the your Rb3DSpace camera, you can see exactly name suggests, this class allows you to treat what section of the coordinate grid you are Methods a whole bunch of Object3D classes as one. pointing at. Note: this feature only works Three methods are associated with an Since it is a sub-class of Object3D, you can within the IDE, not built apps. Rb3DSpace, two of which are typically called do all the same things to an entire Group3D from a MouseUp or MouseDown event. as you can to one individual Object3D. You Object Properties FindObject - This method takes an X,Y can load parts of a car (wheels - remember Rb3DSpace has a Camera, Background, coordinate within an Rb3DSpace and to clone three of them, body, etc.) sepa- and Object property associated with it. returns any Object3D that lies on that point. rately, then load them all into a Group3D These three items are special- that represents the entire car. ized versions of Rb3DSpace’s You can then move or rotate the core classes, Object3D and entire car by moving or rotating Group3D. Rb3D Space Object3D Vector3D Quaternion the Group3D. Camera - This object can be positioned and rotated, which Light3D Class affects what you see within At the time of this writing, Rb3DSpace. There is only one Real Software was developing Camera for each Rb3DSpace Group3D Light3D the Light3D class for inclusion in your application. In addition with REALbasic 4.5. This class to position and orientation, the Figure 2: Rb3D Classes creates one of two types of lights

Continued on page 48

38 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 39 From Scratch by William Leshner

Day 1: The Mission Designing and building a complete application from scratch

hank you for coming to Tthis staff meeting. We don’t have a lot of time, so I’ll get right to the point. Our marketing depart- ment has come up with a product they want us to design and build from scratch, and management has given us only six days to do it. In a nutshell, this new product helps devel- Figure 1: A product information ListBox. opers release software by automatically generating the various documents usually found in a to enter information about the product to to build versions of ShipIt! that will run release, such as a readme, a user’s guide, a be released. This information must include under older versions of the Mac OS (OS web page describing the software, and an the name of the software being released, 8 and OS 9) as well as Mac OS X. A tool email announcing the software to mailing the name of the developers, the company that can also build a Windows version of lists. These documents all share informa- name, copyright information, and a short ShipIt! is preferred, and all the versions tion about the software being released. description. ShipIt! must provide templates must be built from one set of code. We For example, the name of the product, the for the documents it generates, and allow don’t have enough time to write different company name, copyright information, and the user to edit these templates. Each versions of ShipIt! for each of our target a brief description of the product are some template is used to generate one docu- platforms. After considering a number of of information you might find on the docu- ment by substituting release information development environments, we have come ments included in a software release. It is into user-specified fields. ShipIt! must be to the conclusion that REALbasic by REAL a tedious and time-consuming job to keep able to save the release information and Software Inc. is the best tool for the job. this information up-to-date in all of the templates as a document file that can be It meets all of our requirements, and it’s documentation for every release. Our new opened and reused. Standard UI elements fun to use. product solves this problem by gathering such as unique icons and an about box Before we build ShipIt! we must design and maintaining release-related informa- should be implemented, as well as the it. A good design, taking into account our tion and using that information to generate ability to run under Mac OS 8, 9, and X. marketing requirements, is essential in release documents from templates. We are A Windows version of ShipIt! is highly creating a useful application. The first calling this new product ShipIt!. desirable, but not required. All versions marketing requirement is that ShipIt! Let us quickly go over our marketing of ShipIt! should have the look and feel of gather release-related information from requirements. ShipIt! must enable the user the platform on which they are running. In the user. A simple form could satisfy that other words, a Mac OS 8 version of ShipIt! requirement, with fields for each piece of illiam Leshner has been program- should look like a Mac OS 8 application, information we have decided will be needed W ming for twenty years and and a Windows version of ShipIt!, if there in our templates. This approach assumes programming Macs for ten. He has is to be one, should look like a Windows we have correctly anticipated every piece of spent a good deal of the last several application. information about a release that any user years working in REALbasic and has The first order of business is choosing might want. Instead of a form, a two- come to the conclusion that REALbasic our development tool. We need a tool that column list would be more flexible. Each is the best development environment is fast and easy to use, but powerful enough row in the list would contain a template available anywhere. to finish the job. This tool must be able field. The first column would contain the

40 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 41 in XML. XML is easily extended and older versions of ShipIt! will simply ignore tags and attributes in the document it doesn’t understand. To parse our XML files we will need an XML parser. Although we could use a third-party XML parser, we propose to write a very simple one that will handle just enough XML to read ShipIt! files. We will cover the details of the ShipIt! XML tags and the parser in a future column. Our remaining marketing requirements Figure 2: A readme snippet. are solved by our selection of REALbasic as our development tool. REALbasic will produce working applications with a plat- form-correct look-and-feel for all of our name of the field, so that we can refer to with the EditField. Figure 4 shows how target platforms. An about box and menus it in our templates. The second column that might look. are easy to construct and the only other would contain the replacement text, which ShipIt! now has a total of three UI will be substituted in our templates. Such a elements: a product information ListBox, list is easy to implement with REALbasic’s a templates ListBox, and an EditField for ListBox control. See Figure 1 for what the editing one template. The templates ListBox might look like. ListBox and EditField will be together in Our next requirement is that ShipIt! one window, but where will the product provide templates for the release docu- information ListBox be? We could put it in ments it generates and that these templates a separate window, but a better approach be editable so that a user can customize is a single window with a TabPanel control. them for each software product. First we The product information ListBox would be Figure 3: A template for the should consider what a template is and under one tab, and the templates ListBox readme snippet in Figure 1. then we should figure out how to let the and EditField would be together under user edit one. Let us consider a typical another tab. This design keeps each ShipIt! release document: the readme. A snippet document in one window, which simplifies of a readme is shown in Figure 2. the UI and reduces window clutter. consideration is icons. We will discuss The parts of this readme that we might The last ShipIt! requirement that we these issues in the meetings that we will want to share with other release docu- need to consider is the ability to save and hold in the days ahead. ments are the product’s name, version reuse ShipIt! documents. Manipulating That pretty much wraps things up for number, copyright, and description. files in REALbasic is simple, but we need today’s meeting. Next time we will begin Each of these pieces of information to design the ShipIt! file format. We could to layout and code the ShipIt! application should become substitution variables in just invent a proprietary binary format, but in REALbasic, starting with the main a readme template. These variables will tell unless we design it very carefully a propri- window and its two tabs. We will add the ShipIt! how to perform a substitution by etary format could be very inflexible. If, ListBoxes and EditField and write the code naming the information the user entered in a future version of ShipIt!, we need to to manipulate them. in the product information ListBox we change the file format, we might not be discussed previously. We just need to tell able to open new files in older versions of ShipIt! which pieces of text in a template ShipIt!. A better approach is to design a are variables so that it knows what to substi- tute where. Our convention will be to put template variables between ‘#’ characters. For example, a variable for the name of a product might appear as “#product#” in our templates, and “product” will also appear as the name of one of the rows in our product information ListBox (see Figure 1). Figure 3 shows how we have made a template out of the readme snippet. A release will require a number of templates like the readme snippet in Figure 3. One of our requirements is that the user be able to edit them, which can be satisfied with a ListBox and an EditField. The user will select templates with the Figure 4: Templates ListBox and EditField. ListBox and edit the selected template

RBD# 1012 40 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 41 Applescript by Dean Davis

Revealing AppleScript Controlling other applications using AppleScripts

set WhatImReturning to WhatImReturning &item ppleScript has always been one of the When this subroutine is called the script i of PlayListList &“|” best-kept secrets of the Macintosh will be executed and the trash emptied. A end repeat world. Most users know it exists but When the program is compiled, the script set WhatImReturning to WhatImReturning &last haven’t taken the steps to harness its is incorporated into the application so the item of PlayListList powers. REALbasic does a very good job actual script file doesn’t have to be distrib- return WhatImReturning at integrating AppleScript technology into uted with the application. its architecture. The second type of script can return a Now the returned string’s playlist names AppleScript allows your application to value to your program. iTunes will serve are delimited by “pipe” symbols. control, or be controlled, by other appli- as an excellent target application. In the last type of script, a value will cations. With proper programming, this Here is a script that will make iTunes be passed to the script and then a string interaction between programs can work return a list of playlist names. returned. Here is the code that will return across a network, even the internet. Letting a list of tracks in a playlist. other applications control a REALbasic tell application "iTunes" program is done using AppleEvents and set PlayListList to the name of every playlist on run {playlistname} is a topic for another article. end tell tell application "iTunes" Controlling other programs can be return PlayListList set TrackNamesList to the name of every accomplished in two different ways. The track of playlist playlistname controlling program can create and send A script, when called by REALbasic, end tell AppleEvents to a target program, or the always returns a string regardless of the set WhatImReturning to "" controlling program can call a compiled data type that would have been passed back repeat with i from 1 to (count of items in AppleScript “program.” The former is more by the actual script. This script is called as TrackNamesList) - 1 powerful but more difficult to program; any other function would be called. set WhatImReturning to WhatImReturning & the latter method is limited but easy to item i of TrackNamesList &"|" program. We will concentrate on the latter Sub Action() end repeat method with this column. Dim PlayLists as string set WhatImReturning to WhatImReturning &last A program can utilize three different PlayLists = NamesOfPlaylists() item of TrackNamesList types of scripts. The first type are simple, End Sub return WhatImReturning where the script simply accomplishes a end run task, like Emptying the Trash. The returned string is a list of playlist names separated by commas. It can then The example program (AppleScript tell application "Finder" be parsed using the CountFields and Demo.rb) utilizes these scripts to popu- empty trash NthField functions. The problem is late a ListBox with the playlist names, and end tell that if any of the playlist names contain a when a playlist is chosen it will populate comma, the returned list will be useless. the other list box with the track names via Save this code as a compiled AppleScript So the script code needs to be modified to the other script. I leave it as an exercise for and drag it into your project window in return a list with a different delimiter. the reader to write a script and the code to RB. The name of the script now becomes a make iTunes play the selected track. subroutine that can be called in code. (Hint: tell application “iTunes” AppleScript is a somewhat overlooked Double click the script icon in the project set PlayListList to the name of every playlist tool that can be very powerful in solving window to open ScriptEditor.) end tell many problems and helping extend the set WhatImReturning to “” functionality of REALbasic. ean Davis is the author of the share- repeat with i from 1 to (count of items in D ware program WeatherManX and PlayListList) - 1 a huge AppleScript enthusiast. RBD# 1013 42 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 43 Instant Cocoa by Colin Cornaby

The History of Cocoa Cocoa for REALbasic programmers

hen Apple released Mac OS X in creating powerful new technology. They with Microsoft’s new Windows NT OS WMarch last year they did something built futuristic machines called NeXT and saw NeXTStep as exactly what it remarkable. Included with the operating Cubes and a new operating system called needed. Apple bought NeXT and began system (or available for a free download) NeXTStep, which shared the Cube’s spiffy the process of bringing the code over to were powerful development tools that rival technology. It was based on UNIX and was the Mac. Apple began to experiment with the costly commercial C++ development a wonder of its time. NeXT Cubes were NeXT’s programming language (now tools of other platforms. This opened many powered by a new variation of C++, which dubbed Cocoa). They actually ported new possibilities not only for companies was “object oriented.” Objects can send Cocoa so it could run in Windows along wanting to port existing code to OS X, but and receive messages as you’ve probably with other Windows applications. also for shareware and freeware developers, found in REALBasic. NeXT’s new variation Apple also developed Carbon. Carbon and hobbyists. Now, amateurs and smaller of C++ made programming a lot easier. was simply a version of OS 9’s libraries developers could try programming without NeXT programmers quickly and easily that ran under Mac OS X. Because Cocoa paying for development tools. Not only that, built interfaces, cutting development was so different from other programming but Cocoa is one of the easiest varieties of time down to a fraction of what it had languages on the Mac, Apple realized that C. It is a powerful Mac OS X-only language been. This new language became known developers could not easily port their code that allows programmers to use advanced as Object-Oriented C. from OS 9. Carbon is the version of C++ portions of OS X. that developers use to port projects from In this column I’ll be exploring Cocoa “Classic” Mac OS to Mac OS X. Many from a REALbasic developer’s standpoint. developers still write code in Carbon so I will also highlight the main differences that both OS 9 and OS X users can run their between Cocoa and REALBasic. I’ll be programs (especially games). REALbasic assuming that you are an intermediate and programs compiled in REALbasic are RB programmer, and you know the basic also Carbon. vocabulary of RB (such as a method, a class, The history of OS X is important because an argument, etc). I believe that having the development tools have not really a firm understanding of RB is important changed. In fact, there are even varia- before trying Cocoa, as RB and Cocoa are tions of NeXTStep other than OS X that built on similar concepts. I’ll assume, Unfortunately, the NeXT cubes faced exist on other platforms. One example is however, that you know nothing about the same fate as their more recent incar- OpenStep; an open source project with an Cocoa, Mac OS X, or C. nation, the G4 Cube. Too overpriced and OS that is heavily based on NeXTStep and You might get the feeling from my overpowered for the average home user, Cocoa. Apple had an early version of OS X introduction that Apple invented Cocoa NeXT Cubes only caught on in high tech that ran on PCs called Rhapsody. recently. In fact, they didn’t. Cocoa is labs and businesses. NeXT cut back their So should you expand on the familiar probably about as old as that LC II most hardware division and began pushing surroundings of REALBasic and venture of us have wasting away somewhere. When NeXTStep as an alternative OS for (ironi- into the realm known as Cocoa? Read this Steve Jobs was exiled from Apple back in cally) x86 based PCs. column. Every issue, I will be exploring the 80’s he took some of his engineers and NeXT continued with software devel- Cocoa from the perspective of an RB user. founded NeXT, a company dedicated to opment and became fairly popular with Next issue I’ll compare RB and Cocoa side developers for its advanced program- by side. We’ll compare interface elements ming language, but still never caught on and general design principals. After I show olin Cornaby is an OS X developer. in a market that was built for Windows. you the differences and advantages of RB C Current projects include “Duality,” However, it was around this time that and Cocoa, we’ll begin doing some coding a theme changer for Mac OS X, written Apple was looking for a new OS. Apple so you can decide whether or not Cocoa is in REALbasic. needed a product that would compete something you want to learn. RBD# 1014 42 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 43 Interface Design by Toby Rush

Dealing with Dialogs in Aqua The low-down on designing dialog boxes for Mac OS X

qua, the interface component of Mac feel less like they’ve made AOS X, obviously has a lot of differences a mistake and more like the from Platinum, its OS 9 predecessor. Some computer is helping them of them are obvious changes: the Dock, the from doing something they Finder windows, the . But there didn’t mean to do. Buttons are quite a few more subtle things that are should be clearly labelled, new, many of which are a result of some and, if the dialog is asking a fundamental interface changes. question, the buttons should One place where Aqua has introduced give possible answers to that Figure 1: The Note Icon changes is in the field of dialog boxes question. This means “Yes” — those helpful windows that appear when and “No” are often preferable the application needs to communicate with to “OK” and “Cancel.” Aqua interface stan- OS 8 Human Interface Guidelines, both of the user. Dialogs designed in Platinum will dards appear to encourage longer texts in which are available from Apple’s web site almost always work perfectly when ported buttons — like “No, don’t close the window” (http://developer.apple.com/techpubs/ to Aqua, but this approach ignores a lot of — than Platinum standards did. macos8/HumanInterfaceToolbox/ design guidelines established for the new OS, Fonts. Dialog boxes should always use HumanInterfaceGuide/humaninterfac and in some cases these dialogs may cause the appropriate system font — REALbasic eguide.html). The “snap-to” guidelines confusion for the user. Taking the extra steps does this automatically if you enter that REALbasic provides are a good start, to redesign the dialogs can help avoid this “System” as the font name. To be honest, but they don’t cover everything, such as confusion and give your OS X application there are a couple of small changes: Aqua distances in between buttons and other a very professional, polished look. dialogs should use 13-point text instead objects. of the 12-point text used in Platinum, and Let’s take a look now at a few inter- Some Things Never Change Aqua alert boxes (small, one- or two-line face guidelines that have been changed Before we talk about the changes in messages used for warning or alerting the for Aqua. the new interface, let’s cover some of the user) should use the bold version of the aspects of dialog box design that apply no system font. But that’s it for variety: don’t Icons matter what system you’re using. use a different font or size just because you Both Platinum and Aqua alert boxes Language. Text in dialog boxes should think it looks good. display an icon in the upper left-hand always be non-threatening and helpful. Arrangement of controls. Good dialog corner of the window, but the two inter- “Don’t close the window until you are boxes are designed to be read from top-left faces have different criteria for choosing finished entering your preferences!” is to bottom-right. For example, in an alert the icon. short and to the point, but something box the icon is in the top left to catch the In Platinum, there are three icons which like “Closing the window now will cause user’s attention. The message appears to the can be used: the Note icon, the Caution icon, your preferences to be lost. Are you sure right of this icon, and the buttons (which and the Stop icon. The Note icon is used you want to continue?” makes the user represent the user’s response) appear in the for messages to the user that do not involve lower right, with the most probable choice any risk of data loss (see Figure 1). appearing to the farthest right. The Caution icon is used to warn the user oby Rush, a music instructor, Control spacing. While the numbers are of possible data loss (see Figure 2). T consultant, and freelance software different for each operating system, both The Stop icon is used when an action and web designer, has been using Platinum and Aqua have specific pixel cannot be completed due to a problem REALbasic since before version 1.0. His measurements for placement of buttons, (see Figure 3). current projects include The Interface icons, and text. You’ll find them specified These icons can be displayed by Mafia (www.interfacemafia.org) and in detail in the Dialogs sections of the Aqua creating a Canvas control, 32 pixels his newborn son. Human Interface Guidelines and the Mac high and 32 pixels wide, and using the

44 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 45 Alert Boxes, moveable and stationary. These The OS X Caution Icon two dialog box types are In OS 9, icons like the alert box just like the Modal and caution icon are easily available Moveable Modal varieties, as system resources which can be except that the borders retrieved using app.resourceFork and title bar have red (although this is unnecessary thanks highlights. They should to the graphic.drawCautionIcon be used for alert boxes, method). In OS X, however, it’s Figure 2: The Caution Icon regardless of which icon not quite as easy. If you’re up for a is being used. To create challenge, here’s how to find the file one of these in REALbasic, that contains the OS X caution icon. graphic.drawNoteIcon, graphic.draw simply set the window’s MacProcID to 1044 Starting from the root level of your CautionIcon or graphic.drawStopIcon (Stationary) or 1045 (Moveable). OS X startup disk, navigate through methods. Modeless. This type of dialog doesn’t the following folders: In Aqua, however, the rules are a little put the user in a mode; that is, the user bit different: because windows and dialogs can switch to another window and do System:Library:Frameworks: from different programs can be layered in other work without closing the dialog Carbon.framework:Versions:A: between one another it is important that a box. Dialog boxes of this type are rare but Frameworks:HIToolbox.framework: dialog box indicate what program it belongs they are gaining popularity — seasoned Versions:A:Resources to. To do this, the application’s icon itself interface designers like them because they is used as the icon for the alert box. The allow the user more flexibility. To create Inside that last folder, you’ll find only exception to this is when the alert a modeless dialog in REALbasic, set the a file called “HIToolbox.rsrc”. A box is warning about potential irrevers- window’s Frame parameter to “Document great many OS X icons are hidden ible data loss; in this case, the caution icon Window” and make sure the CloseBox item in there, stored in ‘icns’ format. In is used, with the application icon placed as is not checked. order to use any of the images, you’ll a small “badge” over the lower right part In Aqua, the number of dialog types has have to convert that ‘icns’ data into of the icon: been reduced to three: something usable by REALbasic. Modeless. This type is just like its coun- That’s outside the scope of this article, terpart in Platinum, and it’s still the dialog but if you have a way to do it, e-mail type of choice when appropriate. me at [email protected] and Application Modal. This type of dialog I’ll mention the solution in a future is just like the Moveable Modal dialog box article. (Thanks to ResExcellence for in Platinum, but it’s only used when the the location of this resource file!) alert doesn’t pertain to a specific docu- ment window. For example, the Open File dialog box isn’t connected to any particular Pay Attention to the Details Unfortunately, REALbasic doesn’t yet document (since it can be displayed when There are a few other small differences have a built-in way to display this caution no documents are open), while the Save between Platinum and Aqua dialog box icon. It does exist deep within the OS X File dialog box is connected to the docu- guidelines, and it’s well worth reading the System Library, but getting at it will take ment being saved. In this case, the Open appropriate Human Interface Guidelines some extra code (see “The Aqua Caution File dialog box should be an Application documents published by Apple. Because OS Icon” sidebar). Modal type. X is still pretty new, many of these subtle If you use an Application Modal dialog differences are ignored by designers rushing Window Types and include a title in the title bar (like to get their applications compiled for the In Platinum, we have five different types “Open”), it’s a good idea to precede it new system. However, the differences add of windows which dialogs can use: with the name of your application (like a level of professionalism and style that Modal. The modal dialog has no titlebar, “SurfWriter: Open”) so it’s apparent to is well worth the effort. If you make your so it can’t be moved around the screen. It which application the window belongs. program feel at home in Aqua, your users puts the user in a mode (hence the name), Document Modal. This type of dialog is will feel at home with your program. meaning the user can’t do anything else in a new addition; it is attached to an existing the program until he or she dismisses the window and appears to emerge from just dialog box. Use of this window is generally under the titlebar of the discouraged for almost all cases. existing window. This type Moveable modal. This window is still of dialog is also known as modal — the user has to dismiss the dialog a sheet, and unfortunately before doing anything else in the program REALbasic applications — but it has a title bar and can be moved cannot properly take advan- around the screen. When your program tage of them yet (windows requires a modal dialog (for a Preferences set to MacProcID 1088 will window or About box, perhaps), this is the appear to be sheets, but there one to use. are some limitations to using Figure 3: The Stop Icon this method). RBD# 1015 44 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 45 Beyond the Limits by Didier Barbas

Regular Expressions Overdrive Taking regular expressions to the next level

his article assumes that you already it is just that the initialization overhead a.append m.subExpressionString(subEx) have covered the of regular makes it slow on small chunks of text). i=len(m.subExpressionString(0))+m.subExpres T sionStart(0) expressions (RegExes), and have read Matt Neuburg’s introduction on page 24. Bionic Vision... Not! m = me.search(s,i) One common assumption made by people wend Just don’t bother who have played with regular expressions End Sub A discussion on one of the REALbasic is that, being powerful and cryptic tools, discussion lists was how to suppress extra they have some kind of bionic vision that Now, let’s test that. Imagine you want spaces in a text. The pattern that will come gives them the capacity to “see” all matches to catch the last word of each sentence in up immediately to most people is [\t ]+, at once and apply any kind of transforma- a text. Here’s what you’d do: to be replaced with a single space. It was tion to the source, from case adjustment to argued that the correct pattern should be styling. One of the factors that contributes dim r as wrappedRegex [\t ][\t ]+, since RB’s RegEx engine to this confusion is the .ReplaceAllMatches dim result(-1) as string should start matching only when there are option, which does not, on the user/ dim i, j as integer at least two tabs or spaces. However, the developer side, involve any looping. Snap speed difference on average-sized texts was your fingers and Bobby the RegEx will do r = new wrappedRegex // Our new subsclass! negligible (applied to this article [\t ][\t it. Not quite so. The .ReplaceAllMatches is r.options.caseSensitive = false ]+ is six times faster than [\t ]+). just one facility of the regular expression r.searchPattern=" ([-a-zA-Z’]+)[.!?]([\s\ While a fascinating discussion, it’s engine that does the looping for you. But r]|$)" academic since a) we’re talking microsec- it does need to loop. // the $ sign is to make sure you catch onds or milliseconds, not seconds, and b) So what if I want to have all my matches another fellow came up with an example neatly tucked away in an array or something // the last word of the last sentence using replaceAll, which was faster. I made similar? Roll up your sleeves, m’dear; it’s // which may not be followed by anything it even faster by changing inStr to inStrB, time to work. It doesn’t mean you will be // Note that result is passed as byRef and and by adding a line of code to first remove doing it all the time: this is a good example // its value may change odd-numbers of spaces. of a COUP (code once, use plenty). Subclass r.searchAll(editField1.text, result, 1) Compiled, the subroutine executes in 3.8 a regEx and provide a searchAll method. j = ubound(result) milliseconds (5.5 milliseconds without the In the project window, add a class and listBox1.deleteAllRows two optimizations), versus 18+ milliseconds subclass it from regEx. Name it wrappe- for i = 0 to j with the regular expression engine. In this dRegex, for instance. Add a SearchAll case, the use of regular expressions is actu- method as follows: listBox1.addrow result(i) ally slower, so they shouldn’t be used. next In the sample program provided on wrappedRegex.searchAll: RBD’s website (see page 4 for downloading Sub searchAll(source as string, byref a() as This is a bare-bones RegEx; don’t expect instructions), you can see that the longer string, subEx as integer) it to catch everything. The [\s\r] at the the text, the more efficient ReplaceAll dim m as regexMatch end of the searchPattern prevents the becomes (actually ReplaceAll is efficient, dim s as string RegEx engine from matching things like dim i as integer listBox1.deleteAllRows, for instance. idier has been a dilettante Cosmetic, really.

D programmer and linguist for SubEx enables the user to chose what more than 20 years. Unusual for a s = source will be stored in the array, since we often Frenchman, he speaks 11 languages, redim a(-1) care only about a piece of the match, and including Korean and PowerPC m = me.search(s) not the whole match. machine-language. while m <> nil

46 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 47 Another frequent issue connected to this coloring. For our example. we will colorize of keywords, like HTML or PHP keywords. bionic-vision problem is applying versatile all instances of certain words in a text. In the case of PHP, for instance, literal changes to a source with regular expres- strings (between double quotes) are set to sions, like changing the case of matches. Off-line syntax coloring: a different color for better discrimination. To the beginner, it appears to be one single dim r as regex Moreover, C-style comments (/* ... */) can issue, whereas in reality it is an array of 26 dim m As regexMatch spread over several lines too. The problem possible issues. You have to keep in mind is that both comments and literal strings dim c, c2 as color that regular expressions don’t describe also can contain keywords. The conflict things; they describe the way things may dim s, t As string is solved by styling comments first, then look under certain conditions. So, matching dim i, j as integer strings, and finally keywords, if these are words that start with a lower-case letter not already colored. Download the demo is easy, but asking the regular expression c = rgb(0, 0, 200) // Matches to be blue project for the source code. engine to then capitalize these letters r = new regex However, this is not really fast; it took doesn’t make sense. r.options.caseSensitive = false my Titanium PowerBook 1.8 seconds to colorize a 3.5 KB PHP script (see example r.searchPattern="(\W|^)(\w+)(\W|$)" Looping. Again and again. project). And there is no no easy way to cut s = editField1.text // Our source text Since there are 26 letters (at least in down on processing time. Here again, we English), we can loop through them and j = ubound(myList) have to look around for other tools to help change each lowercase to an uppercase m = r.search(s) us achieve the task. In this case switching letter. The code would look like this: while m <> nil from the standard editField to WasteField t = m.subExpressionString(2) // that’s (\w+) will do the trick. WasteField, designed by dim i As integer for i = 0 to j Marco Piovanelli and adapted for RB by dim r As regEx if t = myList(i) then Doug Holton, has many more features than dim m As regExMatch the standard editField, among which are editField1.selStart = dim a, b, source As string m.subExpressionStart(2) two useful functions for syntax coloring: dim t1, t2 As double editField1.selLength = findiIt and SetAttColor. With these tools lenB(m.subExpressionString(2)) we will take a slightly different approach,

editField1.selTextcolor = c since findIt does not find patterns, but source = editField1.text // Our source text exit words. Regular expressions will still be t1 = microseconds used where patterns are needed. Again, end if r = new regEx the source code is in the demo project. next r.options.CaseSensitive = true This executes in around 60 milliseconds m = r.search(s, m.subExpressionStart(0) + flat, and almost a third of that is due to r.options.ReplaceAllMatches = true lenB(m.subExpressionString(0))) For i = 1 to 26 the fact I have to back-pedal every time wend there is a match on a keyword, for fear a = chr(96+i) // a-z = ascii 97 to 122 there could be instances of this keyword b = chr(64+i) // A-Z = ascii 65 to 90 Here again, there is no way we can avoid preceded by a $, i.e. variable names like r.SearchPattern="\b"+a+"([a-z]*)\b" looping or trust the grunt work to the RegEx $date, which, while being legal, would be r.replacementPattern=b+"\1" engine. However, applied on this article, seen by WasteField as the PHP keyword m = r.search(source) the process is quite slow. myList() is a date. if m <> nil then global array that contains the list of words Here again, a combination of regular source = r.replace(source) we are looking for; in this example a, the, expressions and something else did the end if of. This list relates heavily to a dictionary trick. next t2 = microseconds editField1.text = source staticText1.text = format(t2-t1,"###,###") + " microseconds"

Originally, I had tried with a slightly different version, using (\W|^) and (\W|$) as word delimiters, but this proved to be The Beyond1 demo two to three times slower. project, available on the RBD website, lets Styling you test the various Many programs today provide syntax code examples used in coloring services, which makes editing this article and access code much easier. the full source code. There are two ways of doing syntax coloring: real-time or offline. Real-time coloring is neat, but it doesn’t involve regular expressions. Let’s start with off-line RBD# 1016 46 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 47 Intel Focus Advanced Techniques Continued from page 37 Continued from page 31 REAL ADS XCMDs und XFCNs (a black and white mouse cursor), RB will XCMDs and XFCNs are external func - import it and you can use it on Mac OS and // Get a text file from the user. tions originally designed to extend Apple’s Windows. After compiling your applica - f = GetOpenFolderItem("text/plain") Hypercard development environment. You tion, you can open your application’s file if f <> nil then can use them in REALbasic applications using ResEdit and take a look at what ID // Create the storage for the FSSpec running on Mac OS Classic like this: t h i s ‘ C U R S ’ r e s o u r c e i s a s s i g n e d . I f y o u fsspec = NewMemoryBlock(70) a d d a ‘c u rs ’ r e s o u r c e ( a c o l o r e d c u r s o r, if fsspec <> nil then #If targetwin32 note the capitalization) to your app using // Store the result of f.name // can’t work on Windows a resource file it will be colored on Mac fname = f.name #Else but not on Windows. // Create the FSSpec #If TargetCarbon Special chars err = FSMakeFSSpec(f.MacVRefNum, f.MacDirID, // can’t work on Carbon When REALbasic compiles for Windows fname, fsspec) #else it will translate all char codes from Mac to end if CallMyXCMD Windows. But some characters, like the end if #endif ellipsis (“...”), can’t be translated and will #endif result in a small rectangle on Windows. Note that I had to put the file name into the fname variable, since the Name prop- Colored Mouse Cursors erty of the FolderItem class is actually a I f y o u d r a g a r e s o u r c e fi l e i n t o y o u r function call, making it impossible to pass p ro j e c t t h a t c o n t a i n s a ‘C U RS ’ re s o u rc e RBD# 1017 f.name directly. Accessing data from a MemoryBlock is a very important part of calling Toolbox Mac OS PPC Mac OS 68k Mac OS Carbon Win32 routines. As an example, to get the file - name from the FSSpec created above, you TargetMacOS True True True False need to look back at the definition for the TargetPPC True False True False FSSpec data structure to determine where Target68k False True False False t h e d a t a y o u w a nt i s l o c a t e d . A c c o rd i n g TargetCarbon False False True False to the C or assembly language structure definitions, the file name is found at offset TargetWin32 False False False True 6 in the MemoryBlock. It can be accessed as follows: Some Notes: a) None of these constants can tell you if you are running on Mac OS X or not. dim fsspec as MemoryBlock b) In some earlier REALbasic versions there was a constant TargetJava, but the Java compiler dim filename as string was never released and this constant was removed. fsspec = DoSomethingToGetAnFSSpec() c) You can define your own boolean constants in a module. For example: filename = fsspec.PString(6)

// The “then” after the boolean constant is ignored like everything else on the line. These tips should give you a good start // This means that you can’t combine constants in an expression u s i n g D e c l a r e s t a t e m e n t s i n y o u r o w n #If GermanVersion then p rograms. Afte r some e xp e rime ntation msgbox “Guten Tag.” and reading of Apple’s documentation (if you haven’t already), you’ll be accessing the #endif power of Toolbox calls in no time!

Ta b l e 1: Target Constants in REALbasic. RBD# 1007

The Topographic Apprentice Continued from page 39 t h a t c a n b e a d d e d t o R b 3 D S p a c e . T h i s to load 3D models and present techniques RESOURCES gives you more control over lighting the for loading, placing, and viewing 3D objects. Mac OS OpenGL Libraries: http://www.apple.com/opengl/ 3D scene than using Rb3DSpace’s built-in I’ve provided a project, Rb3DSpace Demo, Windows OpenGL: http://www.opengl.org/users/downloads/ light sources. t h a t y o u c a n d o w n l o a d f ro m t h e RBD Quesa Libraries: http://www.quesa.org/info/download.html w e b s i t e ( s e e p a g e 4 f o r i n s t r u c t i o n s ) . I t Quesa Forum: http://www.quesa.org/quesa_forum.html The Next Step allows you to experiment with Rb3DSpace’s Rb3D FAQ: http://www.strout.net/info/coding/rb/ In the next column, I’ll go over the 3D p r o p e r t i e s a n d s e e t h e i r a f f e c t o n t h e Meta File (3DMF) format that Rb3D uses 3D sce ne . RBD# 1011 48 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 49 REAL ADS

FOR SALE SERVICES Made with RB RB Consultant Organize your programming life with Full-time REALbasic consultant (since Z-Write, the non-linear word processor 1 . 0 ) w i t h o v e r 2 0 y e a r s e x p e r i e n c e . for writers and creative types. Take Let me create your entire project or c o n t r o l o v e r y o u r t e x t ! F r e e t r i a l a t s u p p l y y o u w i t h a n e e d e d c l a s s o r http://www.z-write.com. troubleshooting. Joseph Nastasi Pyramid You can’t change the weather but you Designs http: //www.pyramiddesign.tv can see what it is and what it’s going 7 3 2 45 8 - 3 7 3 8 to be with WeatherManX. Check it out RB Websites a t http://www.weathermanx.com Need more REALbasic tutoring? Go to midnite.liteman offers creative solu- REALbasic University every week athttp:// t i o n s fo r yo u r Ma c . id e a S p i r a l , ou r www.applelinks.com/rbu/ —sponsored i d e a or g a n i z e r , ha s re c e i v e d a gr e a t b y R E A L b a s i c De v e l o p e r! deal of attention, and Reference Read by Erick Tejkowski’s REALbasic Worker is highly anticipated. column on ResExcellence: h t t p : / / www.midnite-liteman.com www.resexcellence.com/realbasic/

R E A Lb a s i c D e v el o p e r c l a s s i fie d a d ve r t i s e m e n t s a r e a great value! They start at just $0.15/byte (character). (A typical four-line ad runs about $20U .S.) The cost goes down the more times you run the ad! Purchase online at:

48 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com 49 REALchallenge by Sean Beach

Our First Challenge Win fame and cool prizes!

n REALchallenge, I’ll have contests a scoring system, etc. Just make sure and cursors. Compress the folder in StuffIt Ithat will appeal to both beginners that anything you add does not impede format (.sit) and email it to realchallenge@ and experienced users. These challenges the gameplay. The programming aspects rbdeveloper.com with the subject may consist of entire programs, games, should be easy if you know how to play the “REALchallenge Submission August 2002.” classes, or just algorithms. One issue I’ll game. Rock/Paper/Scissors is a two-player Make sure to include your name, company do a beginner challenge; the next may be game where each player simultaneously (if applicable), mailing address (for sending an intermediate or advanced challenge. chooses a “weapon” — either rock, paper, you your prize), and telephone number in Regardless of difficulty level, each issue I or scissors. See Figure 1 for “The Idiot’s the email. Show the world your talent! will present a new programming task and Guide to Rock/Paper/Scissors” which give you a couple months to write, debug, provides the win/lose scenarios for each Copyright Agreement and submit your solution. possible combination. By submitting your source code to us Your submission will be reviewed on the The deadline for this challenge is you grant us the right to distribute your following criteria: code style, user interface September 30th. Winners will be source code to all of our print and internet (if applicable), features, and overall func- announced in the December issue of subscribers. This means printing your tion. REALbasic Developer will choose REALbasic Developer. project’s source code and/or screenshots the best submission and I’ll feature it in a in REALbasic Developer or on the RBD future column. I may also show my own Submission Rules and website. We may release your software in solution to the task, and explain the logic Requirements either compiled or uncompiled form to our behind the code. When you feel your work is ready for subscribers at our discretion. REALbasic Winners will be presented in the submission, check it for bugs, compile it, Developer does not reserve any rights following categories: Most Efficient and make sure it runs compiled. Make sure to your code (you still own your code), Code, Best Interface (if applicable), you have not used any plugins, and that merely the right to distribute it. You will Coolest Feature, and Best Overall. Each any classes/modules are unprotected. All always receive full credit as the author winner will receive a book of their choice, code must be your own; you may not use and copyright holder. Readers of the courtesy of Peachpit Press (we’ll contact any 3rd party classes or modules. Save magazine are not permitted to use your you with a list of books to choose from), your project as a REALbasic project file. code in their own projects without your and possibly other prizes as well! Place the source in a folder, and don’t written permission. forget to include any necessary files such This Month’s Challenge as pictures, sounds, movies, resource files,

Difficulty Level: Beginner Your challenge for this month is to create a simple rock/paper/scissors game with a Rock Paper Scissors stellar interface. The emphasis is on the interface, so focus on that but do not leave Rock draw paper wins rock wins out playability and features, as those are almost as important! Also don’t forget, Paper paper wins draw scissors wins quirky features will help your score, so don’t be afraid to give it Internet play, Scissors rock wins scissors wins draw

Figure 1: The Idiot’s Guide to Rock/Paper/Scissors ean has been programming since he S was eleven and has used REALbasic since version 1.0. RBD# 1018 50 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Congratulates REALbasic Developer for the inaugural issue!

Partner with us Today!

®

Join the Made with REALbasic program: • Free space on the REALbasic CD • Free distribution of announcements to thousands of subscribers of REALnews • Free promotion on the REALbasic website www.realbasic.com/mwrb

50 Aug/Sept 2002 | REALbasic Developer | www.rbdeveloper.com Get REAL… with FRONTBASE

FrontBase™ is a robust, fully scalable, high-performance, relational database that strictly adheres to international standards. Together with your favorite development environment, you have an unbeatable combination!

FrontBase features • Easy to embed for standalone • Instant Versioning™ for zero downtime applications • Advanced security features • Zero restart time • Low Total Cost of Ownership • Backup of live databases • Virtually zero administration • Standards compliance — SQL92, • License and support programs to suit Unicode, TCP/IP… standalone to Enterprise-wide solutions

We’ve had a lot of requests for links to high-end databases, and the FrontBase Plug-in is a great example of what our users have been asking for. We believe the power of FrontBase’s database server technology is a perfect match for REALbasic’s powerful, but easy-to-use development environment. — Geoff Perlman, CEO REAL Software Inc.

FrontBase plug-in features • Incorporate into Mac OS (9/X) or Windows-based applications • Full support for REALbasic database classes • Simple administration using the built-in database management class

Using the FrontBase REALbasic database plug-in, you can create killer REALbasic applications that utilize the full power of an industrial-strength database — as a client, or with the database embedded in your application.

FrontBase Inc. — www.frontbase.com — [email protected] Los Angeles • Seattle • Copenhagen • Distributors worldwide

All product names and company names and logos mentioned herein are the trademarks or registered trademarks of their respective owners. Other products and corporate names mentioned which are trademarks of a third party are used only for explanation and for the owners’ benefit and with no intent to infringe.