Home > Archive > Clipper > August 2007 > positioning TBrowse - need robust procedure
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
positioning TBrowse - need robust procedure
|
|
| Kristian 2007-08-08, 6:55 pm |
| Hi all,
I have come to the conclusion that one of the most probable demands to
a browse-oriented database system - positioning a given dataset onto a
given line inside the table - is fairly complicated to do in clipper.
For instance, jumping from a dataset in one database to a related
dataset in another database is no problem in respect to positioning
the database pointer. But opening the new browse object such that the
corresponding dataset is positioned conveniently in the same line as
the dataset I am jumping from is pretty tedious, I find.
I wanted a function that stabilizes the browse in that position where
the active dataset is the one given by nRecord, in the row number
specified by nTargetRow. As two of the most popular requests could be
the bottom line and the middle line, these are given as nTargetRow = 0
and 0.5, respectively.
I used Mel Smith's suggestion from last October to create the
following function:
FUNCTION initBrowPosition ( oBrowse, nRecord, nTargetRow )
LOCAL I, nCURROW, nCURREC
DISPBEGIN()
oBrowse:forceStable()
DO CASE
CASE nTargetRow == NIL
nTargetRow := 1
CASE nTargetRow == 0
nTargetRow := oBrowse:rowcount
CASE nTargetRow == 0.5
nTargetRow := INT ( oBrowse:rowcount / 2 )
ENDCASE
IF nRecord == NIL
nRecord := RECNO()
ENDIF
nCURROW := oBrowse:rowpos // Save row of window
we're on
// First position
cursor bar to saved window row (nSavRow)
IF .NOT. ( nCURROW == nTargetRow ) // Re-position the
screen row
oBrowse:rowpos := nTargetRow
oBrowse:configure() // A 'key'
function for re-positioning
oBrowse:forcestable()
oBrowse:refreshAll()
DO WHILE ( !oBrowse:stabilize() ); ENDDO
ENDIF
// Now position the underlying database to saved record number
(nSavRec)
IF .NOT. ( nCURREC := RECNO() ) == nRecord // We've got to move
the record pointer
IF nCURREC <> 0
DBGOTO ( nRecord )
ENDIF
//nrow := nRecord // "I think this statement is
essential" - I think it's wrong
// oBrowse:rowpos := NIL
ENDIF
oBrowse:configure()
oBrowse:forceStable()
DISPEND()
RETURN NIL
This doesn't work too badly, although I have the impression it mostly
takes me to the second line from the bottom where the bottom row is
requested... But what is annoying is that I have not found yet how to
make the function robust: For instance, specifying nTargetRow = 0 when
there are less datasets than browse lines produces unpredictable
results. Who can help me make this function perfect such that, if the
requested nTargetRow is not available because it is larger than the
number of datasets, that then, simply the bottommost line will become
the target, the first dataset being in the first row?
Thanks,
Kristian
| |
| Stephen Quinn 2007-08-08, 9:55 pm |
| Kristian
I think you have it backwards.
You should goto the record number in the DBF then position it to the wanted row in the TBrowse.
Eg
// this should show the record on the 1st row
oTB:RowPos := 1
x->( DBGoto( nRecNo ) )
// if now you want it on the middle row move the DBF/Tbrowse up the required number of steps
nMiddleRow := INT( oTB:RowCount / 2 )
FOR i := 1 TO nMiddleRow
// Need to check for BOF here
oTB:Up()
NEXT
// The record you want to see should now be on the middle line of the TBrowse
// all you need do now is move the hilite to that row
x->( DBGtoto nRecNo ) )
Put it all within a DispBegin/DispEnd pair ad the user should see none of the hilite movement except
the last one.
I'll leave you to figure out the positioning for the last row of the TBrowse
It's always much easier to do these things when you start from a known position - ie row 1 or
lastrow
--
CYA
Steve
| |
| Kristian 2007-08-10, 7:55 am |
| Steve,
thanks for the quick reply. Looks fairly simple, but I seem to be
missing something when it comes to the next stabilize(). Here's what
the code looks like now:
--------------------------------------------------------------------------
FUNCTION initBrowPosition ( oBrowse, nRecord, nTargetRow )
LOCAL i
LOCAL nActualRow := 1
//DISPBEGIN()
oBrowse:forceStable()
// handle special values for nTargetRow: 0 and 0.5
DO CASE
CASE nTargetRow == NIL
nTargetRow := 1
CASE nTargetRow == 0
nTargetRow := oBrowse:rowcount
CASE nTargetRow == 0.5
nTargetRow := INT ( oBrowse:rowcount / 2 )
ENDCASE
// handle input for nRecord: 1 and 0; make it a real
record number
// according to present index and filter conditions
DO CASE
CASE nRecord == NIL
DBGOTOP()
nRecord := RECNO()
CASE nRecord == 1 // some chance of an error here for the
rare case that actually rec# 1 is desired
DBGOTOP()
nRecord := RECNO()
CASE nRecord == 0
DBGOBOTTOM()
nRecord := RECNO()
OTHERWISE
// leave nRecord as it is: a specific record number
ENDCASE
oBrowse:RowPos := 1
DBGoto( nRecord )
// move the DBF/Tbrowse up the required
number of steps
FOR i := 1 TO nTargetRow - 1
IF BOF()
EXIT
ENDIF
oBrowse:up()
nActualRow++
NEXT
DBGoto ( nRecord )
oBrowse:refreshAll()
oBrowse:forceStable()
//DISPEND()
IF nActualRow = nTargetRow
nActualRow := 0
ENDIF
RETURN nActualRow
--------------------------------------------------------------------------
This is much like what you suggested, only that I added the handling
for the input parameters, the check for BOF(), a variable nActualRow
that reflects how many line shifts were actually performed - and the
forceStable() at the end of the function. I put it in here because the
trouble starts when stabilize() is performed by the calling TBrowse
managing function.
I start testing with a database that contains more datasets than there
are lines in the browse table, and it is initially positioned to BOF.
At the end of the function, the TBrowse object correctly contains the
19 last datasets and is filled to the bottommost line (19). BUT: the
active dataset is NOT the last dataset but the one in the first line
of the browse. Although the last dataset is selected by the last
DBGoto(nRecord), (in fact, the pointer is still positioned on that
record,) it is moved to the record in the first line by the concluding
oBrowse:forceStable() call.
I have tried to cure the problem by inserting an additional
oBrowse:Rowpos := nActualRow
before the refreshAll(), but this results in the desired dataset
showing up in the FIRST line of the browse, with no more lines below.
Sorry, but I need more help...
Thanks,
Kristian
| |
| Kristian 2007-08-10, 6:55 pm |
| It was brought to my attention that the solution is in fact very
simple:
- move record pointer to desired dataset
- designate row position to desired rowpos
- configure()
- forceStable()
Appears to be very robust.
Thanks!
|
|
|
|
|