REALbasic University Resources:

RBU: Glossary Defines common REALbasic programming terms
  Archives Previously published columns
Translations: Dutch Courtesy of Floris van Sandwijk
  Japanese Courtesy of Kazuo Ishizuka
  Chinese Courtesy of Dong Li
  RBU Translation Guide Information on Translating RBU into other languages
Books: Matt's Book (2nd Edition!) Ideal for experienced programmers
  Erick's Book Best for beginning programmers
Websites: Mother Ship The publisher of REALbasic
  RB Webring Links to hundreds of REALbasic websites
  RESExcellence Another REALbasic programming column
  REALbasic Developer Magazine The premiere source for REALbasic instruction.

REALbasic University is Sponsored by

Make your Mac do what YOU want it to. Create games, utilities, cool Mac OS X tricks. Download REALbasic now and create your own software.


Print This Article

REALbasic University: Column 103

OOP University: Part Twenty-Five

In lesson 099 we discussed the challenges in developing a progress bar dialog. While it seems simple, there are a number of obstacles, especially if you allow the user to cancel the action. Since a progress bar is usually in a different window, how do you tell the action to stop?

Today we'll create a reusable progress bar system.

A Reusable Progress Bar Dialog

Progress bars are found throughout all sorts of programs, so it makes sense to design a system that's reusable -- that way you only have to code it once. REALbasic makes this kind of thing remarkably easy as it lets you import external items into multiple projects.

You do this by dragging an item into a project window while holding down the Command and Option keys. This links in the external item, but the code is not part of your current project: it's stored externally, so if you fix a bug in that code, all projects that link to that external code are updated as well!

We'll begin by creating a basic dialog box. Within a new project, add a window (File menu, "New Window") and name it progressDialog. Make it 300 pixels wide by 180 tall. Set its Frame property to Movable Modal. Like this:

Now because we want to make this progress dialog as flexible as possible (so it can be used in many different programs), we'll build it as a dual progress bar dialog. But as you'll see, it will be easy to use as a single progress bar if we want.

So let's begin by adding a couple progressBar objects and four staticText objects to progressDialog. Arrange them like this:

Note how the second bar and text label are indented from the left side.

The progressBars should be named (from top to bottom) pBar1 and pBar2, and the staticTexts should be named mainLabel, subLabel, statusLabel, and cancelText. The first two should be textSize 0, the bottom two textSize 10.

Now let's open the Code Editor for progressDialog (Option-tab while window is selected) and add a new method (Edit menu, "New Method..."). Give it the name init and on the parameter line put this:

  
title as string, singleBar as boolean, cancellable as boolean

This is going to be our initialization routine for the dialog. Prior to displaying the window, you first call this routine and establish the window's title, whether there are one or two progress bars, and whether the operation is cancellable or not.

Here's the code for init:

  
const heightDif = 40

gPleaseStopProgress = false
self.title = title
cantCancel = not cancellable
if cantCancel then
cancelText.text = "This operation cannot be cancelled."
end if

if singleBar then
// Hide unused elements
pBar2.visible = false
subLabel.visible = false

// Adjust postioning
statusLabel.top = statusLabel.top - heightDif
statusLabel.left = mainLabel.left
statusLabel.width = mainLabel.width
cancelText.top = cancelText.top - heightDif

// Resize dialog
self.height = self.height - heightDif
end if

The above should be self-explanatory, though we haven't covered some of these properties yet. For now, just go ahead and put this in, and I'll explain later when we add these properties. The main thing that happens here is we adjust the dialog based on whether there are one or two progress bars. If there's only one, we move the bottom text labels up (and remove the indent on statusLabel) and make the whole window smaller as well.

We also set a local property called cantCancel. We might as well add that now, as long as we're thinking about it. Add a new property to progressDialog (Edit menu, "New Property") like this: cantCancel as boolean.

Now we add another method. This one is called startProgress and takes theMessage as string, theMax as integer as parameters. This is the routine that is called to establish the initial message and maximum size of a progresss bar.

  
mainLabel.text = theMessage
statusLabel.text = ""
pBar1.value = 0
pBar1.maximum = theMax
self.refresh
self.show

Actually, there are two of these, almost identical. The second is startSubProgress and takes the same parameters. Here's the code for it.

  
subLabel.text = theMessage
statusLabel.text = ""
pBar2.value = 0
pBar2.maximum = theMax

As you can see, these routines are very simple: they set the maximum size of the progress bar, and establish an initial text message display. The only difference is that startProgress works on pBar1 and startSubProgress works on pBar2.

Next we'll add a method that will be called any time the progress bar needs to be adjusted. This is a simple method that takes the text for the display message and the amount that should be added to the progress bar's value property.

  
sub updateProgress(theMessage as string, addAmount as integer)
mainLabel.text = theMessage
pBar1.value = pBar1.value + addAmount
self.refresh
if not cantCancel and userCancelled then
cancel
end if
end sub

Again, the method is simple. We pass on theMessage as the text to be displayed, and we add the amount passed to the progress bar's value.

Since this first method only updates pBar1, we'll need a second method for pBar2:

  
sub updateSubProgress(theMessage as string, addAmount as integer)
subLabel.text = theMessage
pBar2.value = pBar2.value + addAmount
self.refresh
if not cantCancel and userCancelled then
cancel
end if
end sub

You may notice that both of these methods include a self.refresh command. This forces the window to redraw after we've changed some of the settings. This is important, because sometimes REALbasic gets so busy doing the actual task (usually within a loop, for instance) that it doesn't update the progress bar window as often as you'd like.

Note that both of these routines include a very important piece of code: as they update, they check to see if the user has cancelled the operation. Since not all operations are cancellable, we first check to make sure that cantCancel isn't true (if it is true, we don't bother checking to see if the user has cancelled).

If the user has canceled, we pass control to a method called cancel:

  
gPleaseStopProgress = true

This is a very simple method that sets a global property that tells us the user wants to cancel the operation. Important Note: you'll have to make sure this global property is available within every application you write that uses this dialog. More on this in a bit.

Finally, we must add a method to stop the progress. This will be called either after the operation is finished, or when the user has cancelled it. Add a new method called stopProgress and give it this code:

  
// This is called when dialog is going to
// be closed by calling routine.
pBar1.value = pBar1.maximum
pBar2.value = pBar2.maximum
self.refresh
self.close

This simply sets the two bars to maximum (so the user briefly sees the bars full) and closes the window.

Surprisingly, we're almost done with our reusable progress bar dialog. There's only a couple more things to add.

In the window's open event, put this:

  
#if targetWin32 then
cancelText.text = "Press ESC key to cancel."
#endif

This simply changes the text displayed by cancelText to be more appropriate for Windows users (who don't have a Command key).

Finally, in the keyDown event, add this:

  
if not cantCancel and userCancelled then
cancel
end if

This just keeps watching for the user pressing the cancel keys (Command-period on the Mac, Escape under Windows). If the user does want to cancel, we call our cancel method.

That's it! The reusable progress bar dialog is finished. You can drag a copy of the progressDialog window from your project window to your hard drive and later drag it into any projects you want. Ideally you'd link to it in those other programs (using the Command-Option drag thing) so that you only have one resuable progress bar dialog for use in all your programs.

Next time I'll demonstrate how to actually use this dialog.

If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.

Next Week

Using our resuable progress bar dialog.

News

REALbasic Developer 2.1 August/September 2003 Published

The latest issue of REALbasic Developer magazine is now available! The August/September issue features at ton of great stuff.

First, have you heard the exciting news that the next version of REALbasic will support compiling to Linux? RBD has an exclusive interview with the folks at REAL Software and we get the 411.

Speaking of REAL Software, many of you have probably heard David Grogono's name or exchanged emails with him, but exactly who is he? Our interview with REALbasic Product Manager David Grogono reveals all. Find out how he left a life as a sailboat captain to captain REALbasic.

3D guru Joe Strout is back, this time with wild real-time mesh deformations. His example project shows how to simulate cloth flapping in the wind. It's impressive.

Then we've got a double bill from Charles Yeomans. First he explains what you need to know about REALbasic 5's new Extends and Assigns keywords, and then he's got an excellent article on how to add a neat "recent items" menu to any program.

And of course along with those articles we've got news, reviews, and all our regular columnists!

Subscribers should be receiving their issues this week, and if you aren't a subscriber, become one! You can even order all the back issues if you don't want to miss anything.

Letters

This week we've got a question from a reader who prefers not to be named. His question is about resources (in the Mac resource fork of a file):

I've got a picture in a resource under the ID of 129. The resource's filename is Pictures. How do i call that picture and set it to a variable? And when this is done, how would I display that picture? I'm sorry if you addressed this in previous RBU lessons but i'm too lazy to look through them.

Look at this project file. It's untested, but should work. I created a method that returns the picture from the file. If the picture isn't found, it returns nil. Here's the method:

  
function loadPicture() as picture
dim f as folderItem
dim rf as resourceFork

f = getFolderItem("").child("Pictures")
if f = nil then
return nil
end if

rf = f.openResourceFork
if rf = nil then
return nil
end if

return rf.GetPicture(129)
end function

Currently this example puts the returned picture into the backdrop property of a canvas, but you could just as easily store the picture into a property or do something else with it.

For example, if the window had a property named:

  
thePicture as picture

you could write:

  
thePicture = loadPicture

to store the picture resource 129 into that variable. However, you would be required to initialize the variable with the newPicture command first. See RB's docs for that.

Once you've got the picture in the variable, you can display it either inside a canvas object or inside a window like this:

  
canvas1.graphics.drawPicture thePicture, 100, 200

or

  
window1.graphics.drawPicture thePicture, 100, 200

where the last two numbers are the horizontal and vertical coordinates on the object where the upper left portion of the picture will be displayed.

You could also modify this method to accept an integer as a parameter, then have it return the picture number you specify. So loadPicture(129) would return the picture with id 129. As it is now, the routine's specific to this picture only.


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
is an author, philosopher, graphic designer, photographer, film director, soccer fanatic, and programmer (among other things). He writes for MacOpinion, runs his own software company, Stone Table Software, which sells the revolutionary Z-Write word processor, and is Publisher and Editor of REALbasic Developer. He lives in Northern California with his cats, Mischief and Mayhem, and is rapidly running out of free time.

See the REALbasic University Archives


REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.

Email This Article - Comment On This Article

.

Reader Specials

Server Racks Online:
Apple Xserve CompatibleServer Racks and Universal Network Racks
42U KVM Switch Solutions:
High-End Mac and Multi-Platform KVM Matrix switching solutions!
Digital Camera Online:
Great prices on Digital Cameras and accessories!
KVM Switches Online:
Great prices on Mac KVM Switches from the leading manufacturers!
LCD Monitors Online:
Great prices on LCD Monitors from the leading manufacturers!
LCD Projectors Online:
Shop online for LCD Projectors from the leading manufacturers!
USB 2.0 Online:
Great prices on USB 2.0 products from the leading manufacturers

Serious Business Software:
Accounting, Sales, Inventory, CRM, Shipping, Payroll & more!

KVM Switch solutions for MACs:
DAXTEN is a KVM switch, KVM extender and monitor splitter specialist for PC, SUN and MAC applications from name brand manufacturers - offices worldwide.

The "Think Different Store: The iPod Accessories Store - iPod cases, iPod mini, iPod photo, speakers, itrip, inMotion, Soundstage and all other iPod accessories

Earn Cash with the ThinkDifferent Store Affiliates Program

Need A Web Site?
Applelinks Web Hosting Starting at 19.95 a Month

iTunes_RGB_9mm

.

iTunes_RGB_9mm

Cool Mac Gear


iPod 1G-2G
iPod 3G
iPod 4G
iPod Mini
PowerBook-iBook
Keyboard Skins
Garageband