| |||||||||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||||||||
Print This Article REALbasic University: Column 088
OOP University: Part TwelveIn our previous lesson, we made it so SuperDraw, our object-oriented drawing program, supported selecting and deselecting drawing elements. Today we'll continue to enhance the program, making it so we can move and resize them!
Enabling MovementTo add the two features we plan to add today -- object dragging and object resizing -- we'll need to check for two different types of situations. For instance, object resizing only happens when the user is dragging a corner handle. If the user's dragging in inside an element, they're just moving it. Since we want both features, let's plan ahead and code for both at the same time, though initially we won't add the resize functionality. To do this, let's add a method to shapeClass. Remember last time we added a withinMe method to shapeClass our objects will tell us if the click is inside them? Well, this time we're going to do the same thing again, except this method will check to see if the click is inside a corner handle. Open shapeClass and add a new method (Edit menu, "New Method...") like this:
The code here is simple enough: we check the area of each corner handle to see if the x and y coordinates passed are within those areas. If so, we return true. We also set a property called theHandle to either 0 through 3 to indicate which corner handle is being dragged, as well as set draggingHandle to true.
While we're here, we better add those two new properties:
Going back to our moving object problem, let's open drawCanvasClass and go to the mouseDrag event. Add in this code:
As you can see, we've left some blank area for what happens if the user drags a handle. We'll deal with that in a minute. Our two choices for dragging are either dragging a handle or dragging a drawing object, so the elseIf line above tells us we're not dragging a handle but moving an object. Actually, since more than one object might be selected, we might be moving multiple objects as part of a group selection! For moving, the first thing we do is calculate the amount of movement and store this into xStart and yStart. By virtue of the mathematical formula we use to calculate this amount, these values could be negative if moving left and/or up. Then we start a simple for/next loop through all objects, find the selected ones, and move them by that amount (we add xStart and yStart). Our final step is to reset xStart and yStart to the current mouse position -- this is vital so that next time mouseDrag is called, the correct mouse movement amounts are calculated. We obviously want the amount moved to be from the previous mouse position, not the initial click point. We conclude by redrawing drawCanvasClass, which makes sure the objects are redrawn in their new places. Go ahead and try the project: it should run and let you move objects around.
Resizing ObjectsReszing our drawing objects sounds complicated, but we've actually done most of the work already! First, in the mouseDrag event, we need to put in code for what happens during a handle drag (resize). So put this after the if currentObject.draggingHandle and currentObject.selected then line:
Once again, this calculates the movement amount, then passes this info to a new method called adjustObject which actually resizes the object. Because different corner handles drag in different directions, we change what values we pass to adjustObject. This allows the object to grow (or shrink) in the same direction as the drag. Finally, we refresh and save the current mouse position. Of course for this to work, we've got to add the adjustObject method. It looks like this:
You'll note it takes four integers as parameters, and it's defined as private. Private means that the method can only be called from within drawCanvasClass. In other words, window1 cannot call adjustObject. Why set the method to private? Well, that's an important OOP concept. By having some routines private and others public, the object can control what aspects of itself it allows other objects to see. Routines that deal with things only the object needs to modify are best set to private to avoid external routines from messing with stuff that only the object itself should touch. In this case, window1 (or any other object) has no business telling an object to resize -- that's drawCanvasClass' private business. If you run SuperDraw now, you'll find that handle clicking doesn't seem to work. That's because we didn't add a check within mouseDown for such an event! Go to drawCanvasClass' mouseDown event and after the n = objectCount line, put in this code:
This looks through all the objects. It first checks to see if object is selected -- since there's no point in bothering to check for a handle click on an unselected object -- and then ask the object if the click is within a handle. Remember, if withinHandle returns true, the object's theHandle property is filled with which corner was clicked on. That's how our drag routine knows which handle is being dragged! If the user is dragging a handle, we set currentObject to the current object in the loop, set xStart and yStart, and exit the mouseDown event (as the comment says, there's no point in continuing). Guess what? That's it! We're done! Run SuperDraw and see what you can do. You should be able to select, deselect, move, and resize any of the objects you add to the canvas: ![]() ![]() Cool, eh? Note that because of the object-oriented way we programmed this, today we didn't modify any external code (window1 or canvas1) or any of the sub-objects we created a while back (circleClass, rectClass, triangleClass, etc.) Yet our simple modifications worked with all those objects! That's the power of objects. But you haven't seen anything yet! In our next lesson we're going very quickly and very easily add several brand new object types and you're going to be amazed to see them automatically take on characteristics you didn't even realize they had! If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.
Next WeekWe add new object types to SuperDraw.
NewsThis week 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. LettersThis week we've got emails responding to last week's column. First, Georg Christmann writes with a "correction" concerning my "Debugging Tip."
You are correct that REALbasic 5 catches this: but REALbasic 4.x does not. This is a good thing to note, as RB5 catches many things that are potential problems and alerts us to them before they can become problems. I also heard from Lars Jensen, who responded to Douglas Beagley's request for 3D help.
Excellent, Lars! Thanks for sharing such a terrific resource! 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.
| |||||||||||||||||||||||||||||||||