/*

  Программа ИНДИКАТОР
  Показывает 'процесс' - без начала и конца


*/
// стек индикаторов
STATIC aIndik  := {}
STATIC aProces := {}

MEMVAR INST_COLOR

#define COL_INDIK1     IF(INST_COLOR, "B/W", "N+/W")
#define COL_INDIK2     IF(INST_COLOR, "N/W", "N/W")
#define COL_INDIK3     IF(INST_COLOR, "W+/B", "W*/N")
#define COL_INDIK4     IF(INST_COLOR, "W+/W", "W*/N")

#define SIMVOL1        CHR(176)
#define SIMVOL2        CHR(219)  // CHR(178)

#define  _nNomer       1       /* цвет шкалы индикатора                     */
#define  _nRow         2     /* строка верх                               */
#define  _nCol         3     /* колонка левая                             */
#define  _nLen         4     /* длина строки                              */
#define  _cScreen      5     /* экран до запуска                          */
#define  _nDlina       6     /* длина шкалы индикатора                    */
#define  _nOtstup      7     /* отступ шкалы индикатора от левого края    */
#define  _nMaxElem     8     /* махсимальное значение индикатора          */
#define  _nElem        9     /* текущее значение индикатора               */
#define  _nProcent    10     /* значение индикатора в процентах           */
#define  _cColSimv    11     /* цвет шкалы индикатора                     */
#define  _lIndik      12     /* Вертелка внизу                            */
#define  _nLen0       13     /* Текущая длина                             */

/*
   nRow - номер строки (верх)
   nCol - номер колонки (лево)
   По умолчанию: по центру
*/
FUNCTION INDIK_NEW(nRow, nCol, cColSim )
  LOCAL nNomer := LEN(aIndik)+1
  nRow    := IF( nRow    == NIL, INT(MAXROW()/2-2), nRow)
  nCol    := IF( nCol    == NIL, INT(MAXCOL()/2-2), nCol)
  cColSim := IF( cColSim == NIL, COL_INDIK2,        cColSim)
  AADD( aIndik, { nNomer, nRow, nCol, 0, SAVESCREEN(nRow, nCol, nRow, nCol+1), cColSim} )
RETURN (nNomer)

FUNCTION INDIK_UPDATE(nNomer)
  STATIC aElem := {"/", "-", "\", "|"}
  local set_old := set(_SET_DEVICE,"screen")
  nNomer := ASCAN( aIndik, {|x|x[1]==nNomer} )
  IF( aIndik[nNomer][_nLen] < 4, ++aIndik[nNomer][_nLen], aIndik[nNomer][_nLen]:=1 )
  DispOutAt(aIndik[nNomer][_nRow], aIndik[nNomer][_nCol] ,aElem[aIndik[nNomer][_nLen]] ;
           , aIndik[nNomer][_nDlina])

//  @ aIndik[nNomer][_nRow], aIndik[nNomer][_nCol] SAY aElem[aIndik[nNomer][_nLen]] ;
//           COLOR aIndik[nNomer][_nDlina]
  set(_SET_DEVICE, set_OLD)
RETURN (.T.)

PROCEDURE INDIK_END(nNomer)
  IF nNomer == NIL
    nNomer := ATAIL(aIndik)[1]
  ELSE
    nNomer := ASCAN( aIndik, {|x|x[1]==nNomer} )
  ENDIF
  IF nNomer <> 0
    RESTSCREEN(aIndik[nNomer][_nRow],;
               aIndik[nNomer][_nCol],;
               aIndik[nNomer][_nRow],;
               aIndik[nNomer][_nCol]+1,;
               aIndik[nNomer][_cScreen])
    ADEL(aIndik, nNomer )
    ASIZE(aIndik, LEN(aIndik)-1) // уменьшаем масив на еденицу
  ENDIF
RETURN






/*

  Программа ПРОЦЕС от 0% до 100%



   nMaxElem - максимальное значение индикатора
   nRow     - номер строки (верх)
   nCol     - номер колонки (лево)
   cPrompt  - заголовок
   nDlina   - длина шкалы
   cColFon  - Цвет фона
   cColSim  - Цвет шкалы

   По умолчанию: по центру
*/

FUNCTION PROCES_INI(nMaxElem, nRow, nCol, cPrompt, nDlina, cColFon, cColSim, lIndik )
  LOCAL wSel:=WSelect()     //victor
  LOCAL nLen := 0, nOtstup
  LOCAL nNomer  := LEN(aProces) + 1
  local set_old := set(_SET_DEVICE,"screen")
  LOCAL cScreen
    WSELECT(0)              //victor
    cPrompt := IF(cPrompt == NIL, "Идет расчет. Ждите!", LEFT(ALLTRIM(cPrompt),MAXCOL()-6))
    nDlina  := MIN(IF(nDlina == NIL, 54, nDlina),  MAXCOL()-4)
    nLen    := MAX(LEN(cPrompt) + 6, nDlina + 3)
    nRow    := IF(nRow == NIL, INT(MAXROW()/2)-2,        nRow)
    nCol    := IF(nCol == NIL, INT(MAXCOL()/2 - nLen/2+1), nCol)
    nOtstup := IF(LEN(cPrompt)+6 > nDlina+3, INT((nLen-nDlina)/2), 2)
    cColFon := IF(cColFon == NIL, COL_INDIK1, cColFon)
    cColSim := IF(cColSim == NIL, COL_INDIK2, cColSim)
    cScreen := SAVESCREEN(nRow, nCol, nRow+5, nCol+nLen+2)

    ShadowBox(IF(!EMPTY(cPrompt),"[ "+cPrompt+" ]",),nRow,nCol,nRow+4,nCol+nLen,cColFon)

    @ nRow+1, nCol+nOtstup SAY "0"+ PADC( "50", nDlina-4) +"100" COLOR cColSim
    @ nRow+2, nCol+nOtstup SAY REPLICATE(SIMVOL1,nDlina) COLOR cColSim
    IF ValType(lIndik) == "L" .AND. lIndik
       lIndik := INDIK_NEW(nRow+3, nCol+nLen/2, cColSim )
    ENDIF
    AADD(aProces, { nNomer ,nRow, nCol, nLen, cScreen, nDlina, nOtstup, nMaxElem, 0, 0, cColSim, lIndik,NIL } )
    set(_SET_DEVICE, set_OLD)
    WSELECT(wSel)           //victor

RETURN (nNomer)



FUNCTION PROCES_UPDATE(nNomer, nProcent, nStep, nIndik )
  local set_old := set(_SET_DEVICE,"screen")

  nNomer := ASCAN( aProces, {|x|x[1]==nNomer} )

  IF nNomer <> 0

     IF nProcent == NIL
        IF aProces[nNomer][_nMaxElem] != NIL  // если максимальное значение задано
          aProces[nNomer][_nElem] += IF(nStep ==  NIL, 1, nStep)
          aProces[nNomer][_nProcent] := DIV(aProces[nNomer][_nElem] , aProces[nNomer][_nMaxElem])

        ELSE
          aProces[nNomer][_nProcent] += 0.01  // прибавляем 1%
        ENDIF

     ELSE
       aProces[nNomer][_nProcent] := nProcent
     ENDIF

     IF nIndik == NIL
       IF aProces[nNomer][_nLen0]==NIL.OR.aProces[nNomer][_nLen0]!=INT(aProces[nNomer][_nProcent]*aProces[nNomer][_nDlina]) //HARBOUR
         DispOutAt(aProces[nNomer][_nRow]+2,;
         aProces[nNomer][_nCol]+aProces[nNomer][_nOtstup] ;
         ,PADR(;
                   REPLICATE( SIMVOL2, ;
                              MIN(INT(aProces[nNomer][_nProcent]*  ;  // процент выполнения
                                      aProces[nNomer][_nDlina];
                                     ), ;  // длина шкалы
                                  aProces[nNomer][_nDlina];
                                 );
                             ),;
                  aProces[nNomer][_nDlina], SIMVOL1;
                 ) ; // дополнение до длины шкалы символом фона
        ,aProces[nNomer][_cColSimv])

        // запомним положение курсора
           aProces[nNomer][_nLen0] := INT(aProces[nNomer][_nProcent]*  ;  // процент выполнения
                                     aProces[nNomer][_nDlina])       // длина шкалы

        ENDIF

        IF ValType(aProces[nNomer][_lIndik])=="N"
          INDIK_UPDATE(aProces[nNomer][_lIndik])
        ENDIF
     ELSE
       DispOutAt(aProces[nNomer][_nRow]+aProces[nNomer][_nLen]+1,;
         aProces[nNomer][_nCol] ;
         ,'█' ,aProces[nNomer][_nOtstup])  // на самом деле это цвет фона
       DispOutAt(aProces[nNomer][_nRow]+INT(aProces[nNomer][_nProcent]*  ;  // процент выполнения
                                    aProces[nNomer][_nDlina])+1 , ;  // длина шкалы
         aProces[nNomer][_nCol] ;
         ,'█' ,aProces[nNomer][_cColSimv])
       // запомнтм положение курсора
       aProces[nNomer][_nLen] := INT(aProces[nNomer][_nProcent]*  ;  // процент выполнения
                                     aProces[nNomer][_nDlina])       // длина шкалы
     ENDIF

  ENDIF
  set(_SET_DEVICE, set_OLD)

RETURN (.T.)



PROCEDURE PROCES_END(nNomer)
  local set_old := set(_SET_DEVICE,"screen")
  IF nNomer == NIL
    nNomer := ATAIL( aProces )[1]
  ELSE
    nNomer := ASCAN( aProces, {|x|x[1]==nNomer} )
  ENDIF
  IF nNomer <> 0
    IF ValType(aProces[nNomer][_lIndik])=="N"
      INDIK_END(aProces[nNomer][_lIndik])
    ENDIF
    RESTSCREEN(aProces[nNomer][_nRow],;
               aProces[nNomer][_nCol],;
               aProces[nNomer][_nRow]+5,;
               aProces[nNomer][_nCol]+aProces[nNomer][_nLen]+2,;
               aProces[nNomer][_cScreen])
    ADEL( aProces, nNomer )
    ASIZE(aProces, LEN(aProces)-1) // уменьшаем масив на еденицу
  ENDIF
  set(_SET_DEVICE, set_OLD)
RETURN

/*

  Программа Вертикальный ПРОЦЕС от 0% до 100%



   nMaxElem - максимальное значение индикатора
   nRow     - номер строки (верх)
   nCol     - номер колонки (лево)
   nDlina   - длина шкалы
   cColFon  - Цвет фона
   cColSim  - Цвет шкалы

   По умолчанию: справа
*/

FUNCTION VPROCES_INI(nMaxElem, nRow, nCol, nDlina, cColFon, cColSim)
  LOCAL nNomer  := LEN(aProces) + 1, cScreen, i
  local set_old := set(_SET_DEVICE,"screen")

  nRow    := IF(nRow == NIL, 2,          nRow)
  nDlina  := MIN(IF(nDlina == NIL, MAXROW()-3, nDlina),  MAXROW()-nRow)
  nCol    := IF(nCol == NIL, MAXCOL(), nCol)
  cColFon := IF(cColFon == NIL, COL_INDIK1, cColFon)
  cColSim := IF(cColSim == NIL, COL_INDIK3, cColSim)
  cScreen := SAVESCREEN(nRow, nCol, nRow+nDlina, nCol)

  @ nRow, nCol        SAY chr(24) COLOR cColSim
  @ nRow+nDlina, nCol SAY chr(25) COLOR cColSim
  FOR i := 1 TO nDlina-1
    @ nRow+i, nCol       SAY "█" COLOR cColFon
  NEXT

  AADD(aProces, { nNomer, nRow, nCol, 1, cScreen, nDlina-2, cColFon, nMaxElem, 0, 0, COL_INDIK4, NIL } )
  set(_SET_DEVICE, set_OLD)

RETURN (nNomer)

PROCEDURE VPROCES_END(nNomer)
  local set_old := set(_SET_DEVICE,"screen")
  IF nNomer == NIL
    nNomer := ATAIL( aProces )[1]
  ELSE
    nNomer := ASCAN( aProces, {|x|x[1]==nNomer} )
  ENDIF
  IF nNomer <> 0
    RESTSCREEN(aProces[nNomer][_nRow],;
               aProces[nNomer][_nCol],;
               aProces[nNomer][_nRow]+aProces[nNomer][_nDlina]+2,;
               aProces[nNomer][_nCol],;
               aProces[nNomer][_cScreen])
    ADEL( aProces, nNomer )
    ASIZE(aProces, LEN(aProces)-1) // уменьшаем масив на еденицу
  ENDIF
  set(_SET_DEVICE, set_OLD)
RETURN





