sample calculator and xBrowser

Post Reply
User avatar
Otto
Posts: 4470
Joined: Fri Oct 07, 2005 7:07 pm
Contact:

sample calculator and xBrowser

Post by Otto »

To get some feeling for xBrowser and arrays I inserted a xbrowser into msgcalc – a contribution of Lorenzo Gadaleta years ago – which I use as add on calculator for my programs.
Thanks to NageswaraRao who helped on a xBrowser problem with arrays of size 0.
Now I have a kind of undo in my calculator.
I hope many of you have some input.

Regards,
Otto

Image


Code: Select all

/*********************************************************************/
/*                                                                   */
/* ProcName......: MsgCalc.prg                                       */
/* Author........: Lorenzo Gadaleta                                  */
/* Note..........: Usage Sample :                                    */
/*                 If you want e ret value in your get :             */
/*                                  oGet:VarPut( MsgCalc([nValue]) ) */
/*                                  oGet:Refresh()                   */
/*                 Else                                              */
/*                                  MsgCalc()                        */
/*                                                                   */
/*********************************************************************/

#include "FiveWin.ch"

#include "InKey.ch"
#include "xbrowse.ch"


#define BIF_RETURNONLYFSDIRS    1
#define BIF_DONTGOBELOWDOMAIN   2
#define MAX_PATH              260

#define PAD_LEFT            0
#define PAD_RIGHT           1
#define PAD_CENTER          2


STATIC  aStruc:={}
STATIC oBrw

FUNCTION MsgCalc(nVal)
    // Here for languages pesonalization
    LOCAL cTitle         := "Calculator "
    LOCAL cPastMsg       := "&Einfügen"
    LOCAL cConfirmMsg    := " B&estätigen "
    LOCAL cAbortMsg      := " &End "
    LOCAL cPict          := "@E 999,999,999,999,999.99"

    // End languages personalization
    LOCAL n := 100
    LOCAL nInit := 0
    LOCAL oDlg, oFont, oCursor, oRes, cRes := ""
    LOCAL nMemo:=0, nOpe
    LOCAL oGet, cGet := Space(100), oBtnOk, oBtnAb, oBtn
    LOCAL cLastOpe := "+"
    LOCAL oBt1,oBt2,oBt3,oBt4,oBt5,oBt6,oBt7,oBt8,oBt9,oBt0,oBtC
    LOCAL oBSum, oBMin, oBMol, oBDiv, oBPer, oBCan, oBRes
    LOCAL lRet    := .F.
    local oClearEntryKey

    aadd(aStruc,{"",0,0})

    DEFAULT nVal := 0
    nInit := nVal

    DEFINE FONT oFont NAME "MS Reference Sans Serif" SIZE 0, -12

    DEFINE CURSOR oCursor HAND

    DEFINE DIALOG oDlg SIZE 405, 405 TITLE cTitle PIXEL FONT oFont

    oBrw := TXBrowse():New( oDlg )

    oBrw:nTop     := 5
    oBrw:nLeft    := 5
    oBrw:nBottom  := 90
    oBrw:nRight   := 180

    oBrw:SetArray( aStruc)
    oBrw:nMarqueeStyle       := MARQSTYLE_HIGHLROW
    oBrw:nColDividerStyle    := LINESTYLE_BLACK
    oBrw:lColDividerComplete := .t.

    oBrw:aCols[1]:cHeader         := 'Key'
    oBrw:aCols[1]:nWidth          := 60
    oBrw:aCols[1]:nDataStrAlign   := AL_CENTER
    oBrw:aCols[1]:nEditType       := EDIT_GET_LISTBOX
    oBrw:aCols[1]:aEditListTxt    := {"+", "-", "*", "/"}
    oBrw:aCols[1]:bOnPostEdit     := {|o,x| aStruc[ oBrw:nArrayAt, 1 ] := x, update_total(oRes,oGet) }
    oBrw:aCols[1]:aEditListBound  := {"+", "-", "*", "/"}
    oBrw:aCols[1]:bClrEdit        := oBrw:bClrStd

    oBrw:aCols[2]:cHeader         := 'Value'
    oBrw:aCols[2]:nWidth          := 80
    oBrw:aCols[2]:nDataStrAlign   := AL_RIGHT
    oBrw:aCols[2]:bEditvalue      := { || aStruc[ oBrw:nArrayAt, 2 ] }
    oBrw:aCols[2]:cEditPicture    := "@Z 999 999 999.99"
    oBrw:aCols[2]:nEditType       := EDIT_GET
    oBrw:aCols[2]:bOnPostEdit     := {|o,x| aStruc[ oBrw:nArrayAt, 2 ] := x,  update_total(oRes,oGet) }
    oBrw:aCols[2]:bStrData        := { || Transform( aStruc[oBrw:nArrayAt][2], "@Z 999 999 999.99" )}

    oBrw:aCols[2]:nEditType       := EDIT_GET_BUTTON
    oBrw:aCols[2]:bEditBlock      := {|| Del_line(),  update_total(oRes,oGet) }


    oBrw:aCols[3]:cHeader         := 'Total'
    oBrw:aCols[3]:nWidth          := 80
    oBrw:aCols[3]:nDataStrAlign   := AL_RIGHT
    oBrw:aCols[3]:bStrData        := { || Transform( aStruc[oBrw:nArrayAt][3], "@Z 999 999 999.99" )}

    oBrw:CreateFromCode()

    @ 100,0.5 GET oGet VAR cGet OF oDlg PIXEL SIZE 95,10

    oGet:bChange  := {|nKey,nFlag,oB|(Chr(nKey)$"0123456789.,")} // Logical

    oGet:bKeyDown := { | nKey | VerKey(nKey,oBSum,oBMin,oBMol,oBDiv,oBPer,oBCan,oBRes,oGet) }

    @ 120,5.6 GET oRes VAR cRes OF oDlg PIXEL SIZE 55,10 RIGHT COLOR CLR_RED,CLR_WHITE READONLY

    *@ 1.3,1 BUTTON oBtn PROMPT cPastMsg OF oDlg ACTION (oBCan:Click(),SayNum(oGet,nVal)) FONT oFont SIZE 38,10


    // Numbers
    @ 140  , 1   BUTTON oBt1 PROMPT "1"      OF oDlg ACTION SayNum(oGet,1)    FONT oFont  PIXEL SIZE 30,10
    @ 140  , 36  BUTTON oBt2 PROMPT "2"      OF oDlg ACTION SayNum(oGet,2)    FONT oFont  PIXEL SIZE 30,10
    @ 140  , 70  BUTTON oBt3 PROMPT "3"      OF oDlg ACTION SayNum(oGet,3)    FONT oFont  PIXEL SIZE 30,10

    @ 155  , 1   BUTTON oBt4 PROMPT "4"      OF oDlg ACTION SayNum(oGet,4)    FONT oFont  PIXEL SIZE 30,10
    @ 155  , 36  BUTTON oBt5 PROMPT "5"      OF oDlg ACTION SayNum(oGet,5)    FONT oFont  PIXEL SIZE 30,10
    @ 155  , 70  BUTTON oBt6 PROMPT "6"      OF oDlg ACTION SayNum(oGet,6)    FONT oFont  PIXEL SIZE 30,10

    @ 170  , 1   BUTTON oBt7 PROMPT "7"      OF oDlg ACTION SayNum(oGet,7)    FONT oFont  PIXEL SIZE 30,10
    @ 170  , 36  BUTTON oBt8 PROMPT "8"      OF oDlg ACTION SayNum(oGet,8)    FONT oFont  PIXEL SIZE 30,10
    @ 170  , 70  BUTTON oBt9 PROMPT "9"      OF oDlg ACTION SayNum(oGet,9)    FONT oFont  PIXEL SIZE 30,10

    @ 185  , 1   BUTTON oBt0 PROMPT "  0  " OF oDlg ACTION SayNum(oGet,0)    FONT oFont  PIXEL SIZE 30,10
    @ 185  , 70  BUTTON oBtC PROMPT "."     OF oDlg ACTION SayNum(oGet,".")  FONT oFont  PIXEL SIZE 30,10


    // Operators
    n:=3

    @  95,120  BUTTON oBSum PROMPT " + "        OF oDlg ACTION (CalcRes(cLastOpe,@nMemo,oGet,oRes,cPict),cLastOpe:="+") FONT oFont  PIXEL SIZE 30,10
    @  95,160  BUTTON oBMin PROMPT " - "        OF oDlg ACTION (CalcRes(cLastOpe,@nMemo,oGet,oRes,cPict),cLastOpe:="-") FONT oFont  PIXEL SIZE 30,10
    @ 110,120  BUTTON oBMol PROMPT " * "       OF oDlg ACTION (CalcRes(cLastOpe,@nMemo,oGet,oRes,cPict),cLastOpe:="*") FONT oFont  PIXEL SIZE 30,10
    @ 110,160  BUTTON oBDiv PROMPT " / "       OF oDlg ACTION (CalcRes(cLastOpe,@nMemo,oGet,oRes,cPict),cLastOpe:="/") FONT oFont  PIXEL SIZE 30,10
//    @ 125,130  BUTTON oBPer PROMPT " % "       OF oDlg ACTION (CalcRes(cLastOpe,@nMemo,oGet,oRes,cPict),cLastOpe:="%") FONT oFont  PIXEL SIZE 30,10

    @ 125,160  BUTTON oBCan PROMPT "&C "       OF oDlg ACTION ;
        (;
        ASIZE(aStruc,0),;
        oBrw:refresh(),;
        cLastOpe:="+",;
        nMemo:=0,;
        oRes:cText(""),;
        oGet:cText(Space(100)),;
        oGet:SetFocus());
        FONT oFont PIXEL SIZE 30,10

    @ 140,160  BUTTON oClearEntryKey PROMPT "  C&E "     OF oDlg ACTION ClearEntryKey(oGet) FONT oFont  PIXEL SIZE 30,10
    @ 140,120  BUTTON oBRes PROMPT "    =    " OF oDlg ACTION (CalcRes(cLastOpe,@nMemo,oGet,oRes,cPict),cLastOpe:="") FONT oFont PIXEL SIZE 30,10 DEFAULT

    // Exit
    *@ n+7.3,1   BUTTON oBtnOk PROMPT cConfirmMsg    OF oDlg ACTION (lRet:=.T.,oDlg:End()) FONT oFont SIZE 46,13

    @155,120 BUTTON oBtnAb PROMPT cAbortMsg    OF oDlg ACTION (lRet:=.F.,oDlg:End())  FONT oFont PIXEL SIZE 46,13   CANCEL
    @185,120 BUTTON "   Print"                 OF oDlg ACTION Prn_Calculation(aStruc) FONT oFont PIXEL SIZE 46,13


    // Cursors
    aEval(oDlg:aControls,{|oC|iif(oC:ClassName()="TBUTTON",oC:oCursor:=oCursor,)})

    ACTIVATE DIALOG oDlg CENTER;
        ON INIT  (ASIZE(aStruc,0), oBrw:refresh());
        ON PAINT (oGet:SetFocus());
        VALID (oCursor:End(),oFont:End(),.T.)

    RETURN iif(lRet,nMemo,nInit)


STATIC FUNCTION SayNum(oGet,xNum)

    LOCAL cText := StrTran( Alltrim(oGet:cText()), ",", ".")
    if ValType(xNum) == "C"
        if !"."$cText
            oGet:cText( padR(cText+".",100) )
        else
            Tone(300)
        end
    else
        oGet:cText( padR(cText+cValToChar(xNum),100) )
    end
    oGet:SetFocus()
RETURN NIL

STATIC FUNCTION CalcRes(cOpe,nMemo,oGet,oRes,cPict)
    LOCAL cVal := StrTran( Alltrim(oGet:cText()), ",", ".")
    LOCAL nVal := Val(cVal)

    if !left(cVal,1) $ "0123456789."
        cVal := Substr(cVal,2)
        nVal := Val(cVal)
    end
    if !right(cVal,1) $ "0123456789."
        cVal := Left(cVal,Len(cVal)-1)
        nVal := Val(cVal)
    end

    if      cOpe == "+"
        nMemo += nVal
    elseif  cOpe == "-"
        nMemo -= nVal
    elseif  cOpe == "*"
        nMemo *= nVal
    elseif  cOpe == "/"
        nMemo /= nVal
    elseif  cOpe == "%"
        nMemo := nMemo*nVal/100
    end
    oGet:cText( Space(100) )
    oRes:cText( Tran(nMemo,"@E 999,999,999,999,999.99") )

    //xBrowser
    IF len(ALLTRIM(cVal))=0
    else
        aadd(aStruc,{cOpe,VAL(cVal),nMemo})
    ENDIF
    oBrw:GoBottom()
    oBrw:Refresh()

    oGet:SetFocus()
RETURN NIL

STATIC FUNCTION VerKey(nKey,oBSum, oBMin, oBMol, oBDiv, oBPer, oBCan, oBRes,oGet)
    local nPos
    if  nKey    == 107                      // "+"
        oBSum:Click()
    elseif  nKey    == 8                      // "<-"
        BackSpace(oGet)
        nPos := (len(ALLTRIM(oGet:cText())))
        oGet:SetPos( nPos+1 )
    elseif  nKey    == 109                      // "-"
        oBMin:Click()
    elseif  nKey    == 106                      // "*"
        oBMol:Click()
    elseif  nKey    == 111                      // "/"
        oBDiv:Click()
    end
RETURN 0


func ClearEntryKey(oGet)
    oGet:cText := space(100)
    oGet:SetFocus()
return nil

func BackSpace(oGet)
    local cGetTemp

    cGetTemp   :=  left(ALLTRIM(oGet:cText()),(len(ALLTRIM(oGet:cText()))-1))
    oGet:cText := cGetTemp + space(100)

    oGet:SetFocus()

return nil


function Prn_Calculation(aStruc)
    local oPrn, oFont, oPen
    Local nLinI, nColI, nLinF, nColF
    LOCAL I , nRow
    LOCAL cVal
    LOCAL cTotal

    nRow:=2

    PRINT oPrn NAME "Impresión en Vertical.." PREVIEW
    DEFINE FONT oFont NAME "Arial" SIZE 0, -10 BOLD OF oPrn
    DEFINE PEN oPen WIDTH  2                        OF oPrn

    oPrn:SetPage(9)                             // A4
    oPrn:SetPortrait()                          //Vertical
    PAGE
    nLinI :=  0.90
    nColI :=  0.90
    nLinF := 28.6
    nColF := 20.0
    oPrn:Cmtr2Pix(@nLinI, @nColI)
    oPrn:cmtr2Pix(@nLinF, @nColF)
    oPrn:Box(nLinI, nColI, nLinF, nColF, oPen  )
    oPrn:cmSay( 1.0,  1.0, dtoc(date())+ "   " + time(), oFont,,CLR_BLACK,,PAD_LEFT  )
    oPrn:cmSay( 1.0, 10.5, "Berechnung",    oFont,,CLR_BLACK,,PAD_CENTER )

    FOR I := 1 TO len(aStruc)
        cVal   := Transform( aStruc[I][2], "@Z 999 999 999.99" )
        cTotal := Transform( aStruc[I][3], "@Z 999 999 999.99" )

        oPrn:cmSay( nRow + I*0.6,  3.0, aStruc[I][1] , oFont,,CLR_BLACK,,PAD_LEFT  )
        oPrn:cmSay( nRow + I*0.6,  4.0, cVal , oFont,,CLR_BLACK,,PAD_LEFT  )

        IF I > 1
            IF  aStruc[I][1] = "*" .OR. aStruc[I][1]="/"  .OR. aStruc[I][1]="%"
                oPrn:cmSay( nRow + (I-1) *0.6,  7.0, "=  "+ str(aStruc[I-1][3]) , oFont,,CLR_BLACK,,PAD_LEFT  )

                oPrn:Line(  nRow + (I-1) *0.6, 0,  nRow + (I-1) *0.6, 15)
            ENDIF
        ENDIF

    NEXT

    oPrn:cmSay( nRow + (I+2)*0.6,  7.0, cTotal , oFont,,CLR_BLACK,,PAD_LEFT  )
    ENDPAGE
    ENDPRINT


return nil

func update_total(oRes,oGet)

    local I,nTotal:=0

    FOR I := 1 TO len(aStruc)

        if      aStruc[I][1] == "+"
            nTotal += aStruc[I][2]
        elseif  aStruc[I][1] == "-"
            nTotal -= aStruc[I][2]
        elseif  aStruc[I][1] == "*"
            nTotal *= aStruc[I][2]
        elseif  aStruc[I][1] == "/"
            nTotal /= aStruc[I][2]
        elseif  aStruc[I][1] == "%"
            nTotal := nTotal*aStruc[I][2]/100
        end

        aStruc[I][3]:= nTotal
     NEXT

    oRes:cText( Tran(nTotal,"@E 999,999,999,999,999.99") )

    oBrw:GoBottom()
    oBrw:Refresh()

    oGet:SetFocus()

return nil


func Del_line()
    IF len(aStruc)>0
        ADel( aStruc, oBrw:nArrayAt )
        ASize( aStruc, Len( aStruc ) - 1 )
        oBrw:Refresh()
        oBrw:GoBottom()
        oBrw:Refresh()
    else
        ASIZE(aStruc,0)
        oBrw:refresh()
    endif

return NIL


Changes in cBrowser-class (by NageswaraRao suggested)

Code: Select all

METHOD Refresh( lComplete )  CLASS TXBrowse

   DEFAULT lComplete := .F.

   ::KeyCount()

   if lComplete
      ::nRowSel  = 1
      ::nArrayAt = 1
   else
      ::nRowSel  = Max( 1, Min( ::nRowSel, ::nLen ) )
      ::nArrayAt = Min( ::nArrayAt, ::nLen )
      if ::nArrayAt == 0 .and. ::nLen > 0
         ::nArrayAt := 1
      endif
   endif

   ::GetDisplayCols()

return Super:Refresh( .T. )
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Otto,

It looks really nice :-)

Thanks!
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Otto
Posts: 4470
Joined: Fri Oct 07, 2005 7:07 pm
Contact:

Post by Otto »

I updated a new the screen capture of the calculator.
Now I use Manuels’s class TSButton.
The design is somewhat like an IPhone calculator (BRAUN).
Regards,
Otto
Image
User avatar
kajot
Posts: 309
Joined: Thu Nov 02, 2006 6:53 pm
Location: Poland

Post by kajot »

how may I change code in cBrowser-class
best regards
kajot
User avatar
Otto
Posts: 4470
Joined: Fri Oct 07, 2005 7:07 pm
Contact:

Post by Otto »

Hello kajot,
cbrowser was a typo. If should be xBrowse. But I think this change is not necessary anymore. The newer releases of FIVEWIN have implemented this change.
Regards,
Otto
Post Reply