tips:revmedia:r72

Gasgauge

Published ByDateVersionKnowledge LevelKeywords
Revelation Technologies17 JAN 19912.XINTERMEDIATEGASGAUGE, STATUSLINE, VISUAL, INDICATOR

When executing a lengthy process it is helpful to provide the user with an indication that the process is still working. The user may also want some indication of how much longer the process might take.

This bulletin describes a utility program that you can use to post a "gas gauge" on the Advanced Revelation status line. The R/BASIC code for this routine appears in Figure 1.

The gas gauge is a visual indicator of how far along the current process has proceeded. It does not in any way make a process operate faster (in fact, there is a slight performance overhead in using such a program), but there is a great psychological benefit to the user in being able to see an indication of the status of a process.

The gas gauge in this utility is much like that used for the SELECT command. There is a bar that creeps along the third cell of the status line so that it reaches the right-hand edge when the process is complete. In additions there is a numeric percentage-done indication that accompanies the gas gauge bar.

Two extra features of this utility are:

  • It offers you the opportunity to include text that describes the process in action.
  • It allows you to specify what character you which to use to create the status bar.

For example, you might want to have the word "Updating …" in the status bar, and have the gas gauge be made up of asterisks. At 90% done, cell 3 of the status line might then look something like this:

Updating ... 90%³********************

The size of the area allocated to the gas gauge bar is automatically adjusted to accommodate the length of your optional text.

You can call the gas gauge utility from your own applications as an R/BASIC subroutine. GASGAUGE takes three parameters:

GASGAUGE(COUNTER, COUNT, USER_BAR)

Where

COUNTERis the current count for the process. For instance, in a report program this would be the count for the current record.
COUNTis the total count for the process. For example, in a report program this would be the total number of records in the file or select list.
USER_BARis the character that will creep across the screen to form the gas gauge. The default is a solid block.

To use GASGAUGE, you must call the routine three times: to set up the status line, to update it, and to clean up at the end. Each of these modes is described below. An example of a typical use of GASGAUGE appears in Figure 2.

A zero (0) in the COUNTER parameter indicates a setup call. For example:

EQU SETUP$ TO 0
CALL GASGAUGE(SETUP$)

The COUNT and USER_BAR parameters are optional. COUNT can be used to provide text to be displayed on the left side of the status line, while USER_BAR can be used to override the default bar character.

EQU SETUP$ TO 0
COUNT    = "Updating ..."
USER_BAR = "*"
CALL GASGAUGE(SETUP$, COUNT, USER_BAR)

GASGAUGE will calculate the layout of cell 3 of the status line, taking into account the length of the text in COUNT. Note that the program limits the text to 50 characters.

By setting COUNTER to a positive value, you indicate that the status line should be redisplayed. For example, in this code fragment the status line is updated after each record is read.

DONE    = 0
COUNTER = 0
COUNT   = @RECCOUNT
LOOP
   READNEXT ID ELSE
     DONE = 1
   END
UNTIL DONE
   COUNTER += 1
   GASGAUGE(COUNTER, COUNT)
REPEAT

GASGAUGE does not update the status line if the change in the percentage complete is imperceptible. Even so, you should avoid calling GASGAUGE too frequently. Each call diverts processing time from the task at hand. Try to update the status line frequently enough that the user knows the program is still running, but not so frequently that you significantly slow down your program.

In the example above you could cause the status line to be updated every ten records (instead of with every record) by replacing the call to GASGAUGE with these three lines.

IF MOD(COUNTER, 10) ELSE
   GASGAUGE(COUNTER,COUNT)
END

The display of the status line will not be as smooth, but, on the other hand, that may lead to a perception of speed. Experiment with your programs to see what works best for you.

When your routine is done, you should call GASGAUGE with a negative value in the COUNTER argument. This will indicate to the program that it should restore the previous version of the status line. It will also clear the labelled common variables used in the routine, thereby freeing memory.

Several techniques used in the implementation of the gas gauge utility may require some clarification. Notes below address specific techniques.

UNASSIGNED

The argument COUNT (and USER_BAR) is checked in the SETUP portion of the code for initialization using the function UNASSIGNED. If it is unassigned, it is initialized to null, after which it is assigned a default value. It is good practice to use this technique for arguments passed into any generic subroutine or function, as it is otherwise possible for a user to call your routine with unitialized variables and cause it to break to the debugger.

This routine takes advantage of the fact that cell 3 of the status line can be treated as a modular entity with subcells that can be updated separately. Using this feature allows you to update individual portions of cell 3 in the most efficient way possible.

Note: See pp N5.41 - N.5.47 for information about STATUP and the Advanced Revelation status line.

@MODAL describes the subcells of cell 3. Each value represents a different subcell. Value one is the first subcell, value two is the second subcell, and so on.

Each value has 2 subvalues. The first subvalue indicates the starting column of the subcell, while the second describes how the data to be displayed in that subcell should be formatted.

For example, if @MODAL has this value (commas represent value marks, semicolons represent subvalue marks):

12L#10N30;R#4

it indicates that cell 3 has two subcells. The first subcell begins at position 1 and the data displayed in that position is left justified in a field of 10. The second subcell starts at position 30 and is right justified in a field of 4.

@MODAL is usually updated and restored with STATUP calls using PUSH$ and POP$ respectively. However, it can be updated directly, as in this case. Note that it is your responsibility to ensure that the subcells described by @MODAL do not overlap.

Labelled Common

GASGAUGE stores information about the original status line, the gas gauge character, and about the current length of the status bar in labelled common variables. This saves the calling routine from having to store these and pass them back each time it calls the gas gauge routine to update the status line.

Figure 1

SUBROUTINE GASGAUGE(COUNTER, COUNT, USER_BAR)

DECLARE FUNCTION UNASSIGNED
DECLARE SUBROUTINE STATUP

$INSERT INCLUDE, STATUS.CONSTANTS

EQU DEFAULT_BAR_CHAR$ TO \DB\   ;* Solid block
EQU DIVIDER$          TO \25B3\ ;* % followed by vertical bar
EQU MAX_TEXT$         TO 50
EQU TRUE$             TO 1
EQU FALSE$            TO 0
EQU NULL$             TO ""
EQU SPACE$            TO \20\

COMMON /GASGAUGE/ SAVE_IMAGE@, OLD_BAR_LEN@, BAR_CHAR@

BEGIN CASE
  CASE COUNTER > 0
    GOSUB UPDATE
  CASE COUNTER = 0
    GOSUB SETUP
  CASE COUNTER < 0
    GOSUB WRAPUP
END CASE
RETURN
/***************************************************************************
INTERNAL SUBROUTINES
***************************************************************************/
SETUP:
SAVE_IMAGE@ = NULL$
STATUP(PUSH$, "", SAVE_IMAGE@) ;* Save current status line info
SAVE_IMAGE@<2> = @MODAL ;* Save current modal info
IF UNASSIGNED(COUNT) THEN
  COUNT = NULL$
END

/* Build @MODAL based on the length of count */
LEN_COUNT = LEN(COUNT)
IF LEN_COUNT > MAX_TEXT$ THEN
  COUNT = COUNT[1,MAX_TEXT$]
  LEN_COUNT = MAX_TEXT$
END

/* Initialize @MODAL so cell 3 of the status line has 3 logical fields */
@MODAL = 1 : @SVM : "L#":LEN_COUNT : @VM
@MODAL := LEN_COUNT + 2 : @SVM : "R#3" : @VM
@MODAL := LEN_COUNT + 7 : @SVM : "L#" : 64 - (LEN_COUNT + 7)

/* Initialize cell 3, note that two calls to STATUP are required. The first
clears the status line and puts up the dividing bar. The second initializes
the first logical area of the status line with the text from count */

INITIAL = @MODAL<1,1,2>
INITIAL = INITIAL[-1,"B#"]
INITIAL += 4
STATUP(SINGLE$, 3, STR(SPACE$, INITIAL) : DIVIDER$ )
STATUP(SINGLE.MODAL$, 1, COUNT)

OLD_BAR_LEN@ = 0
IF UNASSIGNED(USER_BAR) THEN
  USER_BAR = NULL$
END

IF USER_BAR = NULL$ THEN
  BAR_CHAR@ = DEFAULT_BAR_CHAR$
END ELSE
  BAR_CHAR@ = USER_BAR[1,1] ;* Only one character is allowed.
END
RETURN

UPDATE:
PERCENT_DONE = COUNTER/COUNT
STAT_SPACE = @MODAL[-1,"B#"] ;* Length of the bar area of the status line
BAR_LEN = INT(STAT_SPACE * PERCENT_DONE)
IF OLD_BAR_LEN@ <> BAR_LEN THEN
  OLD_BAR_LEN@ = BAR_LEN
  BAR = INT(PERCENT_DONE * 100) : @FM : STR(BAR_CHAR@, BAR_LEN)
  STATUP(MULTI.MODAL$, 2 : @FM : 3, BAR)
END
RETURN

WRAPUP:
STATUP(SINGLE$, 3, NULL$)
@MODAL = SAVE_IMAGE@<2>
STATUP(POP$, "", SAVE_IMAGE@<1>)

/* Null out the labeled commons. This saves some memory */
OLD_BAR_LEN@ = NULL$
BAR_CHAR@    = NULL$
SAVE_IMAGE@  = NULL$
RETURN

Figure 2

DECLARE SUBROUTINE GASGAUGE, FSMSG
DECLARE FUNCTION GET.RECCOUNT

EQU SETUP$  TO 0
EQU WRAPUP$ TO -1
EQU TRUE$   TO 1
EQU FALSE$  TO 0

OPEN "SAMPLE_CUSTOMERS" TO SAMPLE_CUSTOMERS_FILE ELSE
  FSMSG()
  STOP
END

SELECT SAMPLE_CUSTOMERS_FILE

VALID = FALSE$
FORCE_COUNT = FALSE$
RECORD_COUNT = GET.RECCOUNT(SAMPLE_CUSTOMERS_FILE, VALID, FORCE_COUNT)
IF VALID THEN
  * count returned, so a gas gauge is possible -- do setup
  GASGAUGE(SETUP$)
END

DONE = FALSE$
COUNTER = 0
LOOP
  READNEXT @ID ELSE
    DONE = TRUE$
  END
  COUNTER += 1
UNTIL DONE
  * Update the status line if appropriate -- only every 10 records
  * for efficiency.
  IF MOD(COUNTER, 10) = 0 THEN
    IF VALID THEN
      * only update if a record count is available
      GASGAUGE(COUNTER, RECORD_COUNT)
    END
  END
  READ @RECORD FROM SAMPLE_CUSTOMERS_FILE THEN
    GOSUB PROCESS ;* code not shown here
  END
REPEAT

IF VALID THEN
  * clean up status line
  GASGAUGE(WRAPUP$)
END
STOP
  • tips/revmedia/r72.txt
  • Last modified: 2024/06/19 20:20
  • by 127.0.0.1