| |||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||
Print This Article REALbasic University: Column 090
OOP University: Part FourteenLast time we added two new drawing objects to our SuperDraw project, polyClass and pictClass. Today we'll add a text object. But first, let's correct a problem from last week.
SuperDraw and REALbasic 5Several readers reported to me that last week's SuperDraw project won't work in REALbasic 5. This is true. REALbasic 5 is a lot more sensitive to naming conflicts than previous versions, so things that you could get away with in 4.5, RB 5 prevents with an error message during compilation. In this case the issue is that in our shapeClass object we have both a doubleClicked method and a doubleClicked event (they have the same name). It had occurred to me that might be an issue, but REALbasic didn't complain and the program worked, so I figured it was fine. I actually wrote this code a while back before the RB5 final was released, so I hadn't tested it under 5 yet. (I promise future RBU projects will be compatible with RB 5.) The solution is simple: open shapeClass and rename the doubleClicked event (not the method) to doubleClick. Then -- very important -- open the doubleClicked method and change its code to:
This simply changes our event to be called doubleClick, and we make sure our method calls that. With that change, the program runs fine in REALbasic 5 (including today's cool addition).
Adding a Text ObjectLet's begin by adding a new class (File menu, "New Class"). Name it textClass, and give it a super of shapeClass. Open it up and let's add some code. First, add two properties (Edit menu, "New Property"):
These properties will contain the settings used for the text object. Next, use this code for the paint event:
As you can see, this sets the text font and size and draws the text. But there are two methods called here. The first is one called init, and it sets the default text and textfont values. Add a new method (Edit menu, "New Method") and put in this code:
Next, we need to add a method called calcTextSize with g as graphics as a parameter that returns an integer:
This function calculates the largest size text that will horizontally fit within the shape's height and width. It does this using REALbasic's stringHeight method, which returns, in pixels, the height of the passed text. Since we also pass width to that method, stringHeight takes into account any word wrapping that will happen based on the amount of text and the width of the text area, reporting the height with the correct number of lines. Then we compare that to make sure we're not taller than the height of our box. The function starts with a size of one, and enlarges that one by one until the text won't fit. Then it returns the size minus one (a size that will fit). You'll notice that this function therefore makes the size of the text as big as the shape of the object. Therefore if we change the size or shape of the object, the text size will change. Now we also must have a way to let the user edit the text. We'll do this with a simple dialog box. But first let's add the code within the doubleClick event:
This does several things. First, it does something critical: it establishes a link to itself within the dialog window. With that link, the dialog will be able to communicate with the textClass object. Without that we'd have no way of knowing when the user changed the text! Second, we must tell askTextDialog the text to edit and the selected font. Finally, we display the dialog. Code in the dialog itself will handle passing any changed values back to our textClass object. Add a new window (File menu, "New Window") and give it these settings: ![]() Make the window look like this: ![]() Name the popup fontPopup. The text field is EditField1; the cancel pushButton is cancelButton; and the okay pushButton is okButton. Now for some code. Add a property, parentObject as textClass. That property contains a pointer back to the textClass object that opened the dialog. Next, add a method called choosePopup with this code:
This method takes a string as a parameter and it searches through the fontPopup list to find the passed font. When it does, it sets fontPopup menu to that font. (This is basically the equivalent of the user selecting that font on the popup menu.) In the controls section, we'll need to add code to several controls. For cancelButton, we add self.close as the code. For fontPopup's open event, put this:
This is code from the RB user's guide and just fills the popup menu with a list of the currently installed fonts. In okButton, put this in the action event:
Since there's a theoretical possibility that parentObject might be invalid (nil), we check for that first. If it's valid, we use it to set the calling object's text and textFont properties (if it was invalid, this code would cause a nilObjectException and crash). This passes the changes (if any) back to the textClass object that opened the dialog. Now we're almost finished. We just need add another pushButton on window1: duplicate the bottom one and change its text to "New text" and make sure its index is 5. Finally, add another case statement to drawCanvasClass' addObject method like we did last week:
This will create the new textClass object when you click the new pushButton. Go ahead and run SuperDraw and if you did everything right, you should be able to add a text object, move and resize it, and edit it and change its font: ![]() Isn't that cool? We've now created an editing canvas that supports multiple kinds of drawing elements, a few basic ones, but also sophisticated ones like imported pictures and editable text. And this is actually a useful tool: I've got an invoicing program and I'm going to use these classes to add the ability for the user to edit invoice layouts (position text fields, import logos, etc.). Best of all, because this was created in an object-oriented fashion, it's easily modified and enhanced. Additional object types can easily be added. There are a few small enhancements we need to make to finalize SuperDraw, as well as adding the important ability to load and save documents. We'll handle that in our next lesson and that will end this portion of OOP University. If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.
Next WeekWe finish SuperDraw.
REALbasic Developer 1.5 PreviewThe next issue of RBD is being printed right now, and I'm here to give you a sneak preview! ![]() Our primary focus in this issue is REALbasic 5, with not one, but two in-depth articles. REAL Software engineer Joe Strout explains the new compiler that is at the heart of the new environment. And even if you think you know RB5, Matt Neuburg is sure to reveal some secrets in his detailed round-up of all the new features. We've got more from Joe as he brings us a fascinating look at path-finding algorithms. The obvious use is finding a way through a maze, but you should study this article as the techniques are there for many other uses. For our Postmortem, Jacob Lauritzen writes about SmartLaunch, and I interview Michael Herrick, author of Spamfire, one of the most successful Made-With-REALbasic products on the market. In other news, I wanted to bring a little fun into the magazine, so I'm pleased to announce Hacker, an original comic strip created just for RBD from Dan Wilson (issue 1.2 cover artist). It's about the daily life of an enthusiastic REALbasic programmer. We'll feature a new cartoon in every issue! Plus, we'll have all our usual columns and topics, news and reviews. If you aren't a subscriber yet, order today and don't miss out!
LettersThis week Joe Rice writes with an unusual problem:
Unfortunately what you are wanting to do is complicated. You're really wanting to write your own compiler (a compiler translates text code into executable machine language). This isn't something easy to do in any language, let alone REALbasic. However, there are some options open to you, depending on the kind of app you are wanting to create. First, if your app is simply changing some settings or information inside the "new" application, it's possible you could store that info inside the app's resource fork. Then your REALbasic "app editor" could make a duplicate of the standard app, edit those resources and change them, and thus create a "new" application. This would work if your editing app were, let's say, creating a new application with the user's logo and name and address info built-in. Another option that's similar but more powerful would be for your template app to include all the elements required for all versions of the app. It would load the active settings from a description file (perhaps an XML file) and only display those elements. As a simple example, let's say your user app has two versions of a certain dialog box. We'll call them DialogA and DialogB. In your question, you wanted the user to be able pick which dialog they wanted to use and compile a new application with that dialog active. However, if you went the with XML configuration dialog, the template app would include both options, but based on the settings inside the definition file it would only use the one the user had selected. The disadvantage with this approach is that the template application might be much larger (it has to include all the elements for every possible version of the app), but from the user's perspective the end effect would be the same as a custom app. A third approach which might also work would be to go with RBScripts as a plugin. I explained about this in RBU 071. RBScripts are external text files of RB code which isn't compiled until while your program is running. You could use the same approach to install a RBScript modules into the template application. These scripts would do different things. When the program is run, the way it works would vary according to the installed scripts. This would give you a way of customizing it externally, allowing you to duplicate the template app but change the installed scripts it uses. Sorry there isn't a better solution, but hopefully one of these three approaches will work for you. If I'm missing something or someone out there has another approach, please let me know! 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.
| |||||||||||||||||||||||||||