Class TBrowse() Foundation

Class function of the TBrowse class.

Description

The class object generates TBrowse objects using the class method :new().

A TBrowse object is an extremely flexible mechanism for browsing any data that can be represented as a table of rows and columns. This includes data that is stored in a traditional .dbf file, data stored in an array, or even data that is created on the fly. Tbrowse objects display data on the screen in a completely customizable rectangular region called a browse window.

The browse window provides a way to view data sources containing more information than can fit on the screen. TBrowse objects contain methods that manipulate the data source and update the browse window, so that the user can interactively browse all rows and all columns of the data source at will. The architecture of the TBrowse class is constructed in a fashion which hides the data implementation from a particular TBrowse object. This provides a high degree of flexibility and customization for the programmer. TBrowse relies on the services of individual objects of the TBColumn class to retrieve and display data for a particular column of the browse. The TBrowse object administers its own cursor which highlights the data in the current row and column.

A TBrowse object contains numerous methods to navigate the browse cursor through the data. Usually, these methods are called in response to keystrokes entered by the user. When the user moves the browse cursor past the edge of the visible data, the TBrowse object scrolls the browse window so that the new rows or columns are visible. It also automatically synchronizes the visible data on the screen with the underlying data source.

Since the data source is hidden from the TBrowse object, fundamental movement operations are not built in. Instead, this functionality is achieved by manually assigning code blocks that handle moving to the beginning of the data source, moving to the end of the data source, and moving one or more rows within the data source (these compare to the GO TOP, GO BOTTOM and SKIP commands). The TBrowse object in turn contains methods which evaluate these code blocks, in response to user input.

The browse window is divided into three areas: header lines with column titles, data rows containing the data from the data source, and footer lines at the bottom of each column. Each area can be visibly separated by a line. Within the data rows, each column can be visibly separated by a line.

The display of data is accomplished by a TBrowse object incrementally row by row using a stabilization cycle. During stabilization, if an event occurs which requires a skip, the incremental display is halted until the skip operation is complete.

Class methods
:new()
Creates an instance of the TBrowse class.
Instance variables
:autoLite
Indicates whether the browse cursor is automatically highlighted as part of stabilization.
:cargo
Instance variable for ad-hoc use.
:colCount
Contains the number of columns (TBColumn objects) in the TBrowse object.
:colorSpec
Contains a character string containing two or more color pairs used to display the data.
:colPos
Contains the current column position of the browse cursor.
:colSep
Contains a character value used to visually separate columns.
:footSep
Contains a character value used to visually separate the footer area from the data area.
:freeze
Contains the number of columns that always remain visible on the left side of the browse window.
:goBottomBlock
Code block which moves the record pointer to the last data record.
:goTopBlock
Code block which positions the row pointer to the first data row.
:headSep
Contains a character value used to visually separate the header area from the data area.
:hitBottom
Indicates an attempt to move beyond the end of the data source.
:hitTop
Indicates an attempt to move prior to the beginning of the data source.
:leftVisible
Contains the position of the leftmost column which can be scrolled horizontally.
:nBottom
Contains the bottom row position of the browse window on the screen.
:nLeft
Contains the left column position of the browse window on the screen.
:nRight
Contains the right column position of the browse window on the screen.
:nTop
Contains the top row position of the browse window on the screen.
:rightVisible
Contains the position of the rightmost column which can be scrolled horizontally.
:rowCount
Contains the number of data rows in the browse window (does not include header/footer rows or seperators).
:rowPos
Contains the current row position of the browse cursor.
:skipBlock
Contains a code block used to skip through the data source.
:stable
Indicates whether the TBrowse object is stable and synchronized with the data source.
Methods for columns
:addColumn()
Attaches a column (TBColumn object) to a TBrowse object.
:delColumn()
Deletes a column (TBColumn object) from a TBrowse object.
:getColumn()
Retrieves a reference to a column (TBColumn object ) in a TBrowse object.
:insColumn()
Inserts a column (TBColumn object) into a TBrowse object.
:setColumn()
Replaces a column (TBColumn object) in a TBrowse object.
Display methods
:colorRect()
Changes color in a rectangular cell area.
:colWidth()
Establishes the width of a column on the screen.
:configure()
Forces a TBrowse object to reconfigure itself for display.
:deHilite()
Displays browse cursor in normal color.
:forceStable()
Forces complete stabilization of the display.
:hilite()
Displays the browse cursor in highlight color.
:invalidate()
Forces the TBrowse object to redisplay the browse window.
:refreshAll()
Causes all data in the data rows to be re-read during the next stabilization cycle.
:refreshCurrent()
Causes the data in the current data row to be re-read during the next stabilization cycle.
:stabilize()
Stabilizes the TBrowse object in a series of incremental steps.
Cursor navigation
:_end()
Moves the browse cursor to the column at the right edge of the browse window.
:down()
Moves the browse cursor down one line.
:firstScrCol()
Determines screen column where the first table column is displayed.
:goBottom()
Positions the record pointer to the last data record in the data source.
:goTop()
Positions record pointer to the first data record of the data source.
:home()
Moves the browse cursor into the first column.
:left()
Moves the browse cursor one column to the left.
:pageDown()
Scrolls one page down.
:pageUp()
Scrolls one page up.
:panEnd()
Moves the browse cursor to the last column defined in the TBrowse.
:panHome()
Moves the browse cursor to the first column defined in the TBrowse.
:panLeft()
Scrolls the browse window one column to the left.
:panRight()
Scrolls the browse window one column to the right.
:right()
Moves the browse cursor one column to the right.
:up()
Moves the browse cursor one row up.
:viewArea()
Determines the coordinates for the data area of a TBrowse object.
Examples
TBrowse and TBColumn usage

// The program example shows the basic procedures for 
// programming with TBrowse and TBColumn objects in this example 
// of a simple DBF File Viewer. In order to display data on the screen 
// the following steps are required: 
// 
//   Generate TBrowse object and 
//   define navagation code blocks.     (-> PROCEDURE DbfView ) 
// 
//   Generate TBColumn objects and      (-> FUNCTION FieldColumn ) 
//   attach to the TBrowse object.      (-> PROCEDURE DbfView ) 
// 
//   Display, stabilize browse window 
//   and examine keyboard (events).     (-> PROCEDURE TBSetFocus ) 
// 
//   Call methods for the 
//   movement of the browse cursor      (-> FUNCTION TBNavigate ) 
// 
//   Perform appropriate skip operations 
//   based on cursor movement           (-> FUNCTION DbfSkipper ) 
// 
//   The basic steps are programmed in five different functions 
//   and procedures. 


#include "Inkey.ch" 

PROCEDURE Main 

   dbfView( 5,10,20,70, "ADRESSES.DBF" ) 

RETURN 

////// 
// The function generates a TBrowse object for 
// viewing the data records and activates 
// the TBrowse object 
////// 
PROCEDURE dbfView( nTop, nLeft, nBottom, nRight, cDbfFile ) 
   LOCAL oTBrowse, n, nCount 

   USE (cDbfFile) NEW                 // Open file 
                                      // Generate TBrowse object 
   oTBrowse := TBrowse():new( nTop, nLeft, nBottom, nRight ) 
   oTBrowse:goTopBlock    := {|| DbGoTop() } 
   oTBrowse:goBottomBlock := {|| DbGoBottom() } 
   oTBrowse:skipBlock     := {|n| DbfSkipper(n) } 
   oTBrowse:headSep       := Chr(205) + Chr(205) + Chr(205) 
   oTBrowse:colSep        := Chr(32)  + Chr(179) + Chr(32) 
   oTBrowse:colorSpec     := "N/BG,W+/B,N/R,W+/R" 

   nCount := FCount() 
   FOR n:=1 TO nCount                 // Generate TBColumn object 
      oTBColumn:= FieldColumn( n )    // in UDF 
      oTBrowse:AddColumn( oTBColumn ) // Attach TBColumn object 
   NEXT 

   TBSetFocus( oTBrowse )             // Activate TBrowse 

RETURN 

////// 
// The function generates a TBColumn object for 
// a field variable with help of the field position 
////// 
FUNCTION FieldColumn( nFieldPos ) 
   LOCAL oTBColumn , cHeading  , bBlock , ; 
         cFieldname, cFieldtype 

   cFieldname := FieldName( nFieldPos ) 
   cFieldtype := Type( cFieldname ) 
   cHeading   := Left( cFieldname, 1 ) + ; 
                 Lower( SubStr( cFieldname, 2 ) ) 

   IF cFieldtype == "M"              // Produce data code block 
      bBlock  := {|| IIf( Empty( FieldGet(nFieldPos) ), ; 
                          "          ", "<Memofield>" )  } 
   ELSE 
      bBlock  := FieldWBlock( cFieldname, Select() ) 
   ENDIF 
                                     // Generate TBColumn object 
   oTBColumn  := TBColumn():new( cHeading, bBlock ) 

   IF cFieldtype == "N"              // Negative numbers have 
                                     // different colors than 
                                     // positive numbers. 
      oTBColumn:colorBlock := {|n| IIF( n<0, {3,4}, {1,2} ) } 
   ELSEIF cFieldtype == "L" 
      oTBColumn:Picture := "Y"       // Picture for logical values 
   ENDIF 

RETURN oTBColumn 

////// 
// This function stabilizes the display in the 
// browse window and gets input from the keyboard 
////// 
PROCEDURE TBSetFocus( oTBrowse ) 
   LOCAL nKey := 0 

   DO WHILE nKey <> K_ESC 

      DO WHILE .NOT. oTBrowse:stabilize() 
         IF (nKey := Inkey()) <> 0 
            EXIT 
         ENDIF 
      ENDDO 

      IF oTBrowse:stable 
         nKey := Inkey(0) 
      ENDIF 

      TBNavigate( oTbrowse, nKey ) 
   ENDDO 

RETURN 

////// 
// The function sends different messages to a TBrowse object 
// for moving the cursor, depending on the key pressed. 
////// 
FUNCTION TBNavigate( oTBrowse, nKey ) 
   LOCAL bBlock  := SetKey( nKey ) 
   LOCAL lReturn := .T. 

   DO CASE 
   CASE bBlock <> NIL        ; Eval( bBlock, oTBrowse ) 
   CASE nKey == K_DOWN       ; oTBrowse:down() 
   CASE nKey == K_PGDN       ; oTBrowse:pageDown() 
   CASE nKey == K_CTRL_PGDN  ; oTBrowse:goBottom() 
   CASE nKey == K_LEFT       ; oTBrowse:left() 
   CASE nKey == K_CTRL_LEFT  ; oTBrowse:panLeft() 
   CASE nKey == K_HOME       ; oTBrowse:home() 
   CASE nKey == K_CTRL_HOME  ; oTBrowse:panHome() 
   CASE nKey == K_RIGHT      ; oTBrowse:right() 
   CASE nKey == K_CTRL_RIGHT ; oTBrowse:panRight() 
   CASE nKey == K_END        ; oTBrowse:end() 
   CASE nKey == K_CTRL_END   ; oTBrowse:panEnd() 
   CASE nKey == K_UP         ; oTBrowse:up() 
   CASE nKey == K_PGUP       ; oTBrowse:pageUp() 
   CASE nKey == K_CTRL_PGUP  ; oTBrowse:goTop() 
   OTHERWISE 
      lReturn:= .F. 
   ENDCASE 

RETURN lReturn 

////// 
// This function executes a skip operation on the data source 
// of a TBrowse object. It is called from oTBrowse:skipBlock 
// which is evaluated in oTBrowse:stabilize(), 
// and receives as a parameter the number of skip 
// operations to perform. DbSkipper() works with  DBF files 
////// 
FUNCTION DbfSkipper( nWantSkip ) 
   LOCAL nDidSkip := 0 

   DO CASE 
   CASE LastRec() == 0              // No data records to skip, 
                                    // nothing happens. 
   CASE nWantSkip == 0 
      GOTO RecNo()                  // Refresh data buffer 

   CASE nWantSkip > 0               // Skip forward 
      DO WHILE nWantSkip > nDidSkip .AND. .NOT. Eof() 
         SKIP 
         IF Eof()                   // End of file 
            SKIP -1 
            EXIT 
         ENDIF 
         nDidSkip ++ 
      ENDDO 

   CASE nWantSkip < 0               // Skip backward 
      DO WHILE nWantSkip < nDidSkip .AND. .NOT. Bof() 
         SKIP -1 
         IF Bof()                   // Beginning of file reached 
            EXIT 
         ENDIF 
         nDidSkip -- 
      ENDDO 

   ENDCASE 

RETURN nDidSkip                     // This much was skipped 
////// 
// EOF TEST.PRG 
////// 
Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.