home *** CD-ROM | disk | FTP | other *** search
- // Tbinsp.prg
- //
- // Tbrowse inspector - display all instance vars in pop - up
- // window - Allows editing. Also displays
- // methods in another, allowing invocation
- //
- // Compile with /a /m /n /w
- //
- // Link with Tbindemo for test
-
- #include "Inkey.ch"
- #include "Setcurs.ch"
-
- MEMVAR getlist
-
- FUNCTION TbDisp(oTbr)
-
- #define GSBIVAR(i) {|o, n| iif(n == NIL, o:i, o:i := n) }
-
- // Array contains Ivar name, a get / set block for it,
- // and whether is is assignable
- STATIC aTbIvars := { ;
- { "colorSpec", GSBIVAR(colorSpec), .T. }, ;
- { "autoLite", GSBIVAR(autoLite), .T. }, ;
- { "colCount", GSBIVAR(colCount) , .F. }, ;
- { "colPos", GSBIVAR(colPos), .T. }, ;
- { "colSep", GSBIVAR(colSep), .T. }, ;
- { "freeze", GSBIVAR(freeze), .T. }, ;
- { "headSep", GSBIVAR(headSep), .T. }, ;
- { "hitBottom", GSBIVAR(hitBottom), .T. }, ;
- { "hitTop", GSBIVAR(hitTop), .T. }, ;
- { "leftVisible", GSBIVAR(leftVisible), .F. }, ;
- { "nTop", GSBIVAR(nTop), .T. }, ;
- { "nLeft", GSBIVAR(nLeft), .T. }, ;
- { "nBottom", GSBIVAR(nBottom), .T. }, ;
- { "nRight", GSBIVAR(nRight), .T. }, ;
- { "rightVisible",GSBIVAR(rightVisible), .F. }, ;
- { "rowCount", GSBIVAR(rowCount), .F. }, ;
- { "rowPos", GSBIVAR(rowPos), .T. }, ;
- { "stable", GSBIVAR(stable), .T. } ;
- }
-
- // Array contains method name, a block to evaluate it, and whether
- // we should save / restore the screen before / after evaluating it.
- #define INVMETH(m) {|o| o:m() }
- STATIC aTbMethods := { ;
- { "down", INVMETH(down), .F. }, ;
- { "end", INVMETH(end), .F. }, ;
- { "goBottom", INVMETH(goBottom), .F. }, ;
- { "goTop", INVMETH(goTop), .F. }, ;
- { "home", INVMETH(home), .F. }, ;
- { "left", INVMETH(left), .F. }, ;
- { "pageDown", INVMETH(pageDown), .F. }, ;
- { "pageUp", INVMETH(pageUp), .F. }, ;
- { "panEnd", INVMETH(panEnd), .F. }, ;
- { "panHome", INVMETH(panHome), .F. }, ;
- { "panLeft", INVMETH(panLeft), .F. }, ;
- { "panRight", INVMETH(panRight), .F. }, ;
- { "right", INVMETH(right), .F. }, ;
- { "up", INVMETH(up), .F. }, ;
- { "addColumn", INVMETH(addColumn), .F. }, ;
- { "colorRect", INVMETH(colorRect), .F. }, ;
- { "colWidth", INVMETH(colWidth), .F. }, ;
- { "configure", INVMETH(configure), .F. }, ;
- { "dehilite", INVMETH(deHilite), .F. }, ;
- { "delColumn", INVMETH(delColumn), .F. }, ;
- { "getColumn", INVMETH(getColumn), .F. }, ;
- { "hilite", INVMETH(hilite), .F. }, ;
- { "insColumn", INVMETH(insColumn), .F. }, ;
- { "invalidate", INVMETH(invalidate), .F. }, ;
- { "refreshCurrent", INVMETH(refreshCurrent), .F. }, ;
- { "refreshAll", INVMETH(refreshAll), .F. }, ;
- { "setColumn", INVMETH(setColumn), .F. }, ;
- { "stabilize", INVMETH(stabilize), .F. }, ;
- { "Full stabilize", {|o| fullStabilize(o) }, .T. } ;
- }
-
- LOCAL oTbrTemp1
- LOCAL oTbrTemp2
- LOCAL cSaveScr
- LOCAL i := 1
- LOCAL j := 1
- LOCAL oTbc
- LOCAL lExitRequested := .F.
- LOCAL nKey
- LOCAL nTop, nLeft, nBottom, nRight
- LOCAL nSaveRow := Row(), ;
- nSaveCol := Col()
- LOCAL xTemp
- LOCAL nSaveCurs
- LOCAL oTbrCur
- LOCAL cCurScreen
-
- // Determine coordinates for TBrowse window - set coordinates
- // to opposite quarter
- IF nSaveRow > MaxRow() / 2
- nTop := 0
- ELSE
- nTop := Int(MaxRow() / 2)
- ENDIF
- // Round up in case odd maxrow()
- nBottom := nTop + Int((MaxRow() + 1) / 2)
-
- // Save area we will overwrite and frame it
- cSaveScr := SaveScreen(nTop, 0, nBottom, MaxCol())
- @ nTop, 0 TO nBottom, MaxCol()
-
- // Create TBrowse object to display instance variables
- // Browse array using "i" as the array index
- oTbrTemp1 := TBrowseNew(nTop + 1, 1, ;
- nBottom - 1, Int(MaxCol() / 2))
-
- oTbrTemp1:goTopBlock := {|| i := 1}
- oTbrTemp1:goBottomBlock := {|| i := Len(aTbIvars) }
- oTbrTemp1:skipBlock := {|n, nSavei| ;
- nSavei := i, ;
- i := iif(n > 0, ;
- Min(i + n, Len(aTbIvars)), ;
- Max(1, i + n)), ;
- i - nSavei ;
- }
-
- // TBcolumn for the instance variable
- oTbc := TBColumnNew("Instance Var", {|| aTbIvars[i, 1] })
- oTbc:width := 14
- oTbrTemp1:addColumn(oTbc)
-
- // Column to display its value
- oTbc := TBColumnNew("Current Value", {|| Eval(aTbIvars[i, 2], oTbr) })
- oTbc:width := 14
- oTbrTemp1:addColumn(oTbc)
-
- // Create second TBrowse object to display method names
- // Browse array using "j" as the array index
- oTbrTemp2 := TBrowseNew(nTop + 1, int(MaxCol() / 2) + 1, ;
- nBottom - 1, MaxCol() - 1)
-
- oTbc := tbColumnNew("Methods", {|| aTbMethods[j, 1] })
- oTbc:width := 14
- oTbrTemp2:addColumn(oTbc)
- // oTbrTemp2:colSep := chr(179)
-
- oTbrTemp2:goTopBlock := {|| j := 1}
- oTbrTemp2:goBottomBlock := {|| j := Len(aTbMethods) }
- oTbrTemp2:skipBlock := {|n, nSavej| ;
- nSavej := j, ;
- j := iif(n > 0, ;
- min(j + n, len(aTbMethods)), ;
- max(1, j + n)), ;
- j - nSavej ;
- }
-
- // We now start our modal TBrowse.
- // First display method names
-
- DO WHILE !oTbrTemp2:stabilize()
- ENDDO
- oTbrTemp2:dehilite()
-
- // We allow users to move between the two tbrowse objects by using
- // a third variable, oTbrCur, which refers to either oTbrTemp1 (the
- // instance variables), or oTbrTemp2 (the method names).
- // We start on oTbrTemp1
- oTbrCur := oTbrTemp1
- DO WHILE !lExitRequested
- DO WHILE !oTbrCur:stabilize()
- ENDDO
- nKey := inkey(0)
-
- // First check whether user wants to move to the other TBrowse
- // object
- IF nKey == K_RIGHT .AND. oTbrCur == oTbrTemp1 .AND. ;
- oTbrCur:colPos == oTbrCur:colCount
- // Highlight bar was on ivars, now move it to methods
- oTbrCur:deHilite()
- oTbrCur := oTbrTemp2
- IF i != j
- oTbrTemp2:rowPos := oTbrTemp1:rowPos
- ENDIF
- ELSEIF nKey == K_LEFT .AND. oTbrCur == oTbrTemp2 .AND. ;
- oTbrCur:colPos == 1
- // Highlight bar was on methods, now move to ivars
- oTbrCur:deHilite()
- oTbrCur := oTbrTemp1
- IF j != i
- oTbrTemp1:rowPos := oTbrTemp2:rowPos
- ENDIF
- ELSEIF !StdMeth(nKey, oTbrCur)
- DO CASE
- CASE nKey == K_ESC
- lExitRequested := .T.
-
- CASE nKey == K_ENTER
- IF oTbrCur:colPos == 2 .AND. oTbrCur == oTbrTemp1 .AND. ;
- aTbIvars[i, 3]
- // We are on ivar contents column, and it is assignable
- // Edit the ivar
- nSaveCurs := Set(_SET_CURSOR, SC_NORMAL)
-
- // Evaluate its get/set block to get its value
- xTemp := Eval(aTbIvars[i, 2], oTbr)
- @ Row(), Col() GET xTemp
- READ
- IF updated()
- // Now update the ivar by evaluating the get/set block and
- // passing it a parameter
- Eval(aTbIvars[i, 2], oTbr, xTemp)
- ENDIF
- Set(_SET_CURSOR, nSaveCurs)
- oTbrCur:refreshCurrent()
- ELSEIF oTbrCur == oTbrTemp2
- // Highlight bar is on the method and the user just pressed
- // the Enter key
- IF aTbMethods[j, 3]
- // This method will mess up screen - save / restore etc
- cCurScreen := SaveScreen(nTop, 0, nBottom, MaxCol())
- RestScreen(nTop, 0, nBottom, MaxCol(), cSaveScr)
- Eval(aTbMethods[j, 2], oTbr)
- cSaveScr := SaveScreen(nTop, 0, nBottom, MaxCol())
- RestScreen(nTop, 0, nBottom, MaxCol(), cCurScreen)
- ELSE
- Eval(aTbMethods[j, 2], oTbr)
- ENDIF
- ENDIF
- ENDCASE
- ENDIF
- ENDDO
-
- RestScreen(nTop, 0, nBottom, MaxCol(), cSaveScr)
-
- RETURN NIL