FWH 1908: Meter Control Enhancements

FWH 1908: Meter Control Enhancements

Postby nageswaragunupudi » Wed Sep 25, 2019 2:22 pm

FWH 1908 introduces many enhancements to the existing TMeter class. The existing syntax for creating Meter control is:
Code: Select all  Expand view  RUN


@ <nRow>, <nCol> METER [ <oMeter> VAR ] <nActual> ;
[ TOTAL <nTotal> ] ;
[ SIZE <nWidth>, <nHeight> ];
[ OF <oWnd> ] ;
[ <update: UPDATE > ] ;
[ <lPixel: PIXEL > ] ;
[ FONT <oFont> ] ;
[ PROMPT <cPrompt> ] ;
[ <lNoPercentage: NOPERCENTAGE > ] ;
[ <color: COLOR, COLORS> <nClrPane>, <nClrText> ] ;
[ BARCOLOR <nClrBar>, <nClrBText> ] ;
[ <lDesign: DESIGN> ] ;
 


The meter is displayed as a horizontal bar.
BARCOLOR <nClrBar> (default CLR_BLUE) is used to display the progress.
COLORS <nClrPane> (default oWnd:nClrPane) is used to display the remaining part.
Both the colors need to be RGB color constants.

Enhancements:
1) Both <nClrBar> and <nClrPane> can now be any combination of the following:
a) Standard RGB colors (present behaviour continues)
b) Alpha colors (transparent) Range 0x01000000 to 0xffffffff
c) Color Gradient (as arrays) consisting of RGB colors and Alpha colors
d) Brush objects of bitmaps/images or any other style
e) Bitmap/Image file or resource.
and
f) Codeblocks returning any colors or gradients. This enables changing colors during the progress depending on the progress or other variables.

2) PROMPT <cText> can also be a codeblock.

All the codeblocks are evaluated with progress expressed as a fraction (0.0 to 1.0) as parameter.

Examples of Usage:
Code: Select all  Expand view  RUN

BARCOLOR { |n| ARGB( n, CLR_HBLUE ) }
PROMPT { |n| TRANSFORM( nSecs * ( 1 - n ) / n, "### Secconds remaining" ) }
 


3) Fix: UPDATE clause had no effect. Now working

4) New clause BORDER <nBorderClr>
nBorderClr can be an RGB color constant or array of {color,width} or a Pen Object. If specified, border is drawn around the meter using the color and thickness.

5) New Optional clause BMPARRAY

If this clause is specified, <nClrBar> and <nClrPane> can be assigned with bitmap handles or bmp files. The meter will display an array of 5 or 10 of these bitmaps depending on the relative width of the control. Progress is displayed with the first bitmap and remaining part is displayed with second bitmap. If only colors are specified, STAR shaped bitmaps are generated internally and displayed using the colors specified.


Sample:
Image

Sample Code (relevant part) fwh\samples\meter01.prg
Code: Select all  Expand view  RUN

   nRow  := 50
   @ nRow, 40 METER aMeter[ 1 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
      COLOR    "..\bitmaps\backgrnd\beach.bmp", CLR_BLACK ;
      BARCOLOR "..\bitmaps\backgrnd\pebbles.bmp", CLR_WHITE ;
      TOTAL nTotal FONT oFont BORDER CLR_BLACK UPDATE

   nRow  += 90
   @ nRow, 40 METER aMeter[ 2 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
      COLOR    0x60ffffff, CLR_BLACK ;
      BARCOLOR 0x60ff0000, CLR_WHITE ;
      TOTAL nTotal FONT oFont BORDER CLR_WHITE UPDATE

   nRow  += 90
   @ nRow, 40 METER aMeter[ 3 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
      COLOR    {{ 0.5, CLR_GRAY, CLR_WHITE },{ 0.5, CLR_WHITE, CLR_GRAY } }, CLR_BLACK ;
      BARCOLOR {{ 0.5, CLR_GREEN, CLR_HGREEN },{ 0.5, CLR_HGREEN, CLR_GREEN }, 0 }, CLR_BLACK ;
      TOTAL nTotal FONT oFont BORDER CLR_BLACK UPDATE

   nRow  += 90
   @ nRow, 40 METER aMeter[ 3 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
      COLOR    {{ 0.5, 0xf0505050, 0x80FFFFFF },{ 0.5, 0x80ffffff, 0xf0505050 }, 0 }, CLR_BLACK ;
      BARCOLOR {{ 0.5, 0xf0004000, 0x8000ff00 },{ 0.5, 0x8000ff00, 0xf0004000 }, 0 }, CLR_BLACK ;
      TOTAL nTotal FONT oFont BORDER CLR_WHITE UPDATE

   nRow  += 90
   @ nRow, 40 METER aMeter[ 4 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
      COLOR    {{ 0.5, CLR_GRAY, CLR_WHITE },{ 0.5, CLR_WHITE, CLR_GRAY }, .f. }, CLR_BLACK ;
      BARCOLOR {{ 0.5, 0x002000, 0x80ff80 },{ 0.5, 0x80ff80, 0x002000 }, 2 }, CLR_BLACK ;
      TOTAL nTotal FONT oFont BORDER CLR_BLACK UPDATE

   nRow  += 90
   bAct  := { |n| n /= 2, { { 0.5-n, CLR_GREEN, CLR_GREEN }, { .25, CLR_GREEN, CLR_HGREEN }, ;
                            { .25, CLR_HGREEN, CLR_GREEN }, { n, CLR_GREEN, CLR_GREEN } } }
   bRem  := { |n| n /= 2, { { n, CLR_GRAY, CLR_GRAY }, { .25, CLR_GRAY, CLR_HGRAY }, ;
                            { .25, CLR_HGRAY, CLR_GRAY }, { 0.5-n, CLR_GRAY, CLR_GRAY } } }

   @ nRow, 40 METER aMeter[ 5 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
      COLOR    bRem, CLR_BLACK ;
      BARCOLOR bAct, CLR_BLACK ;
      TOTAL nTotal FONT oFont BORDER CLR_BLACK UPDATE

   nRow  := 600
   @ nRow, 250 METER nActual SIZE 300,60 PIXEL OF oDlg ;
      BARCOLOR CLR_HRED, CLR_WHITE ;
      TOTAL nTotal FONT oFont UPDATE BMPARRAY
 


Incidentally, this sample demonstrates the new feature of displaying outlined text (hollow text). This is the code:

Code: Select all  Expand view  RUN

   oDlg:bPainted := <|hDC|
      local nRow  := 20
      oDlg:SayHollow( "BITMAP BRUSHES", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
      nRow  += 90
      oDlg:SayHollow( "ALPHA COLORS", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
      nRow  += 90
      oDlg:SayHollow( "GRADIENTS", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
      nRow  += 90
      oDlg:SayHollow( "ALPHA COLOR GRADIENTS", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
      nRow  += 90
      oDlg:SayHollow( "HOTIZONTAL GRADIENTS", { nRow, 25, nRow + 30, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
      nRow  += 90
      oDlg:SayHollow( "COLOR ANIMATION", { nRow, 25, nRow + 30, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
      nRow  := 570
      oDlg:SayHollow( "RATINGS", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_HRED, nil, CLR_WHITE, 3 )
      return nil
      >
 


Next enhancement:
Circular Meter:

For this we need to add the clauses:
Code: Select all  Expand view  RUN

CIRCULAR [INNERDIA <nDia>] [FILLCOLOR <nInnerColor>]
 


For this to work well, the SIZE <nWidth> and <nHeight> need to equal or nearly equal.

By default, the appearance is like a pie chart.
If innerdia is specified, either in pixels or as a ratio (0.1 to 0.9) to the outer diameter, the inner circle is painted separately with fillcolor.
If no fillcolor is specified, the inner circle is left transparent.

In this case also, the three colors nClrBar, nClrPane and nFillColor can be
a) RGB colors
b) alpha colors
c) gradients of RGB colors (alpha color gradients not supported)
d) Brush objects
e) Images
and also
f) codeblocks returning any color.

Sample of Circular Meters

Image

Source code: (relevant part)
fwh\samples\meter02.prg
Code: Select all  Expand view  RUN

#define MANGOES "https://img.huffingtonpost.com/asset/5c1225351f0000f00626a771.jpeg?ops=scalefit_630_noupscale"
#define APPLES  "https://cdn.images.express.co.uk/img/dynamic/109/590x/Apple-links-587431.jpg"
#define GRAPES  "https://img-aws.ehowcdn.com/350x235p/s3-us-west-1.amazonaws.com/contentlab.studiod/getty/f36944f5be3843ddafebd89b1dca105f.jpg"
//-------------

   nRow  := 100
   @ nRow, 40 METER aMeter[ 1 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
      COLOR    "..\bitmaps\backgrnd\beach.bmp", CLR_BLACK ;
      BARCOLOR "..\bitmaps\backgrnd\pebbles.bmp", CLR_WHITE ;
      TOTAL nTotal FONT oFont BORDER CLR_BLACK ;
      CIRCULAR INNERDIA 0.5 ;
      UPDATE

   @ nRow, 300 METER aMeter[ 2 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
      COLOR    {{ 0.5, CLR_GRAY, CLR_HGRAY },{ 0.5, CLR_HGRAY, CLR_GRAY }}, CLR_BLACK ;
      BARCOLOR {{ 0.5, CLR_GREEN, CLR_HGREEN },{ 0.5, CLR_HGREEN, CLR_GREEN }}, CLR_WHITE ;
      TOTAL nTotal FONT oFont BORDER CLR_WHITE ;
      CIRCULAR INNERDIA 0.4 ;
      UPDATE

   @ nRow, 560 METER aMeter[ 3 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
      COLOR    APPLES, CLR_BLACK ;
      BARCOLOR MANGOES, CLR_WHITE ;
      TOTAL nTotal FONT oFont BORDER CLR_WHITE ;
      CIRCULAR INNERDIA { |n| 0.3 + ( n * 0.4 ) } ;
      FILLCOLOR GRAPES ;
      UPDATE

   nRow  += 350
   @ nRow, 40 METER aMeter[ 4 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
      COLOR    0x60ff0000, CLR_BLACK ;
      BARCOLOR 0x6000ff00, CLR_WHITE ;
      TOTAL nTotal FONT oFont BORDER CLR_BLACK ;
      CIRCULAR INNERDIA { |n| 0.2 + ( 0.6 * n ) } ;
      FILLCOLOR { |n| NARGB( 210 - ( n * 200 ), CLR_BLACK ) } ;
      UPDATE

   @ nRow,300 METER aMeter[ 5 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
      COLOR    METRO_STEEL, CLR_BLACK ;
      BARCOLOR METRO_AMBER, CLR_WHITE ;
      TOTAL nTotal FONT oFont BORDER CLR_WHITE ;
      CIRCULAR INNERDIA { |n| 0.3 + ( n * 0.4 ) } ;
      FILLCOLOR {{ 1, CLR_HGREEN, 0X002000 }} ;
      UPDATE

   @ nRow,560 METER aMeter[ 6 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
      COLOR    { |n| NARGB( n * 255, CLR_HRED ) }, CLR_BLACK ;
      BARCOLOR { |n| NARGB( ( 1 - n ) * 255, CLR_GREEN ) }, CLR_WHITE ;
      TOTAL nTotal FONT oSmal BORDER CLR_WHITE ;
      PROMPT { |n| TRANSFORM( ( 1 - n ) * 15, "## SECONDS" ) + CRLF + "MORE" } ;
      CIRCULAR INNERDIA 0.5 ;
      FILLCOLOR { |n| NARGB( 210 - ( n * 200 ), CLR_BLACK ) } ;
      UPDATE

   @ 670,40 SLIDER nActual SIZE 720,20 PIXEL OF oDlg SLIMSTYLE ;
      COLORS nil,nil,CLR_WHITE ;
      RANGE 0,nTotal ON CHANGE oDlg:Update() ;
 


Now the full syntax:
Code: Select all  Expand view  RUN

@ <nRow>, <nCol> METER [ <oMeter> VAR ] <nActual> ;
[ TOTAL <nTotal> ] ;
[ SIZE <nWidth>, <nHeight> ];
[ OF <oWnd> ] ;
[ <update: UPDATE > ] ;
[ <lPixel: PIXEL > ] ;
[ FONT <oFont> ] ;
[ PROMPT <cPrompt> ] ;
[ <lNoPercentage: NOPERCENTAGE > ] ;
[ <color: COLOR, COLORS> <nClrPane>, <nClrText> ] ;
[ BARCOLOR <nClrBar>, <nClrBText> ] ;
[ <circ:CIRCULAR> [INNERDIA <nInnerDia> ] ] ;
[ FILLCOLOR <nClrFill> ] ;
[ BORDER <clrBorder> ] ;
[ <bmpArray:BMPARRAY> ] ;
[ <lDesign: DESIGN> ] ;

// nClrBar, nClrPane, nClrFill can be RGB or Alpha color, oBrush,
// hBitmap, aGradient or any Image source( file/resource/webaddress)
// Options CIRCULR and BMPARRAY or mutually exclusve.
 


Circular Meter without creating as Control:

It is also possible to draw circular meters, in any window, dialog or inside any other control, without actually creating a meter contol, by using this function:

Code: Select all  Expand view  RUN

function PaintCircularMeter( oWnd, aRect, nInnerDia, nActual, nTotal, aColors, aPen )
 


The following example demonstrates using this function:

Image

Sample code:
Code: Select all  Expand view  RUN

   @ 20,20 XBROWSE oBrw SIZE -20,-20 PIXEL OF oDlg ;
      DATASOURCE "STATES" AUTOCOLS CELL LINES ;
      NOBORDER FONT oBrwFont

   WITH OBJECT oBrw
      :lTransparent  := .t.
      :nStretchCol   := STRETCHCOL_WIDEST
      :bPaintBack     := <||
         FillRect( oBrw:GetDC(), GetClientRect( oBrw:hWnd ), oBrush:hBrush )
         PaintCircularMeter( oBrw, {130,30,430,330}, 0.5, oBrw:KeyNo, oBrw:nLen, ;
            { 0x6000ff00, 0x60FA6800 } )
         oBrw:ReleaseDC()
         return nil
         >

      :CreateFromCode()
   END
 
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10646
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: FWH 1908: Meter Control Enhancements

Postby nageswaragunupudi » Wed Sep 25, 2019 2:35 pm

Full source code of the above library function PaintCircularMeter(..)
This function works independently of the class.

Code: Select all  Expand view  RUN
function PaintCircularMeter( oWnd, aRect, nInnerDia, nActual, nTotal, aColors, aPen )

   local hDC
   local nRadius, oRectInner, nRatio, oBold
   local hRgnFull, hRgnInner

   nRadius     := Min( aRect[ 4 ] - aRect[ 2 ], aRect[ 3 ] - aRect[ 1 ] ) / 2
   nRatio      := nActual / nTotal
   hDC         := oWnd:GetDC()
   oBold       := oWnd:oFont:Bold()

   DEFAULT aColors := { METRO_AMBER, METRO_STEEL }

   if !Empty ( nInnerDia )

      if nInnerDia < 1.0
         nInnerDia   *= ( 2 * nRadius )
      endif

      oRectInner  := TRect():New( 0, 0, nInnerDia, nInnerDia )
      oRectInner:FitInside( aRect )

      hRgnFull    := CreateRectRgn( aRect[ 2 ], aRect[ 1 ], aRect[ 3 ] + 1, aRect[ 4 ] + 1 )
      hRgnInner   := CreateEllipticRgnIndirect( oRectInner:aRect )
      CombineRgn( hRgnFull, hRgnFull, hRgnInner, 4 )
      DeleteObject( hRgnInner )
      SelectClipRgn( hDC, hRgnFull )

   endif

   oWnd:PieChart( aRect, { nActual, nTotal - nActual }, aColors, aPen )

   if hRgnFull != nil
      SelectClipRgn( hDC )
      DeleteObject( hRgnFull )
      oWnd:Ellipse( oRectInner:nTop, oRectInner:nLeft, oRectInner:nBottom, oRectInner:nRight, aPen )
   endif

   oWnd:SayHollow( TRANSFORM( 100.0 * nRatio, "999%" ), aRect, "", ;
                     oBold, CLR_BLACK, nil, CLR_WHITE, 2 )

   oBold:End()
   oWnd:ReleaseDC()

return nil
 


Note: oWnd:PieChart(...) is a new method introduced in FWH 1908
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10646
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: FWH 1908: Meter Control Enhancements

Postby TimStone » Wed Sep 25, 2019 4:39 pm

These enhancements look very nice. I am looking forward to working with them when 1908 is released.
Tim Stone
http://www.MasterLinkSoftware.com
http://www.autoshopwriter.com
timstone@masterlinksoftware.com
Using: FWH 23.10 with Harbour 3.2.0 / Microsoft Visual Studio Community 2022-24 32/64 bit
User avatar
TimStone
 
Posts: 2944
Joined: Fri Oct 07, 2005 1:45 pm
Location: Trabuco Canyon, CA USA


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 55 guests