Class XbpBrowse() Foundation
Class function of the XbpBrowse class
General description: The XbpBrowse class is used to create a GUI browser to display data organized in table form. These can be databases or arrays. An XbpBrowse object on its own is a container for XbpColumn objects which are necessary to display a single column of a table. An XbpColumn object has a data code block to retrieve data, for example from a database field, and displays it on the screen.
Similar to the TBrowse class (text mode browser), the :addColumn() method is used to add a table column, or XbpColumn object, to an XbpBrowse object. The latter is not able to display table data on its own, it rather navigates through a table and positions columns on the screen.
Navigation: An XbpBrowse object navigates through a table by means of a browse cursor that can be configured optionally as a row cursor or a cell cursor. The browse cursor corresponds to the record pointer of the underlying data source, and both are automatically synchronized during navigation. To enable an XbpBrowse object to navigate, seven code blocks must be assigned to the object, three of which are used to configure a vertical scroll bar (see the example).
Display: Data is displayed on screen when an XbpBrowse object executes its :forceStable() method. Normally, this method need not be called in a program explicitly. It is executed automatically when an XbpBrowse object processes the xbeBRW_ForceStable event. This event is created by navigation methods, such as :up(), :left() or :pageDown(). This means, an XbpBrowse object has a default behaviour to react to keyboard or mouse events.
Difference to TBrowse: For an XbpBrowse object to display a table, it is sufficient to assign navigation code blocks to the object. This is a major difference between the TBrowse and XbpBrowse class. A TBrowse object requires code to be implemented for display (DO WHILE .NOT. oBrowse:stabilize()) and to process keyboard input. This is not the case with an XbpBrowse object, because it displays data and processes events within the event loop (nEvent := AppEvent() ; oBrowse:handleEvent(nEvent)).
Event handling: The next table lists all keys which are recognized by an XbpBrowse object for navigation:
Key | Description |
---|---|
Left Arrow | One column to the left |
Right Arrow | One column to the right |
Up Arrow | Previous record |
Down Arrow | Next record |
Ctrl+Up Arrow | Scrolls the display down a line |
Ctrl+Down Arrow | Scrolls the display up a line |
Page Up | Previous screen |
Page Down | Next screen |
Ctrl+Page Up | First record |
Ctrl+Page Down | Last record |
Home | First column |
End | Last column |
Return | Evaluates :itemSelected code block |
Left click | Moves browse cursor to mouse pointer |
Left double click | Evaluates :itemSelected code block |
Configuration: The appearance of a table on screen can be configured very detailed by means of presentation parameters. When an XbpBrowse object is created presentation parameters can be specified, too, which are valid for XbpColumn objects. These settings are then used by all XbpColumn objects subsequently added to the XbpBrowse object.
The instance variables in this group configure system resources. If changes are made to these values, they must either be made before the :create() method is executed or the :configure() method must be used to activate the changes.
Callback code blocks for synchronous messages differ from other callback code blocks by their return value. If the return value is NIL, the XbpBrowse object performs no further action. For any other return value, the XbpBrowse object shows its default behaviour after the code block is evaluated. Therefore, returning NIL suppresses the default behaviour of an XbpBrowse object.
// In the example, the user defined function GuiBrowseDB() is
// programmed. It assigns all navigation code blocks to an
// XbpBrowse object which are necessary to browse a database.
// Table columns are created within a FOR..NEXT loop.
// The browser is displayed in the event loop.
#include "Appevent.ch"
#include "Common.ch"
PROCEDURE AppSys
// Desktop remains application window
RETURN
PROCEDURE Main
LOCAL nEvent, mp1, mp2, oXbp, oBrowse, cField, i
USE Customer NEW
// Create a hidden dialog window
oXbp := GuiStdDialog( "Standard GUI Browser for DBF" )
// Create browser in the window
oBrowse := GuiBrowseDb( oXbp:drawingArea )
// Add columns for all fields of the database
FOR i:=1 TO FCount()
cField := FieldName( i )
oBrowse:addColumn( FieldBlock(cField), , cField )
NEXT
// The browser always fills the entire window after :resize()
oXbp:drawingArea:resize := ;
{|mp1,mp2,obj| obj:childList()[1]:setSize(mp2) }
oXbp:show()
oBrowse:show()
SetAppFocus( oBrowse )
DO WHILE nEvent <> xbeP_Close
nEvent := AppEvent( @mp1, @mp2, @oXbp )
oXbp:handleEvent( nEvent, mp1, mp2 )
ENDDO
RETURN
******************************************************************
* Create a GUI browser with navigation code blocks for a database
******************************************************************
FUNCTION GuiBrowseDB( oParent, aPos, aSize )
LOCAL oBrowse
oBrowse := XbpBrowse():new( oParent,, aPos, aSize ):create()
// Navigation code blocks for the browser
oBrowse:skipBlock := {|n| DbSkipper(n) }
oBrowse:goTopBlock := {| | DbGoTop() }
oBrowse:goBottomBlock := {| | DbGoBottom() }
oBrowse:phyPosBlock := {| | Recno() }
oBrowse:goPhyPosBlock := {|n| DbGoto(n) }
// Navigation code blocks for the vertical scroll bar
oBrowse:posBlock := {| | DbPosition() }
oBrowse:goPosBlock := {|n| DbGoPosition(n) }
oBrowse:lastPosBlock := {| | 100 }
oBrowse:firstPosBlock := {| | 0 }
RETURN oBrowse
******************************************************************
* Create a hidden dialog window
******************************************************************
FUNCTION GuiStdDialog( cTitle )
LOCAL oDlg
DEFAULT cTitle TO "Standard Dialog Window"
oDlg := XbpDialog():new( ,,{10,10}, {600,400},, .F. )
oDlg:icon := 1
oDlg:taskList := .T.
oDlg:title := cTitle
oDlg:create()
oDlg:drawingArea:setFontCompoundName( "8.Helv" )
RETURN oDlg
// This example illustrates how XbpBrowse objects can be used for
// browsing an array. In addition, the example shows how the
// visualization of the browse can be adjusted for platforms which
// support visual styles. This is important for computers running
// Windows XP or newer.
******************************************************************
* IMPORTANT: A manifest file or resource must be added to the
* example! More information on defining manifests can be found
* in the documentation of the function "IsThemeActive()".
******************************************************************
#include "xbp.ch"
#include "appevent.ch"
#PRAGMA LIBRARY( "XPPUI2.LIB" )
// Global variables for maintaining
// the data source (array)
STATIC aData
STATIC nLastRec
STATIC nRecno
PROCEDURE Main()
LOCAL oBrowse
LOCAL nEvent
LOCAL oXbp := NIL
LOCAL mp1 := NIL
LOCAL mp2 := NIL
LOCAL oCol
LOCAL nWidth
LOCAL oGroup
// Configure the application window (XbpCrt)
SetMouse( .T. )
SetColor( "N/W+" )
CLS
SetAppWindow():UseShortCuts := .T.
// Create group box as backdrop for the
// browse
oGroup := XbpStatic():New()
oGroup:Type := XBPSTATIC_TYPE_GROUPBOX
oGroup:Caption := "Inventory"
oGroup:Create( ,,, {440,250} )
CenterControl( oGroup )
// Initialize array data for the browse as
// well as associated status variables
aData := { {"Magazines", 133, .T.},;
{"Newspapers", 15, .T.},;
{"Books", 32, .T.},;
{"Postcards", 833, .F.} }
nLastRec := Len(aData)
nRecno := 1
// Create the browse and associate it with the
// data source. Note that visual styles are
// switched off to ensure that cell frames are
// displayed as configured, irrespective of the
// operating system being used
oBrowse := XbpBrowse():New( oGroup )
oBrowse:SkipBlock := {|nSkip,oBrowse| DoSkip(nSkip,oBrowse) }
oBrowse:GoBottomBlock := {|| nRecno := Len(aData) }
oBrowse:GoTopBlock := {|| nRecno := 1 }
oBrowse:PosBlock := {|| nRecno }
oBrowse:PhyPosBlock := {|| nRecno }
oBrowse:GoPhyPosBlock := {|n| nRecno := n }
oBrowse:LastPosBlock := {|| Len(aData) }
oBrowse:FirstPosBlock := {|| 1 }
oBrowse:CursorMode := XBPBRW_CURSOR_ROW
oBrowse:UseVisualStyle := .F.
oBrowse:Create( ,, {20,20}, {400,200},, .F. )
// Add columns to the browse
oBrowse:AddColumn( {|| aData[nRecno,1]}, 15, "Publication" )
oBrowse:AddColumn( {|| aData[nRecno,2]}, 5, "In Stock" )
oBrowse:AddColumn( {|| aData[nRecno,3]}, 1, "Web Shop" )
// Enable visual styles for the scroll
// bars. This way, the data area remains
// fully configurable while the scroll
// bars use platform-default visuals.
oBrowse:HScrollObject:UseVisualStyle := .T.
oBrowse:VScrollObject:UseVisualStyle := .T.
oBrowse:Show()
SetAppFocus( oBrowse )
nEvent := xbeP_None
DO WHILE nEvent != xbeP_Close
nEvent := AppEvent( @mp1, @mp2, @oXbp )
oXbp:HandleEvent( nEvent, mp1, mp2 )
ENDDO
oBrowse:Destroy()
RETURN
******************************************************************
* Skipper function that moves the record pointer through the
* data source (array)
******************************************************************
FUNCTION DoSkip( nSkip )
LOCAL nCanSkip
IF nRecno + nSkip < 1 // "BoF"
nCanSkip := 1 - nRecno
ELSEIF nRecno + nSkip > nLastRec // "EoF"
nCanSkip := nLastRec - nRecno
ELSE
nCanSkip := nSkip
ENDIF
nRecno += nCanSkip
RETURN nCanSkip
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.