Creating a Set of Table Navigation Buttons

A common feature of many applications is a series of navigation buttons that allow users to move through a table. These typically include buttons to move the record pointer to the next or prior record in the table, as well as to the top or bottom record in the table.

Designing the Navigation Buttons

Each of the buttons will have some characteristics and functionality in common, so it is a good idea to create a navigation button class. Then the individual buttons can easily derive this common appearance and functionality. This parent class is the Navbutton class defined later in this section.

Once the parent class is defined, the following subclasses define the functionality and appearance specific to each of the four navigation buttons: navTop, navPrior, navNext, navBottom.

Finally, a container class, vcr, is created and each of the navigation buttons is added to the container class. The container can be added to a form or a toolbar to provide table navigation functionality.

To create Navbutton, save the following six class definitions (Navbutton, navTop, navBottom, navPrior, navNext, and vcr) to a program file such as Navclass.prg.

Definition of the Generic Navigation Commandbutton Class

Code Comments
DEFINE CLASS Navbutton AS
COMMANDBUTTON
  Height = 25
  Width = 25
  TableAlias = ""
Define the parent class of the navigation buttons.

Give the class some dimensions.

Include a custom property, TableAlias, to hold the name of the alias to navigate through.

PROCEDURE Click
  IF NOT EMPTY(This.TableAlias)
   SELECT (This.TableAlias)
  ENDIF
ENDPROC
If TableAlias has been set, this parent class procedure selects the alias before the actual navigation code in the subclasses is executed. Otherwise, assume that the user wants to navigate through the table in the currently selected work area.
PROCEDURE RefreshForm
  _SCREEN.ActiveForm.Refresh
ENDPROC
Using _SCREEN.ActiveForm.Refresh instead of THISFORM.Refresh allows you to add the class to a form or a toolbar and have it function equally well.
ENDDEFINE
End the class definition.

The specific navigation buttons are all based on the Navbutton class. The following code defines the Top button for the set of navigation buttons. The remaining three navigation buttons are defined in the following table. The four class definitions are similar, so only the first one has extensive comments.

Definition of the Top Navigation Button Class

Code Comments
DEFINE CLASS navTop AS Navbutton
  Caption = "|<"
Define the Top navigation button class and set the Caption property.
PROCEDURE Click
Create method code to be executed when the Click event for the control occurs.
  DODEFAULT( )
  GO TOP
  THIS.RefreshForm
Call the Click event code in the parent class, Navbutton, so that the appropriate alias can be selected if the TableAlias property has been set.

Include the code to set the record pointer to the first record in the table: GO TOP.

Call the RefreshForm method in the parent class. It is not necessary to use the scope resolution operator (::) in this case because there is no method in the subclass with the same name as the method in the parent class. On the other hand, both the parent and the subclass have method code for the Click event.
ENDPROC
End the Click procedure.
ENDDEFINE
End the class definition.

The other navigation buttons have similar class definitions.

Definition of the Other Navigation Button Classes

Code Comments
DEFINE CLASS navNext AS Navbutton
  Caption = ">"
Define the Next navigation button class and set the Caption property.
PROCEDURE Click
  DODEFAULT( )
  SKIP 1
  IF EOF( )
   GO BOTTOM
  ENDIF
  THIS.RefreshForm
ENDPROC
ENDDEFINE



Include the code to set the record pointer to the next record in the table.



End the class definition.
DEFINE CLASS navPrior AS Navbutton
  Caption = "<"
Define the Prior navigation button class and set the Caption property.
PROCEDURE Click
  DODEFAULT( )
  SKIP –1
  IF BOF( )
   GO TOP
  ENDIF
  THIS.RefreshForm
ENDPROC
ENDDEFINE



Include the code to set the record pointer to the previous record in the table.



End the class definition.
DEFINE CLASS navBottom AS
Navbutton
  Caption = ">|"
Define the Bottom navigation button class and set the Caption property.
PROCEDURE Click
  DODEFAULT( )
  GO BOTTOM
  THIS.RefreshForm
ENDPROC
ENDDEFINE


Include the code to set the record pointer to the bottom record in the table.

End the class definition.

The following class definition contains all four navigation buttons so that they can be added as a unit to a form. The class also includes a method to set the TableAlias property of the buttons.

Definition of a Table Navigation Control Class

Code Comments
DEFINE CLASS vcr AS CONTAINER
   Height = 25
   Width = 100
   Left = 3
   Top = 3
Begin the class definition. The Height property is set to the same height as the command buttons it will contain.
   ADD OBJECT cmdTop AS navTop ;
      WITH Left = 0
   ADD OBJECT cmdPrior AS navPrior ;
      WITH Left = 25
   ADD OBJECT cmdNext AS navNext ;
      WITH Left = 50
   ADD OBJECT cmdBot AS navBottom ;
      WITH Left = 75
Add the navigation buttons.
PROCEDURE SetTable(cTableAlias)
   IF TYPE("cTableAlias") = 'C'
      THIS.cmdTop.TableAlias = ;
         cTableAlias
      THIS.cmdPrior.TableAlias = ;
         cTableAlias
      THIS.cmdNext.TableAlias = ;
         cTableAlias
      THIS.cmdBot.TableAlias = ;
         cTableAlias
   ENDIF
ENDPROC
This method is used to set the TableAlias property of the buttons. TableAlias is defined in the parent class Navbutton.

You could also use the SetAll method to set this property:
IF TYPE ("cTableAlias") = 'C'
This.SetAll("TableAlias", "cTableAlias")
ENDIF
However, this would cause an error if an object were ever added to the class that did not have a TableAlias property.
ENDDEFINE
End class definition.

Once you have defined the class, you can subclass it or add it to a form.

Creating a Subclass Based on the New Class

You can also create subclasses based on vcr that have additional buttons such as Search, Edit, Save, and Quit. For example, vcr2 includes a Quit button:

Definition of a Table Navigation Control Subclass

Code Comments
DEFINE CLASS vcr2 AS vcr
ADD OBJECT cmdQuit AS
COMMANDBUTTON WITH ;
   Caption = "Quit",;
   Height = 25, ;
   Width = 50
Width = THIS.Width + THIS.cmdQuit.Width
cmdQuit.Left = THIS.Width - ; 
   THIS.cmdQuit.Width
Define a class based on vcr and add a command button to it.
PROCEDURE cmdQuit.CLICK
   RELEASE THISFORM
ENDPROC
When the user clicks cmdQuit, this code releases the form.
ENDDEFINE
End class definition.

Vcr2 has everything that vcr does, plus the new command button, and you don't have to rewrite any of the existing code.

Changes to VCR Reflected in the Subclass

Because of inheritance, changes to the parent class are reflected in all subclasses based on the parent. For example, you could let the user know that the bottom of the table has been reached by changing the IF EOF( ) statement in navNext.Click to the following:

IF EOF( )
   GO BOTTOM
   SET MESSAGE TO "Bottom of the table"
ELSE
   SET MESSAGE TO
ENDIF

You could let the user know that the top of the table has been reached by changing the IF BOF( ) statement in navPrior.Click to the following:

IF BOF()
   GO TOP
   SET MESSAGE TO "Top of the table"
ELSE
   SET MESSAGE TO
ENDIF

If these changes are made to the navNext and navPrior classes, they will also apply automatically to the appropriate buttons in vcr and vcr2.

Adding VCR to a Form Class

Once vcr is defined as a control, the control can be added in the definition of a container. For example, the following code added to Navclass.prg defines a form with added navigation buttons:

DEFINE CLASS NavForm AS Form
   ADD OBJECT oVCR AS vcr
ENDDEFINE

Running the Form Containing VCR

Once the form subclass is defined, you can display it easily with the appropriate commands.

To display the form

  1. Load the class definition:

    SET PROCEDURE TO navclass ADDITIVE
    
  2. Create an object based on the navform class:

    frmTest = CREATEOBJECT("navform")
    
  3. Invoke the Show method of the form:

    frmTest.Show
    

If you don't call the SetTable method of oVCR (the VCR object in NavForm) when the user clicks the navigation buttons, the record pointer moves in the table in the currently selected work area. You can call the SetTable method to specify what table to move through.

frmTest.oVCR.SetTable("customer")

Note   When the user closes the form, frmTest is set to a null value (.NULL.). To release the object variable from memory, use the RELEASE command. Object variables created in program files are released from memory when the program is completed.

See Also

Writing Class Definitions Programmatically | Method and Event Code Guidelines | Definition of a Grid Control | Caption property | Height property | SetAll method | Object-Oriented Programming