TXBrowse

The most powerful and versatile data grid control in FiveWin

Fuente: source/classes/xbrowse.prg  |  Parent: TControl  |  Header: XBrowse.ch

Overview

TXBrowse is the flagship data grid control of FiveWin. It renders tabular data from virtually any source -- DBF tables, in-memory arrays, ADO RecordSets, ODBC cursors, or custom data -- through a unified block-based navigation architecture. It virtualizes rendering so that only visible rows are processed, enabling it to handle millions of records without excessive memory consumption.

Key capabilities include:

Architecture

TXBrowse decouples the visual grid from the underlying data through a set of navigation code blocks. Helper methods like SetRDD(), SetArray(), and SetAdo() simply populate these blocks with the appropriate logic for each data source type.

graph TD subgraph DataSources["Data Sources"] DBF["DBF / RDD
(SetRDD)"] ARR["Array
(SetArray)"] ADO["ADO RecordSet
(SetAdo)"] ODBC["ODBC Cursor
(SetODBC)"] CUSTOM["Custom
(manual blocks)"] end subgraph NavBlocks["Navigation Blocks"] bGoTop bGoBottom bSkip bBof bEof bKeyNo bKeyCount bBookMark bSeek end subgraph TXBrowseObj["TXBrowse Object"] GRID["Grid Engine
paint, scroll, keys"] COLS["aCols<br/>TXBrwCol array"] GRID --- COLS end DBF --> bGoTop ARR --> bGoTop ADO --> bGoTop ODBC --> bGoTop CUSTOM --> bGoTop bGoTop --> GRID bGoBottom --> GRID bSkip --> GRID bKeyCount --> GRID bBookMark --> GRID style TXBrowseObj fill:#1c2129,stroke:#58a6ff,stroke-width:2px,color:#e6edf3 style NavBlocks fill:#1c2129,stroke:#3fb950,stroke-width:1px,color:#e6edf3 style DataSources fill:#1c2129,stroke:#d29922,stroke-width:1px,color:#e6edf3

Column Object: TXBrwCol

Each column in the browse is a TXBrwCol object stored in the aCols array. Columns define what data to display and how to display it.

classDiagram class TXBrwCol { +cHeader : String +bEditValue : Block +bStrData : Block +nWidth : Numeric +cDataType : String +lEdit : Logical +nEditType : Numeric +bClrStd : Block +bClrEdit : Block +cPicture : String +nHeadStrAlign : Numeric +nDataStrAlign : Numeric +AddResource(cBmp) +SetCheck(cResYes, cResNo) } class TXBrowse { +aCols : Array of TXBrwCol +nFreeze : Numeric +lRecordSelector : Logical +nMarqueeStyle : Numeric +lFastEdit : Logical +lIncrFilter : Logical +AddColumn() +SetRDD() +SetArray() +SetAdo() +CreateFromCode() +Refresh() } TXBrowse "1" *-- "many" TXBrwCol : aCols

Key Properties (DATA)

PropertyTypeDescription
aColsArrayArray of TXBrwCol column objects defining every column in the grid
cAliasStringWork area alias when using SetRDD()
nFreezeNumericNumber of left-hand columns that remain frozen during horizontal scroll
lRecordSelectorLogicalWhen .T., displays a row-indicator column on the left edge
nMarqueeStyleNumericVisual style of the selection highlight (see XBrowse.ch constants: MARQSTYLE_HIGHLROW, MARQSTYLE_HIGHLCELL, MARQSTYLE_DOTEDCELL, etc.)
lFastEditLogicalWhen .T., typing a character immediately opens the cell editor -- no Enter key required. Caution: this disables single-key navigation shortcuts.
lIncrFilterLogicalWhen .T., a seek/filter bar appears below the headers for incremental column searching
nDataTypeNumericInternal flag indicating the data source type (RDD, Array, ADO, etc.)
lMultiSelectLogicalEnables multi-row selection with Ctrl+Click and Shift+Click
nArrayAtNumericCurrent row index when browsing an array data source
nRowHeightNumericPixel height of each data row
nHeaderHeightNumericPixel height of the column header row

These code blocks form the data abstraction layer. They are set automatically by SetRDD(), SetArray(), SetAdo(), etc., but you can supply custom blocks for specialized data sources.

BlockSignatureDescription
bGoTop{|| ... }Position data source at first record
bGoBottom{|| ... }Position data source at last record
bSkip{|n| ... }Move n records (positive=forward, negative=backward). Returns actual records moved.
bBof{|| ... }Returns .T. if before first record
bEof{|| ... }Returns .T. if past last record
bKeyNo{|n| ... }Get/set the current logical position (for scrollbar)
bKeyCount{|| ... }Returns total number of records (for scrollbar)
bBookMark{|u| ... }If u is NIL, returns a bookmark for the current row. Otherwise, repositions to bookmark u.
bSeek{|c| ... }Incremental seek -- find the first record matching the string c

Key Methods

MethodDescription
New( oWnd )Constructor. Creates a TXBrowse instance associated with parent window/dialog oWnd.
SetRDD( [cAlias] )Configure navigation blocks for a DBF/RDD work area.
SetArray( aData, [lAutoCol] )Configure navigation blocks for an in-memory array.
SetAdo( oRs )Configure navigation blocks for an ADO RecordSet object.
SetODBC( oQry )Configure navigation blocks for an ODBC result set.
AddColumn( cHead, bData, [cPict], ... )Add a column with header, data block, optional picture, and more.
CreateFromCode()Finalize control creation after configuring data source and columns.
Adjust()Recalculate header, row, and footer dimensions. Sometimes needed after font changes.
Refresh()Repaint all visible rows.
SelectedCol()Returns the currently selected TXBrwCol object.
Report( [cTitle] )Quick-print the browse contents via the FWH print engine.
ToExcel()Export visible data to Microsoft Excel.
ToClip()Copy visible data to the clipboard.

Commands (XBrowse.ch)

FiveWin provides two command styles for creating TXBrowse controls:

Positioned Command

@ nRow, nCol XBROWSE oBrw ;
   [ OF oWnd ] ;
   [ SIZE nWidth, nHeight ] ;
   [ COLUMNS cCol1, cCol2, ... ] ;
   [ HEADERS cHead1, cHead2, ... ] ;
   [ ALIAS cAlias ] ;
   [ ON DBLCLICK bAction ] ;
   [ FONT oFont ] ;
   [ NOBORDER ]

Quick Browser Command

XBROWSER <cAlias>       // browse a DBF alias
XBROWSER <aArray>       // browse an array
XBROWSER <oRs>          // browse an ADO RecordSet

Code Examples

Example 1: Browsing a DBF Table

#include "FiveWin.ch"
#include "XBrowse.ch"

FUNCTION Main()
   LOCAL oWnd, oBrw

   USE Customer VIA "DBFCDX" NEW

   DEFINE WINDOW oWnd TITLE "Customers" FROM 1, 1 TO 24, 80

   oBrw := TXBrowse():New( oWnd )
   oBrw:nTop    := 0
   oBrw:nLeft   := 0
   oBrw:nRight  := -1   // stretch to right edge
   oBrw:nBottom := -1   // stretch to bottom edge

   oBrw:SetRDD()        // bind to current work area

   // Configure individual columns
   WITH OBJECT oBrw:AddColumn( "ID", FieldBlock( "CUST_ID" ), "99999" )
      :nWidth       := 80
      :nDataStrAlign := AL_RIGHT
   END

   WITH OBJECT oBrw:AddColumn( "First Name", FieldBlock( "FIRSTNAME" ), "@!" )
      :nWidth := 140
      :lEdit  := .T.    // allow in-cell editing
   END

   oBrw:AddColumn( "Last Name",  FieldBlock( "LASTNAME" ),  "@!" )
   oBrw:AddColumn( "City",       FieldBlock( "CITY" ) )
   oBrw:AddColumn( "Balance",    FieldBlock( "BALANCE" ),    "@E 999,999.99" )

   oBrw:nFreeze         := 1       // freeze ID column
   oBrw:lRecordSelector := .T.     // show row indicator
   oBrw:nMarqueeStyle   := MARQSTYLE_HIGHLROW

   oBrw:CreateFromCode()

   oWnd:oClient := oBrw            // fill the window client area
   ACTIVATE WINDOW oWnd

   CLOSE Customer
RETURN NIL

Example 2: Browsing an Array

#include "FiveWin.ch"
#include "XBrowse.ch"

FUNCTION Main()
   LOCAL oWnd, oBrw
   LOCAL aData := { ;
      { "Alice",   "Smith",    28, .T. }, ;
      { "Bob",     "Johnson",  34, .F. }, ;
      { "Charlie", "Williams", 45, .T. }, ;
      { "Diana",   "Brown",    31, .T. }, ;
      { "Edward",  "Jones",    52, .F. }  ;
   }

   DEFINE WINDOW oWnd TITLE "Array Browse" FROM 2, 2 TO 20, 70

   oBrw := TXBrowse():New( oWnd )
   oBrw:SetArray( aData, .F. )   // .F. = do not auto-create columns

   oBrw:aCols := {}
   oBrw:AddColumn( "First",  {|| aData[ oBrw:nArrayAt ][ 1 ] } )
   oBrw:AddColumn( "Last",   {|| aData[ oBrw:nArrayAt ][ 2 ] } )
   oBrw:AddColumn( "Age",    {|| aData[ oBrw:nArrayAt ][ 3 ] }, "999" )
   oBrw:AddColumn( "Active", {|| aData[ oBrw:nArrayAt ][ 4 ] } )

   // Make "Active" column render as a checkbox
   oBrw:aCols[ 4 ]:SetCheck( "CHECK1", "UNCHECK1" )

   oBrw:nMarqueeStyle := MARQSTYLE_HIGHLCELL
   oBrw:CreateFromCode()

   oWnd:oClient := oBrw
   ACTIVATE WINDOW oWnd
RETURN NIL

Example 3: Editable Browse with Column Configuration

#include "FiveWin.ch"
#include "XBrowse.ch"

FUNCTION Main()
   LOCAL oWnd, oBrw, oCol

   USE Invoices VIA "DBFCDX" NEW

   DEFINE WINDOW oWnd TITLE "Editable Invoices"

   @ 0, 0 XBROWSE oBrw OF oWnd ;
      COLUMNS "INVNO", "CUSTNAME", "AMOUNT", "INVDATE", "PAID" ;
      HEADERS "Invoice #", "Customer", "Amount", "Date", "Paid?"

   oBrw:SetRDD()

   // Configure the Amount column
   oCol := oBrw:aCols[ 3 ]
   oCol:cPicture  := "@E 999,999.99"
   oCol:lEdit     := .T.
   oCol:nEditType := EDIT_GET             // edit with a GET control
   oCol:bClrStd   := {|| { CLR_BLACK, CLR_WHITE } }

   // Configure the Date column with a date picker editor
   oCol := oBrw:aCols[ 4 ]
   oCol:lEdit     := .T.
   oCol:nEditType := EDIT_DATE

   // Configure the Paid column as a checkbox
   oCol := oBrw:aCols[ 5 ]
   oCol:SetCheck( "CHECK1", "UNCHECK1" )
   oCol:lEdit := .T.

   oBrw:lFastEdit := .T.   // typing goes straight to edit mode
   oBrw:CreateFromCode()

   oWnd:oClient := oBrw
   ACTIVATE WINDOW oWnd

   CLOSE Invoices
RETURN NIL

Example 4: Incremental Seek / Filter Bar

#include "FiveWin.ch"
#include "XBrowse.ch"

FUNCTION Main()
   LOCAL oWnd, oBrw

   USE Customer INDEX Customer VIA "DBFCDX" NEW

   DEFINE WINDOW oWnd TITLE "Customer Search"

   oBrw := TXBrowse():New( oWnd )
   oBrw:SetRDD()

   oBrw:AddColumn( "Name",    FieldBlock( "NAME" ) )
   oBrw:AddColumn( "City",    FieldBlock( "CITY" ) )
   oBrw:AddColumn( "Phone",   FieldBlock( "PHONE" ) )
   oBrw:AddColumn( "Balance", FieldBlock( "BALANCE" ), "@E 999,999.99" )

   // Enable the incremental filter bar
   oBrw:lIncrFilter := .T.

   // Custom seek block -- performs an indexed seek on the NAME field
   oBrw:bSeek := {|cSeek| ( oBrw:cAlias )->( DbSeek( cSeek, .T. ) ) }

   oBrw:nMarqueeStyle   := MARQSTYLE_HIGHLROW
   oBrw:lRecordSelector := .T.

   oBrw:CreateFromCode()
   oWnd:oClient := oBrw
   ACTIVATE WINDOW oWnd

   CLOSE Customer
RETURN NIL

Tips and Best Practices

Ver También