Malcolm Cadman wrote: > Has anyone written a progress bar in SuperBASIC ? > > To inform the user of the progress made during a longish operation like > processing a file. > > A graphical presentation would also be useful. > > 0% ****...............100% > > ( Crude ASCII illustration above ). Here are a few ideas for progress bars which I have written. They are graphical bars in the top left corner of window channel #0. The first listing sets out the theory for an elapsed time bar, which you can study and adapt to your own needs. The actual theory is that you decide on the width of the bar in pixels, then take the total amount of time that is to represent (in seconds) and divide the width by the number of seconds to get the number of pixels per second, which may well be a non-integer like 1.5 pixels per second. Then for each call to the progress indication, you multiply the elapsed time by the number of pixels per second and use BLOCK to draw a bar of that width. A little bit of care is needed if the bar is to be width 0 pixels as not all versions of S*BASIC will draw a BLOCK of 0 piel width without an error, also you may wish to draw a block of the full width in the background colour if elapsed time is 0 and the indicator is likely to cycle round to 0 again during operation (see example 3 below). The REMarks should show how it works.
100 REMark graphical progress bar 110 elapsed_col = 4 : REMark elapsed time shown in this colour 120 background_col = 2 : REMark total time length shown in this colour 130 bar_width = 100 : REMark pixels representing total time 140 bar_height = 10 : REMark pixels height of bar 150 CLS #0 : INPUT #0,'Time to represent > ';time : REMark seconds 160 pix_per_second = bar_width / time : REMark number of pixels representing one second 170 CLS #0 : PRINT #0,'0%'; 180 BLOCK #0,bar_width,bar_height,12,0,background_col : REMark this bar shows the full time period 190 CURSOR #0,12+bar_width,0 : PRINT #0,'100%' 200 start_time = DATE : REMark time at which we started, err, timing 210 REPeat loop 220 elapsed_time = DATE-start_time : REMark how far have we got? 225 elapsed_pix = pix_per_second*elapsed_time : REMark how many pixels represent this time? 227 IF elapsed_pix > bar_width THEN elapsed_pix = bar_width : REMark might just get larger than maximum time if we check at the tick of a second 230 BLOCK #0,pix_per_second*elapsed_time,bar_height,12,0,elapsed_col : REMark the elapsed time bar 240 IF elapsed_time >= time THEN EXIT loop : REMark finished, exit 250 END REPeat loop 260 PRINT #0,'Time finished.' *End of listing one* The next listing shows how to generalise the progress bar for a set number of operations, not just time based. The procedure SETUP_PROGRESS_BAR initialises things, then the SHOW_PROGRESS routine has two parameters, the first is the number of steps completed, the second the total number of steps to be represented. Although the example again reveolves around time, this modification allows it to be more easily adapted to show 'steps' rather than time units, e.g. if you know you have to write 10,000 strings to a file, you could insert a call to SHOW_PROGRESS strings_done,10000. If this slows things down too much, a simple MOD test will allow the loop to only call the routine as often as you feel it needs to be updated (e.g. update only every 100 string writes): IF (strings_done MOD 100) = 0 THEN Show_PRogress strings_done,10000 100 REMark graphical progress bar 110 CLS #0 : INPUT #0,'Time to represent > ';time 120 Setup_Progress_Bar 130 start_time = DATE 140 REPeat loop 150 elapsed_time = DATE-start_time 160 Show_Progress elapsed_time,time 170 IF elapsed_time >= time THEN EXIT loop 180 END REPeat loop 190 PRINT #0,'Time finished.' 200 : 210 DEFine PROCedure Setup_Progress_Bar 220 done_col = 4 230 background_col = 2 240 bar_width = 100 250 bar_height = 10 260 CLS #0 : PRINT #0,'0%'; 270 BLOCK #0,bar_width,bar_height,12,0,background_col 280 CURSOR #0,12+bar_width,0 : PRINT #0,'100%' 290 END DEFine Setup_Progress_Bar 300 : 310 DEFine PROCedure Show_Progress (done,steps) 320 IF done > 0 THEN BLOCK #0,done*bar_width/steps,bar_height,12,0,done_col 330 END DEFine Show_Progress Finally, a silly example showing how to use three progress bars to represent a weird kind of digital clock. Three progress bars represent hours elapsed today, minutes elapsed and seconds elapsed. Compile this and execute it (unlocked if using pointer environment to allow it to overwrite the display EXEP sillyclock_obj,U) 100 REMark graphical progress bars used as silly digital clock! 120 Setup_Progress_Bars 130 start_time = DATE 140 REPeat loop 150 t$ = DATE$ 160 hr = t$(13 TO 14) : Show_Progress hr,24,0 : REMark hours 170 mi = t$(16 TO 17) : Show_Progress mi,60,1 : REMark minutes 180 se = t$(19 TO 20) : Show_Progress se,60,2 : REMark seconds 190 END REPeat loop 200 PRINT #0,'Time finished.' 210 : 220 DEFine PROCedure Setup_Progress_Bars 230 done_col = 4 240 background_col = 2 250 bar_width = 100 260 bar_height = 9 : REMark allows gap between lines 270 CLS #0 280 REMark hours bar 290 PRINT #0,'0'; : BLOCK #0,bar_width,bar_height,12,0,background_col 300 CURSOR #0,12+bar_width,0 : PRINT #0,'24' 310 REMark minutes bar 320 PRINT #0,'0' : BLOCK #0,bar_width,bar_height,12,10,background_col 330 CURSOR #0,12+bar_width,10 : PRINT #0,'60' 340 REMark seconds bar 350 PRINT #0,0 : BLOCK #0,bar_width,bar_height,12,20,background_col 360 CURSOR #0,12+bar_width,20 : PRINT #0,'60' 370 END DEFine Setup_Progress_Bar 380 : 390 DEFine PROCedure Show_Progress (done,steps,bar_number) 400 IF done = 0 THEN 410 BLOCK #0,bar_width,bar_height,12,10*bar_number,background_col 420 ELSE 430 BLOCK #0,done*bar_width/steps,bar_height,12,10*bar_number,done_col 440 END IF 450 END DEFine Show_Progress A possibility with timed progress bars is to compile them with QLiberator as external procedures, LRESPR those and start them with the name of the command generated followed by an exclamation mark which will allow them to multitask, although they'll be suspended if their windows are buried. This email has turned out a bit longer than I thought (sorry everyone), but might give you a clue as to how to write one to suit your needs. -- Dilwyn Jones