Print This Article
REALbasic University: Column 089
OOP University: Part Thirteen
I hope you're enjoying creating our little SuperDraw project. When I began this "OOP University" series I envisioned a handful of columns focused on object-oriented programming, but once I actually began to write the columns I realized they were becoming mere lectures. Practical examples of OOP in the real world seem much more valuable to me, so I developed SuperDraw.
SuperDraw was originally going to stop after just a couple lessons, but as I wrote it, I discovered a couple things. First, I had an itch to improve it by making it do sophisticated things like allowing the resizing of drawing elements. Second, the object-oriented design SuperDraw made it remarkably easy to add these features.
Nothing demonstrates the latter as well as today's lesson, where we'll expand SuperDraw by adding several new object types. Adding these new objects just takes a few lines of code and, remarkably, the new drawing objects automatically inherit the behaviors of the parent object, shapeClass! It's totally sweet.
Adding a Polygon Object
The first object we'll add is a simple polygon object. A polygon is a multi-sided closed figure, and I just arbitrarily chose the shape I chose. Of course you could program your polygon object to draw a different shape that you prefer. Or, if you wanted to get extremely sophisticated, you could create a way for the user to edit and customize the number of sides and the shape of the polygon. In fact, based on how we've designed SuperDraw, it would be possible for each polygon to have a unique shape! (You'd simply store the polygon's array of drawing points within the polygon object -- the tough part would be supporting editing the shape.)
Let's get started by opening the SuperDraw project from last time and adding a new class (File menu, "New Class"). Rename the class polygonClass and set its super to shapeClass (on the properties palette).
Open polygonClass (double-click on it) and in the events area, you should find a paint event. Put this code inside paint:
This is polygonClass' drawing routine. This builds an array of horizontal and vertical coordinates and passes that to the graphic object's drawPolygon method.
Now we've added a new object, but our program doesn't know to do anything with that object yet. There are two simple steps we need to take to actually implement the new drawing element as part of SuperDraw.
First, we need to modify our interface to give us a way to add this kind of object to our drawing. So double-click on window1 and select the third (bottom) pushButton. Press Command-D (or choose "Duplicate" from the Edit menu). Since this control is part of a control array, REALbasic will automatically number it index 3. Perfect! Now change its text to "New Polygon" and just drag the button to where you want it on the window. We're done with this step!
The next thing we need to do is tell drawCanvasClass how to add this new shape. Open drawCanvasClass and go to the addObject method. After the case 2 code and before the else line, put in this:
Guess what? That's it! Our object is added. Amazingly, this object is movable and resizable right off the bat without adding any more code!
But we're not done there. Since that was so easy, let's add some more objects! We're going to move a little quicker this time, so pay attention.
Adding a Picture Object
Wouldn't it be cool if SuperDraw supported placing existing pictures? Well, why not? How hard could it be to add that?
It's actually not difficult, though there is an obstacle to overcome. But we'll deal with that in a minute. First, let's create the object class (File menu, "New Class") and name it pictClass and give it a super of shapeClass.
Open pictClass and add a property of image as picture. In its paint event, put this code:
This simply draws the picture if there is one. If not, it draws an empty picturebox frame.
We'll need to do as before and add another pushButton on window1, and we'll add another case line in drawCanvasObject's addObject method:
That's all there is to getting the picture object working. However, we don't as yet have a way to install a picture there. The simplest interface to add a picture would be to double-click on a picture box and have it prompt for a picture file to select, so let's do that.
First, we need to add a way to detect a double-click. We do that within drawCanvasObject. Open it and let's add a property: startClick as double.
Then go to mouseDown and at the very beginning (after the dim statement) add this:
This will check to see if the current click is within 15 ticks (a quarter second) of the previous tick and if so, decide it's double click.
Now we need to do something with that double click. Look through mouseDown and find the code that scans through every object. It begins with the line for i = n downTo 1. Within that loop, after the yStart = y line, insert this:
What this does is pass the double click on to the current object.
But wait! If you run this now, you'll generate an error: our object doesn't know the doubleClicked event. We need to add that!
Open shapeClass and add a new event (Edit menu, "New Event") called doubleClicked. We need a way to call that event as well, so let's add a method by the same name and for its code put in the single line doubleClicked (this triggers the doubleClicked event).
Now open pictClass and find the suddenly available doubleClicked event. Put this code there:
You'll note that for this to work our app must have defined several file types, so do that next. Choose "File types..." from the Edit menu and use the "Add..." button to add the graphic file formats you want to support. I limited mine to PICT, GIF, and JPEG, but feel free to add more if you want (these standard types are available within the "Add" dialog box's popup menu of predefined file types).
That's it! You should be able to run SuperDraw now, and if you place a new picture on the drawing area, it will initially be an empty box. But double-click on it and it will prompt you to choose a graphic file. Once you've selected one, the graphic will be displayed a drawing element within the drawing area!
Best of all, you'll notice that you can move and resize the graphic and it works perfectly! You can add as many picture objects as you want (limited only by available memory, of course). Cool, eh?
That's all we have time for today. Next week we'll make some more additions, including the ability to add text as a drawing element!
If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.
More super-easy SuperDraw enhancements!
In case you missed it, REAL Software announced that REALbasic 5 for Macintosh is finally shipping! This is the most significant rewrite of REALbasic ever (it includes a new compiler), and promises a bright future for the product. Some of the new features include better Jaguar (Mac OS X) support, new communication protocols (email, http, etc.), and new language features.
You can read more about REALbasic 5 on the REAL Software website. Upgrades start at $29.95.
If you're curious about the new REALbasic 5 features, the upcoming April/May issue of REALbasic Developer magazine features not one, but two in-depth articles on this significant upgrade.
Today we've got a note from a new REALbasic user who writes:
Thanks for the note, Christopher. Good luck in your learning adventure!
As to your questions, I'll do my best. You don't specify which project you completed: the first one we did on RBU was GenderChanger, so I'll assume that's what you're talking about.
Question 1: A module is simply a collection of code (methods), variables, and constants. The idea is that you group related routines together so that they're all in a single module, then you can reuse that module in other projects simply by dragging it into the project window.
For example, I run my own shareware company, and I want all my programs to have the same look and feel. I also want to reuse as much code as I can. By putting common code into modules and reusuing the modules, I accomplish both goals: the programs use the same code, saving me time, and because they use the same code they also look and function in the same manner.
The other significant reasons to use modules are that modules can have constants (a named "variable" that doesn't change it's value) and that any variables (properties) added to a module are global (that is, they are available to every part of your program).
Question 2: If it's GenderChanger you're talking about, the globalsModule has five items: kPrefName, which is a text constant representing the name of the preference file; openFile and SaveFile, which are methods which load and save the program's preferences; gDialogReturn, a string property which we use to pass data to and from our dialog boxes (and thus needs to be global: we can't use a property of window1 since that would only be available within window1); and gTheFileList(), an array of a our custom class, fileTypeClass. Again, since we needed our data structure to be global, we put it in a module.
Question 3: For a good explanation of classes, read the "OOP University" series I'm currently writing from the beginning. Briefly, a new class is a blueprint (template) for an object type. A new module is simply a collection of code. Modules make it easy to group related code together for reuse.
Classes also allow code reuse because you can create objects based on them and reuse the classes in other projects, but a class is just a definition of an object: it's not an object itself. Without an instance of the object to interact with, a class by itself does nothing.
In other words, if you add a module and a class to your project, give them methods called beepbeep and myBeep respectively, beepbeep will work immediately, but myBeep will only work if you create an object of type class you created, and then tell that object to myBeep.
Make sense? Does that help answer your questions?
Don't be surprised if it takes a little time to get used to the distinctions. I can write explanations until my keyboard gives out, but nothing replaces practical experience. Just try things, experiment, and one day a light bulb will go off as you suddenly understand the difference in a deep way. But that rarely happens when you're just starting out.
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.