| |||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||
Print This Article REALbasic University: Column 027
Creating Custom Classes IILast week we explored how to create your own custom classes that can be easily reused in multiple programs. We built two examples of classes that were good for demonstration purposes but aren't especially useful. Today we'll create a very useful EditField class that will automatically (transparently) support unlimited undos! As usual, you can download the complete example project here, or follow along and recreate it step-by-step. (This example project includes the classes from last week as well.)
UndoEditFieldClassHave you ever had a dialog box with an EditField in it and thought wouldn't it be nice if the dialog box supported undoing? Of course, adding undo capability isn't easy, and who wants to fuss with all that? Well, if adding undo to an EditField was just the matter of dragging a class into your project and changing the super of your EditField to UndoEditFieldClass, your dialogs might soon all have undo capability. The good news is that it really is that easy. We'll start by creating a new class (Edit menu, choose "New Class"). Let's name it undoEditFieldClass and set its super to "EditField." Next, add a property to the class. (Double-click on it then choose "New Property" from the Edit menu.) Add undoString(0) as string. This variable is going to store the undone text as an array of strings -- that will give us unlimited undos. Think about the basic steps of an undo system: we must keep track of what the user is doing, save the old value, and restore the old value when the user chooses the Undo command. So the first part of this -- watching what the user is typing -- is done in the KeyDown event. Go to the KeyDown event and put in the following code: undoString.append me.text All this does is save the contents of the text field to the undoString array. The append method automatically allocates more space in the array, adding the passed text as the last item. Next we'll need a menu command for the Undo command. Since REALbasic automatically creates a menu item for the Undo command we don't have to create that, but as long as we're here, let's add a very useful "Select All" command to our class. Open your project's Menu item and click on the Edit menu. At the bottom of the menu that drops down is is a blank rectangle. Click on it and type a hyphen ("-") and press return. That adds a divider line to the menu. Click on the blank rectangle again and type "Select All" and press return. This time, while the Select All item is still highlighted, go to the Properties palette and type an "A" in the CommandKey field. Your finished menu should look like this: ![]() Excellent. Now let's enable the menuitems. Put this into the EnableMenuItems event of undoEditFieldClass: if uBound(undoString) > 0 then What are we doing here? First, we're enabling the Undo menu command as appropriate: if our undo buffer is empty (undoString has no items in it) we don't enable the command. Next, we're changing the name of the Undo menu command to reflect which undo event we are doing and the number of undos we have saved. Finally, we check to see if all the text in the field is already selected. If it's not we enable our Select All menu. Pretty simple, as you can tell. Let's add those menu handlers now. Go to the Edit menu and choose "New Menu Handler" and from the popup menu that's offered, select EditSelectAll. Do that again and add the EditUndo handler. Here's the very simple code for selecting all the text (put this in the EditSelectAll handler): me.selStart = 0 This just puts the start of the selection to the very beginning of the EditField and sets the length of the selection to the length of the EditField's text -- meaning that all the text in the EditField is selected. (Remember, we're working inside a variation of an EditField class: me refers to the current object, i.e. the current EditField.) Now go to the EditUndo handler and type in this: // Undo to saved values This does three things. First it puts the text saved in the final item of the undo buffer into the EditField -- basically going back to the most recent version saved. Then it reduces the size of the undo buffer array (undoString) by one, deleting the last item. Finally, we move the cursor to the end of the EditField. Guess what? That's it! Our undoEditFieldClass is finished! To try it, add an EditField to a window and put its super to "undoEditFieldClass". (If this is in a different project, you'll have to drag a copy of undoEditFieldClass into the project first.) When you run your program, all typing in the EditField is remembered, so you can easily undo your way back to your first character. Note that this class isn't efficient: we save the text of the entire field every time the user types, meaning that if the user typed a whole sentence, we'd have several dozen copies of that sentence in memory. Of course for a simple EditField in a dialog box where the user just puts in a few characters this isn't a problem: but you probably wouldn't want to use this system for a word processor (or you'd limit the number of undos to a reasonable 10 or 20).
Now What?Now that you've got the example project finished, you can drag the classes to your desktop to create modules you can drag into future projects. So you'll be able to instantly add simple undo capabilities to all EditFields in your programs! To do that, just drag undoEditFieldClass into your project and then -- be sure to do this -- set the super of all EditFields you want to have undo capability to undoEditFieldClass. You obviously could also do this with boxClass and onOffClass (from last week), except they aren't quite as useful (though they are good starters for your own useful variations).
Next WeekWe begin our next major project, RBU Pyramid, an implementation of a classic solitaire card game!
NewsREAL Software released the latest upgrade to REALbasic last week, RB 3.5. This new version adds some interesting features:
RBU's TakeI generally stay away from the RB beta releases so I haven't had time to thoroughly explore these new features (you can download some demo projects from the REAL Software website to see the new features in action). On the surface, these features sound great, but in reality I wonder how often they'd be used. The Office Automation feature requires you have Microsoft Office, and my reading about it suggests there are a number of limitations (which will eventually be fixed). I can't quite figure out what to use this for anyway -- I'm trying to purge my system of Microsoft products, not become more dependent upon them. Regular expressions is a much-requested feature, but I doubt it works with styled text (which limits its appeal to me though you may like it). RBScript, on the other hand, is intriguing. Theoretically you could use it to add a plug-in type feature for your program (instead of adding AppleScripts to your program, plug-ins would be written in REALbasic syntax). Likewise, the 3D engine is an excellent addition, but I'm a bit intimidated by complex graphics (especially 3D): we'll have to see how easy it is to use. More disappointing is that long-standing bugs and limitations still exist; while I commend RS for releasing frequent upgrades, I wish they'd fix known issues and enhance existing tools (like the ListBox and EditField controls) before adding wild new features that few people will use (like Office Automation). On the whole, however, it's an excellent upgrade, and reasonably priced at $29.95 for the standard version (though the professional upgrade is a more costly $89.95).
LettersThis week we hear from Cap, who has a question about creating games in REALbasic.
Excellent timing, Cap! I'm not sure why people turn to other tools for games. Admittedly REALbasic has problems with animation and its sprite engine has known bugs (especially under Mac OS X), but unless you're creating a 3D shoot-'em-up, I don't see those bugs as killer items. (And when you look at all the low-level optimization the C++ guys do to get a few extra frame rates out of those games, coding a 3D game in RB is rather ridiculous.) Personally, the kinds of games I want to write are simple dice and card games, logic puzzlers, etc., which are ideally suited for REALbasic. In fact, our next project -- which begins next week -- is a card game. It's a fairly sophisticated version of Pyramid and it will probably take us a month or two to get through, but I hope it will inspire others to use REALbasic for game programming, especially for simple yet enormously entertaining classic games. Keep those letters coming! I may not answer your question immediately, but I'll hopefully get around to it in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise I'll assume it's fair game.) About the Column REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers. Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.) About the Author See the REALbasic University Archives
REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.
|
. |
| |||||||||||||||||||||||||