Files
comun/utile/foxcharts/foxcharts.vc2

10347 lines
322 KiB
Plaintext
Raw Blame History

*--------------------------------------------------------------------------------------------------------------------------------------------------------
* (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!!
*--------------------------------------------------------------------------------------------------------------------------------------------------------
*< FOXBIN2PRG: Version="1.21" SourceFile="foxcharts.vcx" CPID="1252" /> (Solo para binarios VFP 9 / Only for VFP 9 binaries)
*
*
DEFINE CLASS _chartcanvas AS imgcanvas OF "gdiplusx.vcx" && Internal use. Not to be used directly !
*< CLASSDATA: Baseclass="image" Timestamp="" Scale="Pixels" Uniqueid="" />
*<PropValue>
Name = "_chartcanvas"
*</PropValue>
PROCEDURE Init
* Check if using Windows7 and not SP2
IF (OS(3) = "6") AND ;&& (same as Vista)
(OS(4) = "1") AND ; &&(Vista = 0)
(VERSION(4) < "09.00.0000.5411") && VFP 9.0 SP2
This.RenderMode = 1 && File BMP - slower performance
ENDIF
DODEFAULT()
ENDPROC
ENDDEFINE
DEFINE CLASS _legend AS label && Internal use. Not to be used directly !
*< CLASSDATA: Baseclass="label" Timestamp="" Scale="Pixels" Uniqueid="" />
*<DefinedPropArrayMethod>
*m: caption_assign
*m: reset && Resets the legend GDI+ objects
*m: rotation_assign
*m: _drawstring
*m: _setup
*m: _updatemeasures
*m: _value_assign
*p: backcoloralpha
*p: forecoloralpha
*p: format && Specifies the input and output formatting of a control's Value property.
*p: format2
*p: isparent
*p: ogfx
*p: rotationcenter
*p: _forceformat
*p: _height
*p: _initialized
*p: _memberdata && XML Metadata for customizable properties
*p: _obrush
*p: _ofont
*p: _orectangle
*p: _ostringformat
*p: _transfcaption
*p: _value
*p: _vartype
*p: _width
*</DefinedPropArrayMethod>
HIDDEN AddProperty,Anchor,AutoSize,BackStyle,BorderStyle,Click,CloneObject,ColorScheme,ColorSource,Comment,DblClick,Destroy,DisabledBackColor,DisabledForeColor,DragDrop,DragIcon,DragMode,DragOver,Drag,Error,FontCondense,FontExtend,FontOutline,FontShadow,GotFocus,HelpContextID,Init,LostFocus,MiddleClick,MouseDown,MouseEnter,MouseIcon,MouseLeave,MouseMove,MousePointer,MouseUp,MouseWheel,Move,OLECompleteDrag,OLEDragDrop,OLEDragMode,OLEDragOver,OLEDragPicture,OLEDrag,OLEDropEffects,OLEDropHasData,OLEDropMode,OLEGiveFeedback,OLESetData,OLEStartDrag,ParentClass,Parent,ReadExpression,ReadMethod,Refresh,ResetToDefault,RightClick,RightToLeft,SaveAsClass,ShowWhatsThis,StatusBarText,Style,TabIndex,TabStop,Tag,ToolTipText,UIEnable,WhatsThisHelpID,WordWrap,WriteExpression,WriteMethod,ZOrder
*<PropValue>
AutoSize = .T.
backcoloralpha = 0
Caption = "Legend"
DragIcon = ..\
forecoloralpha = 255
format =
format2 =
Height = 17
isparent = .F.
Name = "_legend"
ogfx = .F.
OLEDragPicture = ..\
rotationcenter = 0
Width = 44
_forceformat =
_height = 0
_initialized = .F.
_memberdata = <VFPData>
<memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="whatsthishelpid" type="property" display="WhatsThisHelpID"/>
<memberdata name="_setup" type="method" display="_Setup"/>
<memberdata name="forecoloralpha" type="property" display="ForeColorAlpha"/>
<memberdata name="backcoloralpha" type="property" display="BackColorAlpha"/>
<memberdata name="width" type="property" display="Width"/>
<memberdata name="oledragpicture" type="property" display="OLEDragPicture"/>
<memberdata name=<VFPData><memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="whatsthishelpid" type="property" display="WhatsThisHelpID"/>
<memberdata name="_setup" type="method" display="_Setup"/>
<memberdata name="forecoloralpha" type="property" display="ForeColorAlpha"/>
<memberdata name="backcoloralpha" type="property" display="BackColorAlpha"/>
<memberdata name="width" type="property" display="Width"/>
<memberdata name="oledragpicture" type="property" display="OLEDragPicture"/>
<memberdata name=<VFPData><memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="whatsthishelpid" type="property" display="WhatsThisHelpID"/>
<memberdata name="_setup" type="method" display="_Setup"/>
<memberdata name="forecoloralpha" type="property" display="ForeColorAlpha"/>
<memberdata name="backcoloralpha" type="property" display="BackColorAlpha"/>
<memberdata name="width" type="property" display="Width"/>
<memberdata name="oledragpicture" type="property" display="OLEDragPicture"/>
<memberdata name=<VFPData><memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="whatsthishelpid" type="property" display="WhatsThisHelpID"/>
<memberdata name="_setup" type="method" display="_Setup"/>
<memberdata name="forecoloralpha" type="property" display="ForeColorAlpha"/>
<memberdata name="backcoloralpha" type="property" display="BackColorAlpha"/>
<memberdata name="width" type="property" display="Width"/>
<memberdata name="oledragpicture" type="property" display="OLEDragPicture"/>
<memberdata name=<VFPData><memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="whatsthishelpid" type="property" display="WhatsThisHelpID"/>
<memberdata name="_setup" type="method" display="_Setup"/>
<memberdata name="forecoloralpha" type="property" display="ForeColorAlpha"/>
<memberdata name="backcoloralpha" type="property" display="BackColorAlpha"/>
<memberdata name="width" type="property" display="Width"/>
<memberdata name="oledragpicture" type="property" display="OLEDragPicture"/>
<memberdata name=<VFPData><memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="autosize" type="property" display="AutoSize"/>
<memberdata name="whatsthishelpid" type="property" display="WhatsThisHelpID"/>
</VFPData>
_obrush =
_ofont =
_orectangle =
_ostringformat =
_transfcaption =
_value =
_vartype =
_width = 0
*</PropValue>
HIDDEN PROCEDURE caption_assign
LPARAMETERS tuCaption
LOCAL lcType
m.lcType = VARTYPE(m.tuCaption)
IF m.lcType $ "DLTN" && Logical, Date, DateTime, Numeric
m.tuCaption = TRANSFORM(m.tuCaption)
ENDIF
This.Caption = m.tuCaption
This._UpdateMeasures(.F.) && Character passed
*!* C Character, Memo, Varchar, Varchar (Binary)
*!* D Date
*!* G General
*!* L Logical
*!* N Numeric, Float, Double, or Integer
*!* O Object
*!* Q Blob, Varbinary
*!* T DateTime
*!* U Unknown or variable does not exist
*!* X Null
*!* Y Currency
ENDPROC
HIDDEN PROCEDURE Init
THIS.IsParent = TYPE('this.Parent.Name')='C'
IF THIS.IsParent AND VARTYPE(THIS.PARENT.oGfx)='O'
THIS.oGfx = THIS.PARENT.oGfx
ENDIF
ENDPROC
PROCEDURE reset && Resets the legend GDI+ objects
This._Setup()
This._UpdateMeasures()
ENDPROC
PROCEDURE rotation_assign
LPARAMETERS tnRotation
IF tnRotation < 0
tnRotation = tnRotation + 360
ENDIF
THIS.Rotation = tnRotation
ENDPROC
PROCEDURE _drawstring
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical
LOCAL x1, y1, lnAlign, lnMode, xBack, llBar
llBar = IIF(This.Parent.Name = "ShapeLegend",.T., .F.)
lnMode = 0 && 0 = x,y Coordinates ; 1 = xfcRectangle coordinates
lnAlign = This.Alignment
* 0 = Left 1 = Right 2 = Center
LOCAL loGfx as xfcGraphics
loGfx = This.Parent.oGfx
WITH _Screen.System.Drawing
DO CASE
CASE VARTYPE(tnWidth) + VARTYPE(tnHeight) = "NN"
lnMode = 1
* Create a STRINGFORMAT object in order to draw the string centered in the image
LOCAL loStringFmt as xfcStringFormat
LOCAL lnGdipAlign
loStringFmt = .StringFormat.New()
DO CASE
CASE lnAlign = 2 && Center
lnGdipAlign = .StringAlignment.Center
CASE lnAlign = 1
lnGdipAlign = .StringAlignment.Far
OTHERWISE
lnGdipAlign = .StringAlignment.Near
ENDCASE
loStringFmt.Alignment = lnGdipAlign
IF tlVertical
loStringFmt.FormatFlags = .StringFormatFlags.DirectionVertical
loStringFmt.LineAlignment = .StringAlignment.Center
ENDIF
LOCAL loSize as xfcSize
IF tlVertical
loSize = .Size.New(This.Parent.Width, This.Parent.Height)
ELSE
loSize = .Size.New(tnWidth, tnHeight)
ENDIF
loSize = loGfx.MeasureString(;
This._TransfCaption, This._oFont, loSize, loStringFmt)
This._Height = CEILING(loSize.Height)
This._Width = CEILING(loSize.Width)
LOCAL loRect as xfcRectangle
loRect = .Rectangle.New(tnX, tnY, tnWidth, This._Height)
x1 = tnX
y1 = tnY
IF tlVertical
xBack = tnX + tnWidth / 2 - (This._Width / 2)
DO CASE
CASE lnAlign = 0 && Left
y1 = tnY
CASE lnAlign = 1 && Right
y1 = tnY + tnHeight - This._Height
CASE lnAlign = 2 && Center
y1 = tnY + (tnHeight / 2) - (This._Height / 2)
ENDCASE
ELSE
DO CASE
CASE lnAlign = 0 && Left
xBack = tnX
CASE lnAlign = 1 && Right
xBack = tnX + tnWidth - This._Width
CASE lnAlign = 2 && Center
xBack = tnX + (tnWidth - This._Width) / 2
ENDCASE
ENDIF
CASE lnAlign = 0 && Left
STORE tnX TO x1, xBack
y1 = tnY
CASE lnAlign = 1 && Right
x1 = tnX - This._Width
xBack = x1
y1 = tnY
CASE lnAlign = 2 && Center
x1 = tnX - (This._Width / 2)
xBack = x1
y1 = tnY
ENDCASE
LOCAL lnRotation
lnRotation = This.Rotation
IF lnRotation <> 0
WITH _SCREEN.System.Drawing
LOCAL loPointF as xfcPointF
LOCAL loMatrix as xfcMatrix
loMatrix = .Drawing2D.Matrix.New()
IF lnMode = 1
loPointF = .PointF.New(tnX, tnY) && this is the point of rotation
ELSE
DO CASE
CASE lnAlign = 0 && Left
loPointF = .PointF.New(x1 + 5, y1 + This._Height / 2) && this is the point of rotation
CASE lnAlign = 1 && Right
loPointF = .PointF.New(x1 + This._Width - 5, y1 + This._Height / 2) && this is the point of rotation
CASE lnAlign = 2 && Center
loPointF = .PointF.New(x1 + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation
ENDCASE
ENDIF
loMatrix.RotateAt(lnRotation, loPointF)
loGfx.MultiplyTransform(loMatrix)
ENDWITH
ENDIF
lnRotationCenter = This.RotationCenter
* Center Rotation
IF lnRotationCenter <> 0
WITH _SCREEN.System.Drawing
LOCAL loPointFC as xfcPointF
LOCAL loMatrixC as xfcMatrix
loMatrixC = .Drawing2D.Matrix.New()
* loPointFC = .PointF.New(x1 + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation
loPointFC = .PointF.New(xBack + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation
loMatrixC.RotateAt(lnRotationCenter, loPointFC)
loGfx.MultiplyTransform(loMatrixC)
ENDWITH
ENDIF
IF This.BackColorAlpha > 0
* Draw the BackGround Rectangle
WITH _Screen.System.Drawing
IF lnMode = 0 && default
loGfx.FillRectangle( ;
.SolidBrush.New(.Color.FromARGB(This.BackColorAlpha, This.BackColor)), ;
x1, y1, This._Width, This._Height)
ELSE
loGfx.FillRectangle( ;
.SolidBrush.New(.Color.FromARGB(This.BackColorAlpha, This.BackColor)), ;
xBack, y1, This._Width, This._Height)
ENDIF
ENDWITH
ENDIF
* Draw the Text
IF lnMode = 0
loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, x1, y1)
ELSE
IF tlVertical
loRect = .Rectangle.New(xBack, y1, This._Width, This._Height)
loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, loRect, loStringFmt)
ELSE
loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, loRect, loStringFmt)
ENDIF
ENDIF
IF lnRotation <> 0 OR lnRotationCenter <> 0
loGfx.ResetTransform()
ENDIF
ENDWITH
RETURN
ENDPROC
PROCEDURE _setup
* Update the FONT object
LOCAL liStyle
liStyle = 0 && Regular
IF This.FontBold
liStyle = liStyle + 1
ENDIF
IF This.FontItalic
liStyle = liStyle + 2
ENDIF
IF This.FontStrikethru
liStyle = liStyle + 8
ENDIF
IF This.FontUnderline
liStyle = liStyle + 4
ENDIF
* Prepare the font object
LOCAL lcFont
lcFont = IIF(EMPTY(This.FontName), This.Parent.FontName, This.FontName)
* If no font was selected, then take the _Screen one!
IF EMPTY(lcFont)
lcFont = _Screen.FontName
ENDIF
IF EMPTY(lcFont)
lcFont = "Arial"
ENDIF
WITH _Screen.System.Drawing
LOCAL loFont as xfcFont
loFont = .Font.New(lcFont, This.FontSize, liStyle)
This._oFont = loFont
* Update the BRUSH object
LOCAL loColor as xfcColor
LOCAL lnColor
lnColor = IIF(This.Parent.BrushType = 3, 0, This.ForeColor)
loColor = .Color.FromArgb(This.ForeColorAlpha, lnColor)
LOCAL loBrush as xfcSolidBrush
loBrush = .SolidBrush.New(loColor)
This._oBrush = loBrush
ENDWITH
This._initialized = .T.
ENDPROC
PROCEDURE _updatemeasures
LPARAMETERS tlNumeric
IF VARTYPE(THIS.oGfx)#'O' AND THIS.IsParent
THIS.oGfx = THIS.PARENT.oGfx
ENDIF
IF VARTYPE(THIS.oGfx) <> "O"
RETURN
ENDIF
* Measure the Legend height
IF VARTYPE(THIS._oBrush) + VARTYPE(THIS._oFont) <> "OO" OR NOT THIS._initialized
THIS._Setup()
ENDIF
LOCAL lcCaption, lcFormat
* _ForceFormat is a forced formatting managed directly from FoxCharts
lcFormat = IIF(EMPTY(ALLTRIM(THIS._ForceFormat)), THIS.FORMAT, ALLTRIM(THIS._ForceFormat))
IF tlNumeric
IF VARTYPE(THIS._Value) = "C"
lcCaption = THIS._Value
ELSE
IF this.IsParent and EMPTY(lcFormat)
lcFormat = "999,999,999,999" + ;
IIF(THIS.PARENT._ValueDecimals > 0, ;
"." + REPLICATE("9", THIS.PARENT._ValueDecimals), "")
ENDIF
lcCaption = ALLTRIM(TRANSFORM(THIS._Value, lcFormat))
IF this.IsParent and THIS.PARENT._ValueDecimals>0
lcCaption=RTRIM(RTRIM(lcCaption,'0'),'.')
ENDIF
ENDIF
ELSE
lcCaption = STRTRAN(THIS.CAPTION,[CHR(13)+CHR(10)], CHR(13)+CHR(10),-1,-1,1)
lcCaption = ALLTRIM(textmerge(lcCaption))
ENDIF
LOCAL loSize AS xfcSize
loSize = THIS.oGfx.MeasureString(lcCaption, THIS._oFont) &&, This._oStringFormat)
THIS._Height = loSize.HEIGHT
THIS._Width = CEILING(loSize.WIDTH)
THIS._TransfCaption = lcCaption
ENDPROC
PROCEDURE _value_assign
lparameters tuNewValue
This._Value = tuNewValue
This._UpdateMeasures(.T.) && Value passed
ENDPROC
ENDDEFINE
DEFINE CLASS _tooltip AS label && Internal use. Not to be used directly !
*< CLASSDATA: Baseclass="label" Timestamp="" Scale="Pixels" Uniqueid="" />
*<DefinedPropArrayMethod>
*m: caption_assign
*</DefinedPropArrayMethod>
*<PropValue>
Caption = "ToolTip"
Height = 17
Name = "_tooltip"
Width = 40
*</PropValue>
PROCEDURE caption_assign
LPARAMETERS vNewVal
*To do: Modify this routine for the Assign method
THIS.Caption = m.vNewVal
ENDPROC
ENDDEFINE
DEFINE CLASS foxcharts AS container && This is the main FoxCharts class. Just drop it to a form and start charting !
*< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" ProjectClassIcon="chart.ico" ClassIcon="chart.ico" />
*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder
*< OBJECTDATA: ObjPath="Title" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="SubTitle" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="XAxis" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="YAxis" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="ScaleLegend" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="AxisLegend2" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="ShapeLegend" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="SideLegend" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="ChartCanvas" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Fields" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="ToolTip" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="YAxis2" UniqueID="" Timestamp="" />
*<DefinedPropArrayMethod>
*m: afterchart && Event that occurs immediately after the chart is drawn, but still before the image object is updated.
*m: axiscolor_access
*m: backcolor2_access
*m: brushtype_assign
*m: changecolor && Method that returns a darker or brighter version of the original color. Most recommended to obtain some destination gradient values.
*m: chartscount_assign
*m: charttype_assign
*m: color1_access
*m: colortype_assign
*m: currcolumn_access
*m: currlegend_access
*m: currobjtype_access
*m: currrecno_access
*m: currvalue_access
*m: drawchart && Draws and updates the current chart image. DrawChart is the last method to be called after you setup all the chart properties.
*m: drawreport && Returns the FULLPATH() of physical copy of an image from the current chart drawn using the EMF encoder.
*m: fontname_assign
*m: getchartproperties && Returns the chart user defined properties for the current chart
*m: getscalelegend && Returns legends to be used in vertical scale
*m: getscalevalue && Returns values to be used in vertical scale
*m: mousepointer_access
*m: mousepointer_assign
*m: savechartproperties && Saves current list of properties so that incremental property list can be returned by GetChartProperties()
*m: savetofile && Saves the current chart to a file in the image format compatible with Gdi+: Bmp, Png, Jpeg, Gif, Tiff and Emf.
*m: scalebackcolor_access
*m: scalelinecolor_access
*m: selectedshapecolor_access
*m: shapelegendexpression_access
*m: shapemouseenter && Event that occurs when a user moves the mouse over a shape object from the chart.
*m: shapemouseleave && Event that occurs when a user moves the mouse out of a shape object from the chart.
*m: shapemousemove && Event that occurs when a user moves the mouse into a shape object of the chart.
*m: shapetooltip && Event that occurs immediately before the default tooltip of FoxCharts is exibited. Use this event in order to customize the text that is to be shown in the tooltips.
*m: sourcealias_assign
*m: _adjuststartsweep
*m: _beforedraw
*m: _calculatescale
*m: _centerpath
*m: _checkmouseposition
*m: _checkparams
*m: _detachclickedslice
*m: _drawaxis
*m: _drawbar
*m: _drawbarchart
*m: _drawcylinder
*m: _drawdoughnutslice
*m: _drawlegendinbar
*m: _drawlinechart
*m: _drawpiechart
*m: _drawscale
*m: _drawshape
*m: _drawshapelegend
*m: _drawsidelegends
*m: _drawslice
*m: _drawsliceexternal
*m: _drawstackedareachart
*m: _drawtrianglebar
*m: _drawverticallineback
*m: _drawxaxislegend
*m: _drawyaxis
*m: _drawyaxislegend
*m: _getadjustedangle
*m: _getbasiccolor
*m: _getcenterpoint
*m: _getchartprop
*m: _getchartproperties
*m: _getchartscript && Returns a complete script to reproduce the current chart in a separate PRG.
*m: _getcursorpos
*m: _getfieldtype
*m: _getgradientcolor
*m: _getpalettecolor
*m: _getrandomcolor
*m: _getrelativepositions
*m: _getrgb
*m: _getshapepath
*m: _getvalue
*m: _getylegendsize
*m: _initchart
*m: _initpalettes
*m: _newfield
*m: _objtoclientex
*m: _preparebackground
*m: _preparebrushes
*m: _preparecolors
*m: _preparedata
*m: _preparelegend
*m: _preparelegendinslice
*m: _preparesidelegend
*m: _preparetitle
*m: _preparetooltip
*m: _preparevariables
*m: _ps
*m: _setfieldscount
*m: _spellproperty
*m: _str
*m: _updatechartinfo
*m: _updatecoordinates
*m: _updatequality
*p: alphachannel && Numeric, 0-255 Determines the level of the transparency level; 255 = Opaque; 0 = Transparent ***Spinner0,255
*p: area3dtop && Logical, when true, a line will be drawn on the top of the 3D Area chat
*p: areadrawborders && Logical, draws borders around each Area piece
*p: axisalpha && Numeric, Determines the Alpha (transparency) for the Y and X axis and the background lines. Useful when the background contains colors. ***Spinner0,255
*p: axiscolor && Numeric, the RGB value for the Axis main color. ***COLOR
*p: backcolor2 && Numeric or logical, specifies the secondary RGB color for the background of the current chart. .F. means that this property will be ignored, and the background color will be solid, determined by the property "BackColor".
*p: backcoloralpha && Numeric (0-255), the transparency level of the background of the chart. ***Spinner0,255
*p: backgradientmode && Numeric, if gradient background (having BackColor2 specified). *** 0 = Horizontal, 1 = Vertical, 2 = Diagonal 1 , 3 = Diagonal 2
*p: barlegenddirection && Integer (0-2), the direction from the legend that stays inside the bars shapes. ***0 = Horizontal, 1 = Vertical (top to bottom), 2 = Vertical (bottom to top)
*p: barlegendtype && Integer, specifies the how the legend text inside bars shapes will be displayed.*** 0 = Default; 1 = Text is aligned at the center of the shape (old behavior)
*p: barsperscale && Integer, number of horizontal bars per scale legend. ***Spinner0,255
*p: barsspacebetween && Numeric, for bars chart - the distance between bars in pixels. ***Spinner0,500
*p: bartype && Integer (0-2), the bar type ***0 = Rectangular ; 1 = Cylinder ; 2 = Triangle
*p: brushtype && Numeric, Type of brush used to fill the chart: ***1 = Solid Colors; 2 = Gradient Colors; 3 = Monochrome Hatch brush
*p: changecoloronmouse && Logical, determines if a shape color will be changed when the mouse is passed over it.
*p: chartrow && Numeric, only for Pie, Doughnut and SingleBars charts, determines which row will be used to create the chart, for the case when more than one sequence of data is passed.
*p: chartscount && Numeric, the number of data series.
*p: chartsum && Numeric, ReadOnly, For Pie, Doughnut and SingleBars charts, returns the sum for the current column of data when the readonly SingleData property is true.
*p: charttype && Num, type of chart: ***1=Pie;2=Donut;3=Full-Stacked bars;4=Point;5=Line;6=Area;7=Bars;8=MultiBars;9=Stacked Bars; 10=Stacked Area;11=3D Bars;12= Hor Bars;13=Hor MultiBars;14=Hor Stacked Bars;15=Hor Full-Stacked Bars;16=Full-Stacked Area;17=Paired Bars
*p: charttype1
*p: color1 && Numeric, the RGB value of the color from the first chart. For backwards compatibility - use Fields.Color instead
*p: colortype && Numeric, the type of colors: 0 = Basic Colors 1 = Custom (default) 2 = Random 3 = Scale of Gradients
*p: currcolumn && Numeric, ReadOnly, the column number from the Source alias cursor. To be used when controlling mouse events.
*p: currindex && Numeric, ReadOnly, the index number to be used in the aCoord property index to obtain more info about the current shape. If no shape was selected, the value of this property is 0 (zero). To be used when controlling mouse events.
*p: currlegend && Character, ReadOnly, The current associated legend. To be used when controlling mouse events.
*p: currobjtype && Character, ReadOnly, the type of object - "Pie", "Rect" or "Legend". To be used when controlling mouse events.
*p: currrecno && Numeric, ReadOnly, the RECNO(), the row value from the Source alias cursor. To be used when controlling mouse events.
*p: currvalue && ReadOnly, the value of the current shape. To be used when controlling mouse events.
*p: debug && logical, determines the creation of a log file when an error occurs. The file "FOXCHARTS.LOG" will contain general error info, and you can send it to vfpimaging@hotmail.com, with some other detailed information about the error.
*p: depth && Numeric, the depth in pixels, simulating a 3D effect (0 = plain) ***Spinner0,50
*p: donutratio && For Doughnut chart - Numeric, the width of the donut related to its size ( 0.01 = full slice ; 0.99 = thin).
*p: fieldaxis2 && Character, the name of the field that contains the text to be drawn in the axis opposite to the scale.
*p: fieldcolor && Character, the field name of the cursor that contains the RGB values of the custom colors for the chart
*p: fielddetachslice && Character, the field name of the cursor that contains the logical values that tell if the slice of the Pie or Donut chart will be detached or not
*p: fieldhideslice && Character, the field name of the cursor that contains the logical values that tell if the slice of the Pie or Donut chart will be hidden or not
*p: fieldlegend && Character, the field name of the cursor that contains the character values that contain the main legends of the Pie or Donut charts
*p: fieldvalue1 && Character, the field name from the data cursor that contains the numeric values that will create the chart. For backwards compatibility - use Fields(n).FieldValue instead
*p: fieldxaxis && For backwards compatibility - use FieldAxis2 instead
*p: fontname && Character, the name of the font used to display text.
*p: gradientinvertcolors && Logical, determines if the gradient start and destination colors will be inverted.
*p: gradientlevel && Numeric, for gradient brush mode (-10 = destination black; 0 = solid color; +10 destination white). ***Spinner -10,10
*p: gradientposition && Numeric (0-1), specifies where, along any radial from the center of the path to the path's boundary, the center color will be at its highest intensity. A value of 1 places the highest intensity at the center of the path. ***Spinner0,1,0.1
*p: gradientshapedirection && Integer, (0-3) determines the gradient direction for gradient brush charts: *** 0 = Horizontal; 1 = Vertical; 2 = Diagonal1 ; 3 = Diagonal 2
*p: gradienttype && Integer, Gradient type 0 = SigmaBell - The transition from one color to another is based on a bell-shaped curve; 1 = Triangular - gradient with a center color and a linear falloff to each surrounding color. ***0 = SigmaBell; 1 = Triangular
*p: legend1 && The legend for the first column of chart. For backwards compatibility - use Fields.Color instead
*p: legendhidewhennull && Logical, For Pies, Doughnuts and Simple horizontal and vertical bars, will hide the legends associated when the source value s NULL.
*p: legendposition && Num, position where side legend will be drawn*** 0=No Legend;1=Vert TopLeft;2=Vert BotLeft;3=Vert TopRight;4=Vert BotRight;5=Hor TopLeft;6=Hor TopCenter;7=Hor TopRight;8=Hor BotLeft;9=Hor BotCenter;10=Hor BotRight;11=Vert CentLeft;\n12=Vert CentRight\n
*p: linecaps && Logical, for the case of plain line chart, shows rounded caps in each point.
*p: linecapsshape && Integer, the value of the shape to be used in the lines intersections for the line charts
*p: lineignorenulls
*p: margin && Numeric, Specifies the margin width created in the text portion of the control.
*p: marginbottom && Numeric, Specifies the bottom margin left without any drawing in the FoxCharts control.
*p: marginleft && Numeric, Specifies the left margin left without any drawing in the FoxCharts control.
*p: marginright && Numeric, Specifies the right margin left without any drawing in the FoxCharts control.
*p: margintop && Numeric, Specifies the top margin left without any drawing in the FoxCharts control.
*p: maxvalue && If numeric, maximum value plotted along Y-Axis. Otherwise ignored (maximum value will be calculated).
*p: minnumberscalelegends && Numeric, Determines the minimum number of scales legends along the Y-Axis
*p: minvalue && If numeric, minimum value plotted along Y-Axis. Otherwise ignored (minimum value will be calculated).
*p: multichart && Logical, determines if more than one kind of chart will run at the same time
*p: multichartmargin && Logical, Determines if there will be a margin at the beginning and at the end of the chart, when using the Multichart mode. To be used when a Bar chart is not present, in order to obtain a better effect. \n
*p: obmp && Object, ReadOnly, The GDI+ Bitmap object for the Chart Canvas. For GdiPlusX users, allow direct manipulation of the charts canvas.
*p: ogfx && Object, ReadOnly, The GDI+ Graphics object for the Chart Canvas. For GdiPlusX users, allow direct manipulation of the charts canvas.
*p: oldstyleproperties && Logical, determines if the legacy style using enumerated properties will be used. Disrecommended use !
*p: piecompensateangles && Logical, recalculates the needed angles, adjusting for a better visualisation when the pie has an important difference between width and height. Set this to false to force circular shapes.
*p: piedetachanimationsteps && Numeric, the quantity of steps that a slice of a pie or doughnut will take till full detachment
*p: piedetachpixels && Numeric, for Pie and Doughnut charts, the quantity of pixels to detach from center
*p: piedetachsliceonclick && Logical, allows detachment of pie or doughnut slices on mouse click.
*p: piedetachsliceonlegendclick && Logical, allows detachment of pie or doughnut slices on mouse click over the associated side legend
*p: piedirection && Integer (0-1), determines the direction that the slices will be drawn in Pie or Doughnut charts *** 0 = Clockwise, 1 = Anticlockwise
*p: pieenhanceddrawing && Logical, For Pie and Doughnut charts. Enables the enhancing drawing mode, with all edges separately, providing a better effect.
*p: pieforcecircle && logical, for Pie and Doughnut charts, determines if the shape will be a circle with the same width and height.
*p: piegradcenterangle && Numeric, the angle that the desired Center Point for the gradient brush will be applied (0-360). Use together with "PieGradCenterDistance"
*p: piegradcenterdistance && Numeric, the distance from the center that the desired Center Point for the gradient brush will be applied (-2, +2). Use together with "PieGradCenterAngle"
*p: pielegenddistance && Numeric (0.01-2), the distance in percentage starting from the center of the pie or doughnut. 0=Center of the pie; 1=external border of the pie. ***Spinner 0.01,2.00,0.01
*p: pieshowpercent && Logical, shows the percentage of the slice in the tooltip.
*p: pointshapewidth && Numeric, for Point chart, determines the width of the pen that will draw the shapes. ***Spinner1,10,1
*p: qualitycompositing && Specifies the quality level to use during compositing. *** 0 = Default; 1 = HighSpeed; 2 = HighQuality; 3 = GammaCorrected; 4 = AssumeLinear
*p: qualitysmoothing && Specifies whether smoothing (antialiasing) is applied to lines and curves and the edges of filled areas. *** 0 = Default; 1 = HighSpeed Specifies no antialiasing; 2 = HighQuality; 3 = None Specifies no antialiasing; 4 = AntiAlias
*p: qualitytextrenderinghint && Specifies the quality of text rendering. *** 0 = SystemDefault; 1 = SingleBitPerPixelGridFit; 2 = SingleBitPerPixel; 3 = AntiAliasGridFit; 4 = AntiAlias; 5 = ClearTypeGridFit
*p: scale && Numeric, determines the scale value for the Y axys; 0 = Automatic scale
*p: scaleautoformat && Logical, determines if the Scales formatting from "ScaleLegend.Format" will be automatically configured.
*p: scalebackalpha && Numeric (0-255), Determines the level of the transparency level; 255 = Opaque; 0 = Transparent. ***Spinner0,255
*p: scalebackbarstype && Integer (0-3), the background scale type; *** 0 = None; 1 = Horizontal lines; 2 = Vertical lines; 3 = Both
*p: scalebackcolor && Numeric, the RGB value for the bar background scale color. ***Color
*p: scalebacklinesdash && Numeric, The Dash style of the GDI+ pen used to draw the background scale ***0 = Solid line;1 = Line consisting of dashes; 2 = Line consisting of dots; 3 = Line consisting of a repeating pattern of dash-dot; 4 = DashDotDot (a pattern of dash-dot-dot)
*p: scalebacklinestype && Integer (0-3), the background scale type; *** 0 = None; 1 = Horizontal lines; 2 = Vertical lines; 3 = Both
*p: scalebacklineswidth && Numeric, Width in pixels of the GDI+ pen used to draw the background scale
*p: scaledivider && Numeric, the value that the scales must be divided. Useful when the scale values are very big.
*p: scalelinecolor && Numeric, RGB value for the line Background color. ***Color
*p: scalelinezerocolor && Numeric, the RGB value for the color of the line of the zero scale. ***COLOR
*p: selectedshapecolor && Numeric, the RGB values for the selected shape color when property 'ChangeColoronMouse' is true ***COLOR
*p: shadow && Logical, determines if shadows will be drawn under the shapes. The deepness is defined by the "depth" property.
*p: shape1
*p: shapelegendexpression && Character, an expression that replaces the default ShapeLegend text. A valid expression to fully customize the text to be "drawn" in the chart shapes. Use the "Curr" properties to get detailed info about the current shape and build your expression.
*p: shapemousepointer && Numeric, Specifies the shape of the mouse pointer when the mouse is over a shape of the chart at run time
*p: showaxis && Logical, for Line, Area or Point charts - defines if the X and Y axys will be drawn
*p: showaxis2tics && Logical, determines if the legend axis (axis2) will show tic marks on each legend.
*p: showlinezero && Logical, determines if the background line for the zero scale will be shown or not.
*p: showpercentages && Logical, for full-stacked charts, determines if the default ShapeLegend and Tooltip text will show as Percentage\ninstead of values \nValid for the chart types: 3, 7, 8, 12, 13, 15, 16
*p: showscale && Logical, determines if the scale in the Y axys will be shown
*p: showsidelegend && Logical, Shows the side legends
*p: showtips && Logical, specifies if ToolTips are shown for the controls on the specified Form object or the specified ToolBar object.
*p: showvaluesonshape1
*p: showvaluesonshapes && Logical, determines if the values will be drawn inside the shapes of the chart
*p: showvaluezero && Logical, If True, ensures that a value of zero will appear in Y-Axis. If False, calculated range may be entirely above or entirely below zero.
*p: singledata && Logical, ReadOnly, tells if the current chart is based on single data, eg. Pie, Doughnut, Single Bars
*p: sourcealias && Character, The name of the alias that contains the needed fields that will create the chart
*p: ticlength && Integer, the length in pixels of the tic marks used in the scales and in the legend axis. ***Spinner0,30
*p: version && Numeric, the current version number of FoxCharts class.
*p: versiona && Character, the detailed version of FoxCharts class, in alphanumeric format.
*a: acolors[1,0] && ReadOnly, Array that contains information about the current colors for the chart. Useful when working with random colors.
*a: acoord[1,0] && Array that stores information about the object that is under the mouse, like X, Y, Width, Height, Value, Legend, Start, Sweep, CHartIndex, RECNO(), ObjType. See HELP for detailed information about the available info.
*a: apalettecolors[1,0]
*a: _acolors[1,0]
*a: _apoints[1,2]
*a: _ashapes[1,0]
*a: _asidelegends[1,2]
*p: _3d && Numeric, the quantity of pixels that create the 3D effect. For backwards compatibility - use the property "Depth" instead.
*p: _absolutescalevalues
*p: _allowaxis
*p: _anchor
*p: _axis2scalewidth
*p: _bottomoffset
*p: _chartindex
*p: _charty0
*p: _charty1
*p: _currentrow
*p: _datacursor
*p: _deepchart
*p: _drawing
*p: _firstactivate
*p: _generaltype
*p: _hasnegatives
*p: _inlegend
*p: _inreport
*p: _insideform
*p: _leftoffset
*p: _legendexternalmargin
*p: _legendheight && Internal Use
*p: _legendpixheight
*p: _legendwidth && Internal use
*p: _maxscale
*p: _maxscale2
*p: _memberdata && XML Metadata for customizable properties
*p: _minscale
*p: _minscale2
*p: _minvalue
*p: _ncolor && Internal Use
*p: _nindex
*p: _nmouseonshape
*p: _nmouseover
*p: _nrecords && Internal use, the total of records in the main cursor
*p: _o3dbrush && Internal Use, GDI+ Brush object for drawing the 3D effects
*p: _oblackpen
*p: _oborderpen && Internal Use, Gdi+ Pen for drawing borders
*p: _oclrblack
*p: _oclrmatrix && Internal Use, GDI+ ColorMatrix object for drawing the transparent shapes
*p: _oclrwhite
*p: _omainbrush && Internal Use, GDI+ Brush object for drawing the main shapes
*p: _orientation
*p: _origmousepointer
*p: _otempbmp && Internal Use, GDI+ Bitmap object for drawing the transparent shapes
*p: _palettecolors
*p: _pie1stdetached
*p: _pieanimatedrec
*p: _pieanimationpix
*p: _piex0
*p: _piey0
*p: _redraw
*p: _rightoffset
*p: _savedchartproperties
*p: _scale
*p: _scale2
*p: _scaleadjust
*p: _scaleadjust2
*p: _scaleh
*p: _scaleh2
*p: _scaleinpercent
*p: _scalelegaxis1forceformat
*p: _scalelegaxis2forceformat
*p: _scalelegend2forceformat
*p: _scalerange
*p: _scalerange2
*p: _scalew
*p: _scalew2
*p: _skippreparedata
*p: _spellinglist
*p: _stacked
*p: _started
*p: _sumrow
*p: _tippixels
*p: _titleheight && Internal use
*p: _topoffset
*p: _updaterandomcolors
*p: _useaxis
*p: _using3d
*p: _valuedecimals
*p: _valueformat
*p: _valuetype
*p: _xaxisheight
*p: _xrelative
*p: _yaxiswidth
*p: _yaxiswidth2
*p: _yrelative
*</DefinedPropArrayMethod>
*<PropValue>
alphachannel = 255
Anchor = 0
area3dtop = .T.
areadrawborders = .T.
axisalpha = 200
axiscolor = 15790320
backcolor2 = .F.
backcoloralpha = 255
backgradientmode = 0
barlegenddirection = 0
barlegendtype = 0
barsperscale = 2
barsspacebetween = 15
bartype = 0
brushtype = 1
changecoloronmouse = .F.
chartrow = 1
chartscount = 1
chartsum = 0
charttype = 1
charttype1 = 0
color1 = 0
colortype = 1
currcolumn = 0
currindex = 0
currlegend =
currobjtype =
currrecno = 0
currvalue = 0
depth = 20
donutratio = 0.50
fieldaxis2 =
fieldcolor =
fielddetachslice =
fieldhideslice =
fieldlegend =
fieldvalue1 =
fieldxaxis =
fontname =
gradientinvertcolors = .F.
gradientlevel = 5
gradientposition = 0.6
gradientshapedirection = 0
gradienttype = 0
Height = 264
legend1 =
legendhidewhennull = .T.
legendposition = 3
linecaps = .T.
lineignorenulls = .F.
margin = 4
marginbottom = 0
marginleft = 0
marginright = 0
margintop = 0
maxvalue = .F.
minnumberscalelegends = 5
minvalue = .F.
MouseIcon = ..\..\..\gradobjects\gradobjects_foxite\gradobjects\
multichart = .F.
multichartmargin = .T.
Name = "foxcharts"
obmp = NULL
ogfx = NULL
oldstyleproperties = .F.
piecompensateangles = .T.
piedetachanimationsteps = 3
piedetachpixels = 30
piedetachsliceonclick = .T.
piedetachsliceonlegendclick = .F.
piedirection = 0
pieenhanceddrawing = .T.
pieforcecircle = .F.
piegradcenterangle = 0
piegradcenterdistance = 0
pielegenddistance = 0.75
pieshowpercent = .T.
pointshapewidth = 2
qualitycompositing = 2
qualitysmoothing = 4
qualitytextrenderinghint = 4
scale = 0
scaleautoformat = .T.
scalebackalpha = 128
scalebackbarstype = 1
scalebackcolor = 16118000
scalebacklinesdash = 0
scalebacklinestype = 1
scalebacklineswidth = 1
scaledivider = 1
scalelinecolor = 0
scalelinezerocolor = 255
selectedshapecolor = 8421504
shadow = .F.
shape1 = 0
shapelegendexpression =
shapemousepointer = 15
showaxis = .T.
showaxis2tics = .T.
showlinezero = .T.
showpercentages = .F.
showscale = .T.
showsidelegend = .T.
showtips = .T.
showvaluesonshape1 = .T.
showvaluesonshapes = .F.
showvaluezero = .T.
singledata = .F.
sourcealias =
StatusBarText = ""
ticlength = 5
version = 1.37
versiona = FoxCharts v1.37b ALPHA
Width = 360
_3d = .F.
_absolutescalevalues = .F.
_allowaxis =
_anchor = 0
_axis2scalewidth = 0
_bottomoffset = 0
_chartindex = 0
_charty0 = 0
_charty1 = 0
_currentrow = 0
_datacursor =
_deepchart = .F.
_firstactivate = .F.
_generaltype =
_hasnegatives = .F.
_inlegend = .F.
_inreport = .F.
_insideform = .T.
_leftoffset =
_legendexternalmargin = 19
_legendheight = 0
_legendpixheight = 0
_legendwidth = 0
_maxscale = 0
_maxscale2 = 0
_memberdata = <VFPData>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
<memberdata name="version" display="Version"/>
<memberdata name="getchartproperties" display="GetChartProperties"/>
<memberdata name="getscalelegend" display="GetScaleLegend"/>
<memberdata name="getscalevalue" display="GetScaleValue"/>
<memberdata name="savechartproperties" <VFPData><memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseenter" display="ShapeMouseEnter"/>
<memberdata name="shapemouseleave" display="ShapeMouseLeave"/>
<memberdata name="shapemousemove" display="ShapeMouseMove"/>
<memberdata name="versiona" display="VersionA"/>
</VFPData>
_minscale = 0
_minscale2 = 0
_minvalue = 0
_ncolor = 0
_nindex = 0
_nmouseonshape = 0
_nmouseover = 0
_nrecords = 0
_o3dbrush =
_oborderpen =
_oclrblack =
_oclrmatrix =
_oclrwhite =
_omainbrush =
_orientation = 1
_origmousepointer = 0
_otempbmp =
_palettecolors = 184
_pie1stdetached = .F.
_pieanimatedrec = 0
_pieanimationpix = 0
_piex0 = 0
_piey0 = 0
_rightoffset =
_savedchartproperties = .NULL.
_scale = 0
_scale2 = 0
_scaleadjust =
_scaleadjust2 = 0
_scaleh = .F.
_scaleh2 = 0
_scaleinpercent = .F.
_scalelegaxis1forceformat =
_scalelegaxis2forceformat =
_scalelegend2forceformat =
_scalerange =
_scalerange2 = 0
_scalew = .F.
_scalew2 = 0
_skippreparedata = .F.
_spellinglist =
_started = .F.
_sumrow = 0
_tippixels = 16
_titleheight = 0
_topoffset = 0
_updaterandomcolors = .T.
_useaxis = .T.
_using3d = .F.
_valuedecimals = 0
_valueformat =
_valuetype =
_xaxisheight = 0
_xrelative = 0
_yaxiswidth = 0
_yaxiswidth2 = 0
_yrelative = 0
*</PropValue>
ADD OBJECT 'AxisLegend2' AS _legend WITH ;
Alignment = 2, ;
Caption = "AxisLegend2", ;
FontBold = .F., ;
FontSize = 9, ;
FontUnderline = .F., ;
Left = 108, ;
Name = "AxisLegend2", ;
Top = 130, ;
Visible = .F.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'ChartCanvas' AS _chartcanvas WITH ;
drawwheninvisible = .T., ;
Height = 60, ;
Left = 0, ;
Name = "ChartCanvas", ;
Top = 0, ;
Width = 72, ;
_usesmooth = .T.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="image" />
ADD OBJECT 'Fields' AS collection WITH ;
Left = 0, ;
Name = "Fields", ;
Top = 0
*< END OBJECT: BaseClass="collection" />
ADD OBJECT 'ScaleLegend' AS _legend WITH ;
Alignment = 2, ;
Caption = "ScaleLegend", ;
FontBold = .F., ;
FontSize = 7, ;
FontUnderline = .F., ;
Left = 108, ;
Name = "ScaleLegend", ;
Top = 60, ;
Visible = .F.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'ShapeLegend' AS _legend WITH ;
Alignment = 2, ;
Caption = "ShapeLegend", ;
FontSize = 9, ;
Left = 108, ;
Name = "ShapeLegend", ;
Top = 80, ;
Visible = .F.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'SideLegend' AS _legend WITH ;
Alignment = 0, ;
Caption = "SideLegend", ;
FontBold = .F., ;
FontSize = 9, ;
FontUnderline = .F., ;
Left = 216, ;
Name = "SideLegend", ;
Top = 46, ;
Visible = .F.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'SubTitle' AS _legend WITH ;
Alignment = 2, ;
Caption = "SubTitle", ;
FontBold = .T., ;
FontSize = 11, ;
Left = 108, ;
Name = "SubTitle", ;
Top = 36, ;
Visible = .F.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'Title' AS _legend WITH ;
Alignment = 2, ;
Caption = "Title", ;
FontBold = .T., ;
FontSize = 16, ;
ForeColor = 0,128,255, ;
Left = 108, ;
Name = "Title", ;
Top = 8, ;
Visible = .F.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'ToolTip' AS _tooltip WITH ;
Alignment = 2, ;
AutoSize = .T., ;
BackColor = 255,255,164, ;
BackStyle = 1, ;
BorderStyle = 1, ;
Left = 216, ;
Name = "ToolTip", ;
Top = 12, ;
Visible = .F., ;
WordWrap = .T.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'XAxis' AS _legend WITH ;
Alignment = 2, ;
Caption = "XAxis", ;
FontBold = .T., ;
FontSize = 10, ;
FontUnderline = .F., ;
Left = 108, ;
Name = "XAxis", ;
Top = 105, ;
Visible = .F.
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'YAxis' AS _legend WITH ;
Alignment = 2, ;
Caption = "YAxis", ;
FontBold = .T., ;
FontSize = 10, ;
FontUnderline = .F., ;
Height = 144, ;
Left = 24, ;
Name = "YAxis", ;
Rotation = 270, ;
Top = 57, ;
Visible = .F., ;
Width = 24
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
ADD OBJECT 'YAxis2' AS _legend WITH ;
Alignment = 2, ;
Caption = "YAxis2", ;
FontBold = .T., ;
FontSize = 10, ;
FontUnderline = .F., ;
Height = 144, ;
Left = 312, ;
Name = "YAxis2", ;
Rotation = 270, ;
Top = 57, ;
Visible = .F., ;
Width = 24
*< END OBJECT: ClassLib="foxcharts.vcx" BaseClass="label" />
PROCEDURE afterchart && Event that occurs immediately after the chart is drawn, but still before the image object is updated.
ENDPROC
PROCEDURE axiscolor_access
RETURN This._GetRGB(This.AxisColor)
ENDPROC
PROCEDURE backcolor2_access
LOCAL luBackColor2
m.luBackColor2 = This.BackColor2
IF VARTYPE(m.luBackColor2) = "L"
RETURN This.BackColor2
ELSE
RETURN This._GetRGB(This.BackColor2)
ENDIF
ENDPROC
PROCEDURE brushtype_assign
LPARAMETERS tnBrushType
This.BrushType = m.tnBrushType
This._UpdateRandomColors = .T.
ENDPROC
PROCEDURE changecolor && Method that returns a darker or brighter version of the original color. Most recommended to obtain some destination gradient values.
LPARAMETERS tnRGB, tnLevel
IF VARTYPE(m.tnRGB) + VARTYPE(m.tnLevel) <> "NN"
RETURN 0
ENDIF
IF m.tnLevel = 0
RETURN m.tnRGB
ENDIF
m.tnLevel = m.tnLevel / 100
LOCAL lnRed, lnGreen, lnBlue
m.lnRed = BITAND(m.tnRGB, 0x000000FF)
m.lnGreen = BITRSHIFT(BITAND(m.tnRGB, 0x0000FF00), 8)
m.lnBlue = BITRSHIFT(BITAND(m.tnRGB, 0x00FF0000), 16)
IF m.tnLevel > 0
RETURN RGB( ;
m.lnRed + ((255 - m.lnRed) * m.tnLevel) , ;
m.lnGreen + ((255 - m.lnGreen) * m.tnLevel) , ;
m.lnBlue + ((255 - m.lnBlue) * m.tnLevel) )
ELSE
RETURN RGB( ;
m.lnRed + (m.lnRed * m.tnLevel) , ;
m.lnGreen + (m.lnGreen * m.tnLevel) , ;
m.lnBlue + (m.lnBlue * m.tnLevel) )
ENDIF
ENDPROC
PROCEDURE chartscount_assign
LPARAMETERS tnCount
This.ChartsCount = m.tnCount
* Prepare the Enumerated properties
IF This.OldStyleProperties
LOCAL n, lcIndex
FOR m.n = 1 TO m.tnCount
m.lcIndex = This._Str(m.n)
IF m.n > 1 && The enum properties #1 already exists - no need to recreate
This.AddProperty("ChartType" + m.lcIndex, 0)
This.AddProperty("FieldValue" + m.lcIndex, "")
This.AddProperty("Legend" + m.lcIndex, "")
This.AddProperty("Color" + m.lcIndex, "")
This.AddProperty("Shape" + m.lcIndex, 0)
This.AddProperty("ShowValuesOnShape" + m.lcIndex, .T.)
This.AddProperty("AxisIndex" + m.lcIndex, 1)
ENDIF
ENDFOR
ENDIF
* Prepare the Fields collection
This._SetFieldsCount(m.tnCount)
ENDPROC
PROCEDURE charttype_assign
LPARAMETERS tnChartType
This.ChartType = tnChartType
This._UpdateRandomColors = .T.
This._SkipPrepareData = .F.
ENDPROC
PROCEDURE color1_access
RETURN This._GetRGB(This.Color1)
ENDPROC
PROCEDURE colortype_assign
LPARAMETERS tnColorType
This.ColorType = m.tnColorType
IF m.tnColorType = 2 && Random
This._UpdateRandomColors = .T.
ENDIF
ENDPROC
PROCEDURE currcolumn_access
LOCAL lnIndex, lnColumn
m.lnIndex = This.CurrIndex
m.lnColumn = IIF(m.lnIndex = 0, 0, This.aCoord(m.lnIndex, 9))
RETURN m.lnColumn
ENDPROC
PROCEDURE currlegend_access
LOCAL lnIndex, lcLegend
m.lnIndex = This.CurrIndex
m.lcLegend = IIF(m.lnIndex = 0, "", This.aCoord(m.lnIndex, 6))
RETURN m.lcLegend
ENDPROC
PROCEDURE currobjtype_access
LOCAL lnIndex, lcObjType
m.lnIndex = This.CurrIndex
m.lcObjType = IIF(m.lnIndex = 0, "", This.aCoord(m.lnIndex, 11))
RETURN m.lcObjType
ENDPROC
PROCEDURE currrecno_access
LOCAL lnIndex, lnRec
m.lnIndex = This.CurrIndex
m.lnRec = IIF(m.lnIndex = 0, 0, This.aCoord(m.lnIndex, 10))
RETURN m.lnRec
ENDPROC
PROCEDURE currvalue_access
LOCAL lnIndex, lnValue
m.lnIndex = This.CurrIndex
m.lnValue = IIF(EMPTY(m.lnIndex), 0, This.aCoord(m.lnIndex, 5))
RETURN m.lnValue
ENDPROC
PROCEDURE drawchart && Draws and updates the current chart image. DrawChart is the last method to be called after you setup all the chart properties.
* Some setups before drawing for the case of transparent background
* When some Image Canvas settings are needed
IF This.BackColorAlpha < 255 && Transparency active
This.ChartCanvas.Clear(_Screen.System.Drawing.Color.Transparent)
This.ChartCanvas.RenderMode = 4 && Memory PNG
This.BackStyle = 0 && Transparent
ENDIF
IF NOT This._Started
This._InitChart()
ENDIF
This.ChartCanvas.Draw()
ENDPROC
PROCEDURE drawreport && Returns the FULLPATH() of physical copy of an image from the current chart drawn using the EMF encoder.
LPARAMETERS tnWidth, tnHeight
This._SkipPrepareData = .T.
This._InReport = .T.
LOCAL ARRAY laBackup(1)
ACOPY(This.aCoord, laBackup)
LOCAL lcFile, lcAlias
m.lcAlias = ALIAS()
m.lcFile = This.ChartCanvas.DrawReport(m.tnWidth, m.tnHeight)
ACOPY(laBackup, This.aCoord)
This._InReport = .F.
SELECT(m.lcAlias)
RETURN m.lcFile
ENDPROC
PROCEDURE fontname_assign
LPARAMETERS tcFontName
This.FontName = m.tcFontName
* Set all the legend types available
This.SetAll("FontName", m.tcFontName, "_Legend")
* Set the Tooltip fontname as well
IF This._InsideForm
This.ToolTip.FontName = m.tcFontName
ENDIF
ENDPROC
PROCEDURE getchartproperties && Returns the chart user defined properties for the current chart
**********************************************************************************************
* Method: GetChartProperties
* Author: Jim R. Nelson
* Returns the properties and values used to create the current chart
* 2009-12-11 CChalom: added parameter #4, for getting the full script
**********************************************************************************************
Lparameters tnType, tbWrapper, tlShowDescriptions
* tnType = 1 for all properties
* = 2 for non-default properties
* = 3 for properties since last call to .SaveChartProperties
* = 4 for returning a full script for recreating the chart
* tbWrapper = .T. to include code around it ... WITH / ENDWITH
Local lcResult, lcObjects, lcCollection, loPropertiesList, lcMember, lnType, laMembers(1), laObjMembers(1), lcObjMem, lcItem, lnI, lcTempResult, lnJ
Local lcTabs, lnRow, lcDescription, loMember
Local lcCRLF, lnTabSpaces, lcProperty
m.lcCRLF = Chr(13) + Chr(10)
m.lnTabSpaces = 4
m.lcTabs = Space(m.lnTabSpaces)
Do Case
Case Empty (m.tnType)
m.lnType = 1
Case m.tnType = 3 And Isnull(This._savedchartproperties)
* for tnType =2, you must have first invoked method SaveChartProperties ...
* the result is then all properties modified after the call to SaveChartProperties
m.lnType = 2
CASE m.tnType = 4
RETURN This._GetChartScript()
Otherwise
m.lnType = m.tnType
Endcase
m.lcResult = ""
m.lcObjects = ""
m.lcCollection = ""
m.loPropertiesList = This._GetChartProperties()
Amembers(laMembers, m.loPropertiesList, 3)
*!* 2009-12-17
*!* CChalom: Changed order of appearance of the properties
For m.lnI = 1 To Alen (m.laMembers, 1)
m.lcMember = This._spellproperty (m.laMembers(m.lnI,1))
m.lcDescription = ''
m.lnRow = Ascan (m.loPropertiesList._Descriptions, m.lcMember, -1, -1, 1, 9)
If m.lnRow > 0
m.lcDescription = m.loPropertiesList._Descriptions(m.lnRow, 4)
Endif
Do Case
Case Lower(m.lcMember) = '_descriptions'
Case "O" # Type ("loPropertiesList." + m.lcMember) && simple properties
m.lcResult = m.lcResult + This._GetChartProp(m.loPropertiesList, m.lcMember, m.lnType, This._savedchartproperties, m.lcDescription, m.tlShowDescriptions)
Case "C" = Type ("loPropertiesList." + m.lcMember, 1) && collection container
For m.lnJ = 1 To Evaluate ("loPropertiesList." + m.lcMember + ".Count")
m.lcItem = m.lcMember + ".Item(" + Transform(m.lnJ) + ")"
m.loMember = Evaluate ("loPropertiesList." + m.lcItem)
Amembers (laObjMembers, m.loMember)
m.lcTempResult = ''
For Each m.lcObjMem In m.laObjMembers
m.lcObjMem = This._spellproperty (m.lcObjMem)
m.lcDescription = ''
If m.tlShowDescriptions And Pemstatus(m.loMember, "_Descriptions", 5)
m.lnRow = Ascan (m.loMember._Descriptions, m.lcObjMem, -1, -1, 1, 9)
If m.lnRow > 0
m.lcDescription = m.loMember._Descriptions(m.lnRow, 4)
Endif
Endif
m.lcProperty = This._GetChartProp(;
m.loPropertiesList, m.lcItem + "." + m.lcObjMem, m.lnType, This._savedchartproperties, m.lcDescription, m.tlShowDescriptions)
m.lcTempResult = m.lcTempResult + m.lcProperty
Endfor
If Not Empty (m.lcTempResult)
m.lcCollection = m.lcCollection + ;
"WITH ." + m.lcMember + "(" + Transform(m.lnJ) + ")" + m.lcCRLF + ;
Strtran(m.lcTempResult, "." + m.lcItem, m.lcTabs)+ "ENDWITH" + m.lcCRLF
Endif
Endfor
Otherwise && Legend objects
m.loMember = Evaluate ("loPropertiesList." + m.lcMember)
Amembers (laObjMembers, m.loMember)
m.lcTempResult = ''
For Each m.lcObjMem In m.laObjMembers
m.lcObjMem = This._spellproperty (m.lcObjMem)
m.lcDescription = ''
If m.tlShowDescriptions And Pemstatus(m.loMember, "_Descriptions", 5)
m.lnRow = Ascan (m.loMember._Descriptions, m.lcObjMem, -1, -1, 1, 9)
If m.lnRow > 0
m.lcDescription = m.loMember._Descriptions(m.lnRow, 4)
Endif
Endif
m.lcTempResult = m.lcTempResult + This._GetChartProp (;
m.loPropertiesList, m.lcMember + "." + m.lcObjMem, m.lnType, This._savedchartproperties, m.lcDescription, m.tlShowDescriptions)
Endfor
If Not Empty (m.lcTempResult)
m.lcObjects = m.lcObjects + "WITH ." + m.lcMember + m.lcCRLF + ;
Strtran(m.lcTempResult, "." + m.lcMember, m.lcTabs) + ;
"ENDWITH" + m.lcCRLF
Endif
Endcase
Endfor
* Merge all types
m.lcResult = m.lcResult + m.lcObjects + m.lcCollection
*!* 2009-02-21
*!* CChalom: Fixed insertion of With/Endwith
If m.tbWrapper
Local lcCommand, laLines(1), N
m.lcCommand = ""
For m.N = 1 To Alines(laLines, m.lcResult)
m.lcCommand = m.lcCommand + Space(3) + m.laLines(m.N) + m.lcCRLF
Endfor
TEXT TO m.lcResult NOSHOW TEXTMERGE
LOCAL loChart as FoxCharts OF "FoxCharts.vcx"
m.loChart = CREATEOBJECT("FoxCharts")
WITH loChart
<<m.lcCommand>>
<<m.lcTabs>>loChart.DrawChart()
ENDWITH
ENDTEXT
Endif
Return m.lcResult
ENDPROC
PROCEDURE getscalelegend && Returns legends to be used in vertical scale
Lparameters tnScaleNumber, tnValue
****************************************************************
* Jim Nelson 10/10/08
* Returns the Value for the N-th scale legend on the vertical axis.
* tnScaleNumber = 0 corresponds to the highest scale legend
*
* for tnScaleNumber = -1, returns the value to be used in determining the width of the scale legends.
*
* Return value may be numeric (usual) or character (e.g., substituting "zero" for 0)
Do Case
* -1 means the default (maximum) used to determine width
Case (m.tnScaleNumber <> -1) AND (0 # m.tnScaleNumber % This.BarsPerScale)
Return []
Case m.tnScaleNumber = -1
RETURN This._MaxScale
*!* Case m.tnScaleNumber = -1 And Not Empty (This.ScaleLegend._ForceFormat)
*!* Return This.ScaleLegend._ForceFormat
*!* Case m.tnScaleNumber = -1 And Empty (This.ScaleLegend._ForceFormat)
*!* RETURN This._MaxScale
Otherwise
Return m.tnValue
Endcase
ENDPROC
PROCEDURE getscalevalue && Returns values to be used in vertical scale
Lparameters tnScaleNumber, tnIndex
m.tnIndex = EVL(m.tnIndex, 1)
****************************************************************
* Jim Nelson 10/10/08
* Returns the Value for the N-th scale on the vertical axis.
* tnScaleNumber = 0 corresponds to the highest scale
*
* Returns .F. for values of lnScaleNumber that are beyond the lowest scale.
* This code assumes that the increment between successive scale values is constant.
* There is not need for that to be true.
* For instance, it could return the values in the first column here, where the second column is the grade
* (and Method GetScaleLegend could return the character grades)
*
* 100 A+
* 90 A
* 80 B
* 65 C
* 50 D
* 0 F
Local lnResult
IF m.tnIndex = 1
m.lnResult = This._MaxScale - m.tnScaleNumber * This._Scale
If m.lnResult >= This._MinScale - This._Scale / 100
Return m.lnResult
Else
Return .F.
ENDIF
ELSE
m.lnResult = This._MaxScale2 - m.tnScaleNumber * This._Scale2
If m.lnResult >= This._MinScale2 - This._Scale2 / 100
Return m.lnResult
Else
Return .F.
ENDIF
ENDIF
ENDPROC
PROCEDURE Init
This._InitChart()
ENDPROC
PROCEDURE MouseMove
LPARAMETERS nButton, nShift, nXCoord, nYCoord, tnValue, tcLegend, tnCoordIndex, tcObjType
ENDPROC
PROCEDURE mousepointer_access
RETURN This.ChartCanvas.MousePointer
ENDPROC
PROCEDURE mousepointer_assign
LPARAMETERS nMousePointer
This.ChartCanvas.MousePointer = m.nMousePointer
This.MousePointer = m.nMousePointer
ENDPROC
PROCEDURE MouseUp
LPARAMETERS nButton, nShift, nXCoord, nYCoord, tnValue, tcLegend, tnCoordIndex, tcObjType
ENDPROC
PROCEDURE Moved
This._GetRelativePositions()
ENDPROC
PROCEDURE Resize
IF This._InsideForm
IF Thisform.Visible = .F. OR This.Visible = .F.
This.ChartCanvas.lRedrawNow = .F.
This.ChartCanvas.Width = This.Width
This.ChartCanvas.Height = This.Height
RETURN
ENDIF
ENDIF
IF This._FirstActivate && AND Thisform.Visible
This._FirstActivate = .F.
RETURN
ENDIF
This._UpdateRandomColors = .F.
This.ChartCanvas.lRedrawNow = .F.
This.ChartCanvas.Width = This.Width
This.ChartCanvas.Height = This.Height
This._SkipPrepareData = .T.
IF This._Started
This.ChartCanvas.lRedrawNow = .T.
ENDIF
RETURN
ENDPROC
PROCEDURE savechartproperties && Saves current list of properties so that incremental property list can be returned by GetChartProperties()
****************************************************************
* Jim Nelson 10/20/2008
* modified 06/30/2009
* Save current settings of Chart Properties so that later comparisons
* can determine which properties have changed
Lparameters tlSkipIfAlreadySaved
If tlSkipIfAlreadySaved And "O" = Vartype(This._SavedChartProperties)
Return
Endif
This._SavedChartProperties = This._GetChartProperties()
ENDPROC
PROCEDURE savetofile && Saves the current chart to a file in the image format compatible with Gdi+: Bmp, Png, Jpeg, Gif, Tiff and Emf.
LPARAMETERS tcFile, tnQuality
IF EMPTY(m.tcFile) && Invalid File Name
RETURN .F.
ENDIF
LOCAL lcImgFormatTypes, lcFile, lcExt
LOCAL loImgFormat as xfcImageFormat
LOCAL loQualityEncoder AS xfcEncoderParameter
LOCAL loEncoderParameters AS xfcEncoderParameters
m.loEncoderParameters = .F.
m.lcExt = LOWER(JUSTEXT(m.tcFile))
IF EMPTY(m.lcExt)
m.lcExt = "png"
ENDIF
DO CASE
CASE m.lcExt = "bmp" OR m.lcExt = "bitmap"
m.loImgFormat = _Screen.System.Drawing.Imaging.ImageFormat.Bmp
CASE m.lcExt = "jpg" OR m.lcExt = "jpeg"
m.loImgFormat = _Screen.System.Drawing.Imaging.ImageFormat.Jpeg
IF VARTYPE(m.tnQuality) = "N" && set the quality encoder if the parameter was passed
&& otherwise, the default 75% for Gdi+ will be used.
&& Create an EncoderParameters object.
&& An EncoderParameters object has an array of EncoderParameter
&& objects. In this case, there is only one
&& EncoderParameter object in the array.
m.loEncoderParameters = _Screen.System.Drawing.Imaging.EncoderParameters.New(1)
&& Save the bitmap as a JPEG file with quality level.
m.loQualityEncoder = _Screen.System.Drawing.Imaging.EncoderParameter.New(_Screen.System.Drawing.Imaging.Encoder.Quality, m.tnQuality)
m.loEncoderParameters.Param.Add(m.loQualityEncoder)
ENDIF
CASE m.lcExt = "gif"
m.loImgFormat = _Screen.System.Drawing.Imaging.ImageFormat.Gif
CASE m.lcExt = "png"
m.loImgFormat = _Screen.System.Drawing.Imaging.ImageFormat.Png
CASE m.lcExt = "tif" OR m.lcExt = "tiff"
m.loImgFormat = _Screen.System.Drawing.Imaging.ImageFormat.Tiff
CASE m.lcExt = "emf"
LOCAL lcTempFile
m.lcTempFile = This.DrawReport()
IF FILE(m.lcTempFile)
COPY FILE (m.lcTempFile) TO (m.tcFile)
ENDIF
RETURN
OTHERWISE
RETURN .F.
ENDCASE
TRY
This.oBmp.Save(m.tcFile, m.loImgFormat, m.loEncoderParameters)
CATCH
ENDTRY
ENDPROC
PROCEDURE scalebackcolor_access
RETURN This._GetRGB(This.ScaleBackColor)
ENDPROC
PROCEDURE scalelinecolor_access
RETURN This._GetRGB(This.ScaleLineColor)
ENDPROC
PROCEDURE selectedshapecolor_access
RETURN This._GetRGB(This.SelectedShapeColor)
ENDPROC
PROCEDURE shapelegendexpression_access
RETURN This.ShapeLegendExpression
ENDPROC
PROCEDURE shapemouseenter && Event that occurs when a user moves the mouse over a shape object from the chart.
LPARAMETERS nButton, nShift, nXCoord, nYCoord, tnValue, tcLegend, tnCoordIndex
ENDPROC
PROCEDURE shapemouseleave && Event that occurs when a user moves the mouse out of a shape object from the chart.
LPARAMETERS nButton, nShift, nXCoord, nYCoord, tnValue, tcLegend, tnCoordIndex
ENDPROC
PROCEDURE shapemousemove && Event that occurs when a user moves the mouse into a shape object of the chart.
LPARAMETERS nButton, nShift, nXCoord, nYCoord, tnValue, tcLegend, tnCoordIndex
ENDPROC
PROCEDURE shapetooltip && Event that occurs immediately before the default tooltip of FoxCharts is exibited. Use this event in order to customize the text that is to be shown in the tooltips.
LPARAMETERS nButton, nShift, nXCoord, nYCoord, tnValue, tcLegend, tnCoordIndex, tcObjType
WITH This
LOCAL lcCaption, lcFormat, lnDecimals, lcDecHelp, i
IF m.tcObjType = "Legend"
m.lcCaption = ""
ELSE
* 2013-02-24 CChalom - Update to calculate the decimals for the current object
m.lcDecHelp = TRANSFORM(ABS(INT(tnValue) - tnValue))
m.lcDecHelp = SUBSTR(m.lcDecHelp, 3)
FOR i = 1 TO LEN(m.lcDecHelp)
IF RIGHT(m.lcDecHelp,1) = "0"
m.lcDecHelp = LEFT(m.lcDecHelp, LEN(m.lcDecHelp) - 1)
ELSE
EXIT
ENDIF
ENDFOR
m.lnDecimals = LEN(m.lcDecHelp)
* -
m.lcFormat = .ShapeLegend.Format
IF EMPTY(m.lcFormat) && AND NOT EMPTY(This.ShapeLegendExpression)
* m.lcFormat = "999,999,999,999" + ;
IIF(This._ValueDecimals > 0, "." + REPLICATE("9", This._ValueDecimals), "")
m.lcFormat = "999,999,999,999" + ;
IIF(m.lnDecimals > 0, "." + REPLICATE("9", m.lnDecimals), "")
ENDIF
m.lcCaption = ALLTRIM(ALLTRIM(TRANSFORM(m.tnValue, m.lcFormat)) + ;
IIF(EMPTY(m.tcLegend),"", CHR(13) + m.tcLegend) + ;
IIF(m.tcObjType = "Pie", CHR(13) + TRANSFORM(INT((m.tnValue / .ChartSum)*100)) + "%",""))
ENDIF
.ToolTip.Caption = m.lcCaption
.MousePointer = .ShapeMousePointer
IF NOT EMPTY(m.lcCaption) AND ;
Thisform.FoxChartsToolTip.Width = 0
Thisform.FoxChartsToolTip.Width = 10
ENDIF
ENDWITH
RETURN
ENDPROC
PROCEDURE sourcealias_assign
LPARAMETERS tcNewAlias
This.SourceAlias = m.tcNewAlias
IF NOT EMPTY(This._DataCursor) AND USED(This._DataCursor)
USE IN (This._DataCursor)
ENDIF
This._DataCursor = ""
ENDPROC
PROCEDURE _adjuststartsweep
LPARAMETERS tnStart, tnSweep, tnWidth, tnHeight
LOCAL lnDrawStart, lnDrawSweep, lnDestAngle
IF This.PieCompensateAngles
m.lnDrawStart = This._GetAdjustedAngle(m.tnStart, m.tnWidth, m.tnHeight)
m.lnDestAngle = This._GetAdjustedAngle(m.tnStart + m.tnSweep, m.tnWidth, m.tnHeight)
IF m.lnDestAngle < m.lnDrawStart
m.lnDestAngle = m.lnDestAngle + 360
ENDIF
m.lnDrawSweep = m.lnDestAngle - m.lnDrawStart
m.tnStart = m.lnDrawStart
m.tnSweep = m.lnDrawSweep
ELSE
IF m.tnStart < 0
m.tnStart = m.tnStart + 360
ENDIF
ENDIF
ENDPROC
PROCEDURE _beforedraw
Local loException as Object
TRY
This._Drawing = .T.
* Store the current selected table / cursor
LOCAL lnSelect
m.lnSelect = SELECT()
* Initial Settings
LOCAL loChart as FoxCharts OF FoxCharts.Vcx
m.loChart = This
m.loChart.oGfx = This.ChartCanvas.oGfx
m.loChart.oBmp = This.ChartCanvas.oBmp
* Update quality settings
This._UpdateQuality()
* Check if the FoxCharts object was created
* This is for the case when the user does not create the chart cursor before the form is initialized.
IF EMPTY(This.SourceAlias)
m.loChart._PrepareBackGround()
EXIT
ENDIF
* Check for the minimum dimensions
IF This.ChartCanvas.Width < 30 OR ;
This.ChartCanvas.Height < 30
EXIT
ENDIF
m.loChart._CheckParams()
m.loChart._UpdateChartInfo()
IF NOT m.loChart._SkipPrepareData OR NOT USED(This._DataCursor)
* Check if empty cursor
IF NOT m.loChart._PrepareData()
m.loChart._PrepareBackGround()
m.loChart._PrepareTitle()
EXIT
ENDIF
* Make sure to clear some properties to avoid issues if changing the chart type
* having the Chart active
This._ScaleLegAxis1ForceFormat = ""
This._ScaleLegAxis2ForceFormat = ""
This.ScaleLegend._ForceFormat = ""
m.loChart._PrepareVariables()
m.loChart._PrepareColors()
ELSE
SELECT (This._DataCursor)
GO TOP
ENDIF
* m.loChart._PrepareColors()
m.loChart._PrepareBackGround()
m.loChart._PrepareTitle()
m.loChart._PrepareSideLegend()
m.loChart._PrepareLegend()
m.loChart._DrawAxis()
m.loChart._PrepareTooltip
IF m.loChart.ShowValuesOnShapes
m.loChart.ShapeLegend._Setup()
ENDIF
LOCAL lnChartType
m.lnChartType = m.loChart.ChartType
IF INLIST(m.lnChartType, 6, 9, 14, 11, 10) AND This._HasNegatives
MESSAGEBOX("The selected Chart type does not support negative values" + CHR(13) + "The chart will not be drawn", 48, "Invalid Data")
ELSE
DO CASE
*!* Chart Type Values:
*!* 1 = Pie ; 2 = Donut ;
*!* 3 = Unspecified ;
*!* 4 = Point ; 5 = Line ; 6 = Area ;
*!* 7 = Simple Bar ; 8 = Multiple Bars ; 9 = Stacked Bars ; 11 = 3D Bars
*!* 10 = Stacked Area
*!* 12 = Horizontal Bars ; 13 = Horizontal multiple bars ; 14 = Horizontal Stacked Bars
CASE This._GeneralType = "Pie" && Pie or Donut Chart
m.loChart._DrawPieChart()
CASE This._GeneralType = "Bar" && Bar Chart
m.loChart._DrawBarChart()
CASE INLIST(m.lnChartType, 4, 5, 6, 18) && Line or Area Chart
m.loChart._DrawLineChart()
CASE INLIST(m.lnChartType, 10, 16) && Stacked Area Chart
m.loChart._DrawStackedAreaChart()
ENDCASE
ENDIF
m.loChart._DrawSideLegends()
m.loChart.AfterChart()
m.loChart._FirstActivate = .F.
m.loChart._SkipPrepareData = .F.
m.loChart._yAxisWidth = 0
m.loChart._yAxisWidth2 = 0
* Restore the original selected alias
SELECT (m.lnSelect)
This._GetRelativePositions()
CATCH TO m.loException
IF This.Debug
* Send the error to a file
LOCAL lcVersion, lcError, lcErrFile, lcCRLF, lcLine
m.lcCRLF = CHR(13) + CHR(10)
m.lcLine = m.lcCRLF + REPLICATE("=", 60) + m.lcCRLF
m.lcErrFile = "FoxCharts.log"
m.lcError = "FoxCharts Error" + ;
m.lcLine + ;
TRANSFORM(DATETIME()) + m.lcLine + ;
[Error: ] + STR(m.loException.ERRORNO) + m.lcCRLF + ;
[Line : ] + STR(m.loException.LINENO) + m.lcCRLF + ;
[Message: ] + m.loException.MESSAGE + m.lcCRLF + ;
[Procedure: ] + m.loException.PROCEDURE + m.lcCRLF + ;
[Details: ] + m.loException.DETAILS + m.lcCRLF + ;
[StackLevel: ] + STR(m.loException.STACKLEVEL) + m.lcCRLF + ;
[LineContents: ] + m.loException.LINECONTENTS + m.lcCRLF + ;
[UserValue: ] + m.loException.USERVALUE + m.lcLine + m.lcCRLF
* Code from Christof Wollenhaupt
LOCAL lcDir, lcMemory, lcStatus
m.lcDir = ADDBS(GETENV("TEMP"))
IF FILE(m.lcDir + "mem.txt")
ERASE (m.lcDir + "mem.txt")
ENDIF
LIST MEMORY LIKE * TO (m.lcDir + "mem.txt") NOCONSOLE
IF FILE(m.lcDir + "List_status.txt")
ERASE (m.lcDir + "List_status.txt")
ENDIF
LIST STATUS TO (m.lcDir + "list_status.txt") NOCONSOLE
m.lcMemory = FILETOSTR(m.lcDir + "mem.txt")
m.lcStatus = FILETOSTR(m.lcDir + "List_Status.txt")
ERASE (m.lcDir + "mem.txt")
ERASE (m.lcDir + "List_status.txt")
*------------------------------------------------------
* Assemble the calling hierarchy
*------------------------------------------------------
LOCAL lcHierarchy, lnLevel, lcProcedure, laStack[1]
m.lcHierarchy = "PROCEDURE HIERARCHY" + m.lcLine
FOR m.lnLevel = ASTACKINFO(laStack) - 1 TO 1 STEP - 1
m.lcProcedure = SUBSTR(SYS(16, m.lnLevel), AT(" ", ;
SYS(16, m.lnLevel), 1) + 1)
m.lcHierarchy = m.lcHierarchy + ;
" " + PROPER(ALLTRIM(LEFT(m.lcProcedure, ;
AT(" ", m.lcProcedure)))) + " in " + ;
JUSTSTEM(SUBSTR(SYS(16, m.lnLevel), ;
AT(" ", SYS(16, m.lnLevel), 2) + 1)) + ;
", " + TRANSFORM(m.laStack[m.lnLevel, 5]) + ;
CHR(13) + CHR(10)
ENDFOR
* GdiPlusX version check
LOCAL lnVersion
m.lnVersion = 0
IF pemstatus(_Screen.System, "Version", 5)
m.lnVersion = _Screen.System.Version
ENDIF
m.lcVersion = "Visual FoxPro " + TRANSFORM(VERSION(4)) + m.lcCRLF + ;
"System: " + TRANSFORM(OS(1)) + " - " + TRANSFORM(OS(7)) + m.lcCRLF + ;
"GdiPlusX Version: " + TRANSFORM(m.lnVersion) + m.lcCRLF + ;
"FoxCharts Version: #" + TRANSFORM(This.Version) + " - " + TRANSFORM(This.VersionA) + ;
m.lcLine + m.lcCRLF
* Retrieve Chart properties
LOCAL lcChartProps
TRY
m.lcChartProps = This.GetChartProperties()
m.lcChartProps = STRTRAN(m.lcChartProps, CHR(13), m.lcCRLF)
CATCH
m.lcChartProps = "Not Available"
ENDTRY
m.lcChartProps = "Chart Properties" + m.lcCRLF + m.lcLine + m.lcCRLF + m.lcChartProps
IF FILE(m.lcErrFile)
ERASE (m.lcErrFile)
ENDIF
* Save error file to disk
STRTOFILE(m.lcVersion + m.lcError + m.lcLine + ;
m.lcChartProps + m.lcLine + ;
m.lcHierarchy + m.lcLine + m.lcMemory + m.lcLine + m.lcStatus, m.lcErrFile)
MESSAGEBOX("A Log file containing info about this error and your environment details was created: " + m.lcCRLF + m.lcCRLF + ;
FULLPATH(m.lcErrFile) + m.lcCRLF + m.lcCRLF + ;
"Please send it to: vfpimaging@hotmail.com to help us fixing it." + m.lcCRLF + m.lcCRLF + ;
m.lcError + m.lcCRLF + m.lcCRLF + ;
"Sorry for the inconvenience", 16, "FoxCharts Error")
ELSE
IF _VFP.StartMode = 0
LOCAL lcVersion, lcError, lcErrFile, lcCRLF, lcLine
m.lcCRLF = CHR(13) + CHR(10)
m.lcLine = m.lcCRLF + REPLICATE("=", 30) + m.lcCRLF
m.lcError = "FoxCharts Error" + ;
m.lcLine + ;
TRANSFORM(DATETIME()) + m.lcLine + ;
[Error: ] + STR(m.loException.ERRORNO) + m.lcCRLF + ;
[Line : ] + STR(m.loException.LINENO) + m.lcCRLF + ;
[Message: ] + m.loException.MESSAGE + m.lcCRLF + ;
[Procedure: ] + m.loException.PROCEDURE + m.lcCRLF + ;
[Details: ] + m.loException.DETAILS + m.lcCRLF + ;
[StackLevel: ] + STR(m.loException.STACKLEVEL) + m.lcCRLF + ;
[LineContents: ] + m.loException.LINECONTENTS + m.lcCRLF + ;
[UserValue: ] + m.loException.USERVALUE + m.lcLine + m.lcCRLF
MESSAGEBOX(m.lcError, 16, "FoxCharts error")
THROW m.loException
ENDIF
ENDIF
This._Drawing = .F.
IF This._Redraw = .T.
This._Redraw = .F.
This.DrawChart()
ENDIF
ENDTRY
RETURN
ENDPROC
PROCEDURE _calculatescale
LPARAMETERS tnMaxValue, tnMinValue, tnAxis
m.tnAxis = EVL(m.tnAxis, 1)
* 2009-12-12 CChalom - if working with full-stacked charts, use fixed values
IF This._ScaleInPercent
This._MinScale = 0
This._MaxScale = 100
This._ScaleRange = 100
This._Scale = IIF(This.Scale > 0, MIN(This.Scale, 100), 20)
This._ScaleAdjust = 0
RETURN
ENDIF
* By Jim Nelson
* Determines the maximum and minimum values plotted along the Y-Axis, and the increment between the legends.
* Arguments:
* tnMaxValue = Maximum value in the data being plotted
* tnMinValue = Minimum value in the data being plotted
* Properties referenced:
* .Scale = Increment between legends along the axis. If empty, will be calculated.
* .MaxValue = If numeric, the value of the top legend along the axis. Otherwise calculated.
* .MinValue = If numeric, the value of the bottom legend along the axis. Otherwise calculated.
* .ShowValueZero = If True, insures that a value of zero will appear along the Y-Axis. Otherwise,
* the calculated range may be entirely above or below zero.
* .MinNumberScaleLegends = The minimum number of scale legends to be drawn along the axis.
* (The actual number is dependent on the data; the maximum will be one less
* than twice this number.)
* .BarsPerScale = The number of horizontal background bars (alternating colors) for each
* scale legend.
* Note that the values for Scale, MaxValue, and MinValue are normally left at their default values, so that
* "nice" (that is, visually attractive) values can be determined.
* Not all combinations of these properties make sense: for instance, setting MaxValue and/or MinValue
* can make ShowValueZero irrelevant; setting Scale makes MinNumberScaleLegends irrelevant
Local lnMax, lnMin, lnScale, lnMaxScale, lnMinScale, lnRange, lnLegendHeight, lnDigits, lnScaling
IF m.tnAxis = 1
m.lnMax = Icase( ;
"N" = Vartype (This.MaxValue), This.MaxValue, ;
This.ShowValueZero, Max (0, m.tnMaxValue) , ;
m.tnMaxValue)
m.lnMin = Icase( ;
"N" = Vartype (This.MinValue), This.MinValue, ;
This.ShowValueZero, Min (0, m.tnMinValue), ;
m.tnMinValue)
m.lnScale = This.Scale
ELSE
m.lnMax = m.tnMaxValue
m.lnMin = m.tnMinValue
m.lnScale = 0
ENDIF
* 20081006 - JNelson fixed range calculation
m.lnRange = m.lnMax - m.lnMin
* Calculate the scale, if none supplied
Do Case
Case Not Empty (m.lnScale)
m.lnMaxScale = m.lnScale * Ceiling (m.lnMax / m.lnScale)
m.lnMinScale = m.lnScale * Floor (m.lnMin / m.lnScale)
*** JRN 07/01/09 : Insure legend on both top and bottom of Y-Axis
If This.BarsPerScale > 1
m.lnLegendHeight = m.lnScale * This.BarsPerScale
m.lnMaxScale = m.lnLegendHeight * Ceiling( (m.lnMaxScale - m.lnMinScale) / m.lnLegendHeight)
Endif
If This.ScaleAutoFormat
m.lnDigits = Ceiling (Log10(Max (10, Abs( m.lnMaxScale / This.ScaleDivider ), Abs (m.lnMinScale / This.ScaleDivider))))
This.ScaleLegend._ForceFormat = " " + Right ("999,999,999,999,999", m.lnDigits + Floor((m.lnDigits + 3) / 3)+1)
Else
This.ScaleLegend._ForceFormat = ""
Endif
Case m.lnRange = 0
m.lnScale = 10
m.lnMaxScale = 1
m.lnMinScale = 0
Otherwise
* choose "nice" steps sizes -- 10, 20, 25, or 50 times some power of ten.
Local laSteps(4)
m.laSteps(1) = 1
m.laSteps(2) = 2
m.laSteps(3) = 2.5
m.laSteps(4) = 5
Local lnMult, lnCurrentNSteps, lnStep, lnSteps, lnNiceStep, lnPowerof10, lnExponent
m.lnExponent = Floor ( Log10 (m.lnRange)) - 3 && scale range to be between 1,000 and 9,999
m.lnCurrentNSteps = 9999
For Each m.lnNiceStep In m.laSteps
For m.lnPowerof10 = 0 To 3
m.lnStep = (m.lnNiceStep / Evl (This.BarsPerScale, 1)) * 10 ^ (m.lnExponent + m.lnPowerof10)
m.lnSteps = Ceiling (m.lnMax / m.lnStep) - Floor (m.lnMin / m.lnStep)
*** JRN 07/01/09 : Insure legend on both top and bottom oy Y-Axis
If This.BarsPerScale > 1
m.lnSteps = This.BarsPerScale * Ceiling( m.lnSteps / This.BarsPerScale)
Endif
If Between (m.lnSteps, This.MinNumberScaleLegends, m.lnCurrentNSteps)
m.lnScale = m.lnStep / 1
m.lnMaxScale = m.lnStep * Ceiling (m.lnMax / m.lnStep)
m.lnMinScale = m.lnStep * Floor (m.lnMin / m.lnStep)
m.lnCurrentNSteps = m.lnSteps
m.lnScaling = m.lnExponent + m.lnPowerof10 + Iif (0 = m.lnNiceStep % 1, 1, 0)
*** JRN 07/01/09 : Insure legend on both top and bottom oy Y-Axis
If This.BarsPerScale > 1
m.lnLegendHeight = m.lnScale * This.BarsPerScale
m.lnMaxScale = m.lnLegendHeight * Ceiling( (m.lnMaxScale - m.lnMinScale) / m.lnLegendHeight)
Endif
Endif
Next m.lnPowerof10
Endfor
m.lnDigits = Ceiling (Log10(Max (10, Abs( m.lnMaxScale / This.ScaleDivider ), Abs (m.lnMinScale / This.ScaleDivider))))
If This.ScaleAutoFormat
This.ScaleLegend._ForceFormat = " " + Right ("999,999,999,999,999", m.lnDigits + Floor((m.lnDigits + 3) / 3))
If m.lnScaling < 1
This.ScaleLegend._ForceFormat = This.ScaleLegend._ForceFormat + "." + Replicate ("9", 1 - m.lnScaling)
Endif
Else
This.ScaleLegend._ForceFormat = ""
Endif
Endcase
****************************************************************
* Save
WITH This
IF m.tnAxis = 1
._Scale = m.lnScale
._ScaleRange = m.lnMaxScale && - m.lnMinScale
._ScaleAdjust = - m.lnMinScale
._MinScale = m.lnMinScale
._MaxScale = m.lnMaxScale + m.lnMinScale
IF This.ChartType = 17
._ScaleRange = m.lnMaxScale * 2 && - m.lnMinScale
._MinScale = - ._MaxScale
ENDIF
ELSE
._Scale2 = m.lnScale
._ScaleRange2 = m.lnMaxScale && - m.lnMinScale
._ScaleAdjust2 = - m.lnMinScale
._MinScale2 = m.lnMinScale
._MaxScale2 = m.lnMaxScale + m.lnMinScale
ENDIF
ENDWITH
ENDPROC
PROCEDURE _centerpath
LPARAMETERS toPath as xfcGraphicsPath, tlScale, tnWidth, tnHeight
LOCAL loMatrix as xfcMatrix, ;
loRect as xfcRectangle, ;
lnWidth, lnHeight, x1, y1
m.loRect = m.toPath.GetBounds()
m.lnWidth = m.loRect.Width
m.lnHeight = m.loRect.Height
m.loMatrix = _Screen.System.Drawing.Drawing2D.Matrix.New() && lnWidth /2, lnHeight /2)
IF m.tlScale
m.loMatrix.Scale(1+This.PointShapeWidth /10, 1+This.PointShapeWidth /10)
m.toPath.Transform(m.loMatrix)
m.loRect = m.toPath.GetBounds()
m.lnWidth = m.loRect.Width
m.lnHeight = m.loRect.Height
m.x1 = m.loRect.X
m.y1 = m.loRect.Y
m.loMatrix.Translate(-m.x1 -m.lnWidth/2, -m.y1 -m.lnHeight/2)
ELSE
m.x1 = m.loRect.X
m.y1 = m.loRect.Y
m.loMatrix.Translate(-m.x1 -m.lnWidth /(2 * This.PointShapeWidth), ;
-m.y1 -m.lnHeight /(2 * This.PointShapeWidth))
ENDIF
m.toPath.Transform(m.loMatrix)
RETURN m.toPath
ENDPROC
PROCEDURE _checkmouseposition
LPARAMETERS nButton, nShift, nXCoord, nYCoord, lnValue, lcLegend, lnCoordIndex, lcObjType
* Passed by reference: lnValue, lcLegend
IF VARTYPE(m.lcLegend) = "L"
m.lcLegend = ""
ENDIF
m.lcObjType = ""
IF VARTYPE(This.aCoord(1,1)) <> "N" OR m.nYCoord < 0 OR m.nXCoord <0
This.MouseMove(m.nButton, m.nShift, m.nXCoord, m.nYCoord, 0, "", 0, "")
RETURN
ENDIF
WITH This
LOCAL n, lnValue, lnStart, lnSweep, lnLeft, lnTop
m.lnLeft = This._xRelative &&+ .Left
m.lnTop = This._yRelative &&+ .Top
* 1st step is to check if we are over the side legends
IF This.ShowSideLegend AND ;
BETWEEN(m.nXCoord - m.lnLeft,;
This.SideLegend.Left, ;
This.SideLegend.Left + This.SideLegend.Width) AND ;
BETWEEN(m.nYCoord - m.lnTop, ;
This.SideLegend.Top , ;
This.SideLegend.Top + This.SideLegend.Height)
m.lcObjType = "Legend"
ENDIF
ENDWITH
*!* This.aCoord(n,1) = tnX
*!* This.aCoord(n,2) = tnY
*!* This.aCoord(n,3) = tnWidth
*!* This.aCoord(n,4) = tnHeight
DO CASE
CASE This._GeneralType = "Bar" OR This._GeneralType = "Point" OR m.lcObjType = "Legend"
FOR m.n = ALEN(This.aCoord,1) TO 1 STEP -1 && Reverse in order to catch the first drawing
IF BETWEEN(m.nXCoord - m.lnLeft,;
This.aCoord(m.n,1), ;
This.aCoord(m.n,1) + This.aCoord(m.n,3)) ;
AND ;
BETWEEN(m.nYCoord - m.lnTop, ;
This.aCoord(m.n,2) , ;
This.aCoord(m.n,2) + This.aCoord(m.n,4))
m.lnValue = This.aCoord(m.n, 5)
m.lcLegend = This.aCoord(m.n, 6)
m.lnCoordIndex = m.n
m.lcObjType = This.aCoord(m.n,11)
IF m.lcObjType = "Legend"
This._nMouseOnShape = 0
RETURN
ENDIF
IF This._nMouseOnShape = 0
This._nMouseOnShape = m.n
IF This.ChangeColoronMouse
This._SkipPrepareData = .T.
This.DrawChart()
ENDIF
This.ShapeMouseEnter(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ELSE
IF This._nMouseOnShape <> m.n
This._nMouseOnShape = m.n
IF This.ChangeColoronMouse
This._SkipPrepareData = .T.
This.DrawChart()
ENDIF
This.ShapeMouseEnter(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ELSE && Mouse over the shape
This.ShapeMouseMove(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ENDIF
ENDIF
RETURN
ELSE
ENDIF
NEXT
IF This._nMouseOnShape <> 0
This._nMouseOnShape = 0
This.ShapeMouseLeave(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ENDIF
CASE This._GeneralType = "Pie"
*!* This.aCoord(n,1) = tnX
*!* This.aCoord(n,2) = tnY
*!* This.aCoord(n,3) = tnWidth
*!* This.aCoord(n,4) = tnHeight
*!* This.aCoord(n,5) = tnValue
*!* This.aCoord(n,7) = tnStart
*!* This.aCoord(n,8) = tnSweep
*!* This.aCoord(n,9) = This._ChartIndex
*!* This.aCoord(n,10) = RECNO()
* Adapted code from Luis Maria Guayan - VFP MVP from Argentina
LOCAL lnX1, lnX2, lnX3, lnY1, lnY2, lnY3, lnStart, lnSweep, lnValue, m.lcLegend, lnAngle
* Center of Ellipse
m.lnX1 = This.aCoord(1,3) / 2
m.lnY1 = This.aCoord(1,4) / 2
* Coordinates inside the Shape
IF This._Pie1stDetached
m.lnX2 = (m.nXCoord - m.lnLeft - m.lnX1 - This._PieX0)
m.lnY2 = ((m.nYCoord - m.lnTop - m.lnY1 - This._PieY0) * (-1))
ELSE
m.lnX2 = (m.nXCoord - m.lnLeft - m.lnX1 - This.aCoord(1,1))
m.lnY2 = ((m.nYCoord - m.lnTop - m.lnY1 - This.aCoord(1,2)) * (-1))
ENDIF
* Angle in degrees [0<>..360<EFBFBD>]
m.lnAngle = RTOD(ATAN(m.lnY2/m.lnX2))
DO CASE
CASE m.lnX2 < 0
m.lnAngle = 180 + m.lnAngle
CASE m.lnY2 < 0
m.lnAngle = 360 + m.lnAngle
OTHERWISE
ENDCASE
m.lnAngle = 360 - m.lnAngle
LOCAL lnFoundShape, n
m.lnFoundShape = 0
* Now we need to find the shape
FOR m.n = 1 TO ALEN(This.aCoord,1)
m.lnStart = EVL(This.aCoord(m.n,7), 0)
IF VARTYPE(m.lnStart) <> "N"
EXIT
ENDIF
m.lnSweep = EVL(This.aCoord(m.n,8), 0)
IF BETWEEN(m.lnAngle, m.lnStart, m.lnStart + m.lnSweep) OR ;
BETWEEN(m.lnAngle + 360, m.lnStart, m.lnStart + m.lnSweep)
m.lnFoundShape = m.n
EXIT
ENDIF
ENDFOR
IF m.lnFoundShape = 0
RETURN
ENDIF
* Now we can know exactly the positions in the screen
* for the case of detached slices
* So, we restart, using the correct information
* Center of Shape
m.lnX1 = This.aCoord(m.lnFoundShape,3) / 2
m.lnY1 = This.aCoord(m.lnFoundShape,4) / 2
* Coordinates inside the Shape
m.lnX2 = m.nXCoord - m.lnLeft - m.lnX1 - This.aCoord(m.lnFoundShape, 1)
m.lnY2 = -(m.nYCoord - m.lnTop - m.lnY1 - This.aCoord(m.lnFoundShape, 2))
* Percentage in the ellipse
m.lnX3 = m.lnX2 / m.lnX1
m.lnY3 = m.lnY2 / m.lnY1
*** NEW ANGLE
* Angle in degrees [0<>..360<EFBFBD>]
m.lnAngle = RTOD(ATAN(m.lnY2/m.lnX2))
DO CASE
CASE m.lnX2 < 0
m.lnAngle = 180 + m.lnAngle
CASE m.lnY2 < 0
m.lnAngle = 360 + m.lnAngle
ENDCASE
m.lnAngle = 360 - m.lnAngle
IF BETWEEN(m.lnAngle, m.lnStart, m.lnStart + m.lnSweep) OR ;
BETWEEN(m.lnAngle + 360, m.lnStart, m.lnStart + m.lnSweep)
ELSE
IF This._nMouseOnShape <> 0
This._nMouseOnShape = 0
IF This.ChangeColoronMouse
This._SkipPrepareData = .T.
This.DrawChart()
ENDIF
This.ShapeMouseLeave(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ENDIF
RETURN
ENDIF
*** NEW ANGLE
LOCAL lnRatio
m.lnRatio = m.lnY3^2 + m.lnX3^2
IF m.lnRatio > 1 OR ;
This.ChartType = 2 AND m.lnRatio < This.DonutRatio / 2 && Doughnut
IF This._nMouseOnShape <> 0
This._nMouseOnShape = 0
This.ShapeMouseLeave(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
IF This.ChangeColoronMouse
This._SkipPrepareData = .T.
This.DrawChart()
ENDIF
This.ShapeMouseLeave(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ENDIF
RETURN
ENDIF
m.lnValue = This.aCoord(m.lnFoundShape, 5)
m.lcLegend = This.aCoord(m.lnFoundShape, 6)
m.lnCoordIndex = m.lnFoundShape
m.lcObjType = "Pie"
IF This._nMouseOnShape = 0
This._nMouseOnShape = m.lnFoundShape
IF This.ChangeColoronMouse
This._SkipPrepareData = .T.
This.DrawChart()
ENDIF
This.ShapeMouseEnter(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ELSE
IF This._nMouseOnShape <> m.lnFoundShape
This._nMouseOnShape = m.lnFoundShape
IF This.ChangeColoronMouse
This._SkipPrepareData = .T.
This.DrawChart()
ENDIF
This.ShapeMouseEnter(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ELSE
This.ShapeMouseMove(m.nButton, m.nShift, m.nXCoord, m.nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex)
ENDIF
ENDIF
RETURN
OTHERWISE
ENDCASE
ENDPROC
PROCEDURE _checkparams
ASSERT BETWEEN(This.AlphaChannel, 0, 255) MESSAGE "AlphaChannel must be between 0-255"
ASSERT BETWEEN(This.AxisAlpha, 0, 255) MESSAGE "AxisAlpha must be between 0-255"
ASSERT BETWEEN(This.BackGradientMode, 0, 3) MESSAGE "BackGradientMode not available (0-3)"
ASSERT BETWEEN(This.BarType, 0, 2) MESSAGE "BarType not available (0-2)"
ASSERT BETWEEN(This.BrushType, 1, 3) MESSAGE "BrushType not available (1-3)"
ASSERT BETWEEN(This.ChartType, 1, 18) MESSAGE "ChartType not available (1-18)"
ASSERT BETWEEN(This.ColorType, 0, 27) MESSAGE "ColorType not available (0-27)"
ASSERT BETWEEN(This.DonutRatio, 0, 1) MESSAGE "DonutRatio must be between 0 and 1"
ASSERT BETWEEN(This.GradientLevel, -10, +10) MESSAGE "GradientLevel not available (-10, +10)"
ASSERT BETWEEN(This.ScaleBackAlpha, 0, 255) MESSAGE "ScaleBackAlpha must be between 0-255"
ASSERT BETWEEN(This.ScaleBackBarsType, 0, 3) MESSAGE "ScaleBackBarsType not available (0-3)"
ASSERT BETWEEN(This.ScaleBackLinesType, 0, 3) MESSAGE "ScaleBackLinesType not available (0-3)"
ASSERT BETWEEN(This.ScaleBackLinesDash, 0, 4) MESSAGE "ScaleBackLinesDash must be between 0-4"
ASSERT This.ScaleDivider > 0 MESSAGE "ScaleDivider must be greater than Zero"
ASSERT This.BarsPerScale > 0 MESSAGE "BarsPerScale must be greater than Zero"
ASSERT This.LegendPosition <=12 MESSAGE "LegendPosition must be between 0-12"
ASSERT USED(This.SourceAlias) MESSAGE "The specified source alias - '" + ;
This.SourceAlias + "' could not be found!"
IF This.ColorType = 3 && Gradient
ASSERT (VARTYPE(This.Fields(1).Color) = "N" OR VARTYPE(This.Color1) = "N") ;
MESSAGE "You have to define the property .Fields(1).Color to determine the main starting gradient color"
ENDIF
* GdiPlusX version check
LOCAL lnVersion
m.lnVersion = 1.10
IF pemstatus(_Screen.System, "Version", 5)
m.lnVersion = _Screen.System.Version
ENDIF
IF m.lnVersion < 1.20
ASSERT (This.ChartType <> 4) ;
MESSAGE "Points ChartType #4 is not supported for GdiPlusX System.App versions prior to version 1.20" + CHR(13) + ;
"Please make sure to be using at least version 1.20 to be able to use this type of chart"
ENDIF
ENDPROC
PROCEDURE _detachclickedslice
LPARAMETERS tnIndex
LOCAL llOrigDetach as Boolean
IF EMPTY(m.tnIndex) OR (VARTYPE(m.tnIndex) <> "N")
RETURN
ENDIF
LOCAL lnRecno, lnChartIndex, llOriginalDetach
*!* This.aCoord(n,1) = tnX
*!* This.aCoord(n,2) = tnY
*!* This.aCoord(n,3) = tnWidth
*!* This.aCoord(n,4) = tnHeight
*!* This.aCoord(n,5) = tnValue
*!* This.aCoord(n,7) = tnStart
*!* This.aCoord(n,8) = tnSweep
*!* This.aCoord(n,9) = This._ChartIndex
*!* This.aCoord(n,10) = RECNO()
m.lnRecno = This.aCoord(m.tnIndex,10)
m.lnChartIndex = This.aCoord(m.tnIndex,9)
SELECT (This._DataCursor)
GO m.lnRecno
m.llOrigDetach = lDetach
LOCAL lcCursor
m.lcCursor = (This._DataCursor)
REPLACE lDetach WITH NOT lDetach FOR RECNO() = m.lnRecno IN &lcCursor
IF m.llOrigDetach
This._SkipPrepareData = .T.
This.DrawChart()
ELSE
This._PieAnimatedRec = m.lnRecno
LOCAL lnDetachPixels, n, lnStep
m.lnDetachPixels = This.PieDetachPixels
m.lnStep = m.lnDetachPixels / MAX(1,This.PieDetachAnimationSteps)
FOR m.n = m.lnStep TO m.lnDetachPixels STEP m.lnStep
This._PieAnimationPix = m.n
This._SkipPrepareData = .T.
This.DrawChart()
ENDFOR
ENDIF
This._PieAnimatedRec = 0
This._PieAnimationPix = 0
This._SkipPrepareData = .F.
ENDPROC
PROCEDURE _drawaxis
LOCAL ln3D, lnMargin, lnYAxisHeight
LOCAL lnHeight as Number
m.lnMargin = This.Margin
IF This._DeepChart && Point, Line or Area
m.ln3D = This._3D * This.ChartsCount
ELSE
m.ln3D = This._3D
ENDIF
* Prepare the scale in the Y Axis, populating the ._ScaleW property
This._GetyLegendSize()
IF This.ChartType = 18 AND This.ShowScale && DoubleAxis
This._GetyLegendSize(2)
ENDIF
m.lnYAxisHeight = 0
IF This.ShowAxis = .T.
* Draw the main Y Axis caption
LOCAL lcYText
m.lcYText = This.YAxis.Caption
IF NOT EMPTY(m.lcYText)
This.YAxis.Reset()
m.lnYaxisHeight = CEILING(This.YAxis._Height)
ENDIF
ENDIF
* Leaving some extra space for the X Axis legends
LOCAL lnMinLeft, lnLeftCaptionWidth
IF NOT EMPTY(This.FieldAxis2)
* Measure the legend width
This.AxisLegend2._Setup()
GO TOP && First Legend
This.AxisLegend2.Caption = cAxis2 && Field text
m.lnLeftCaptionWidth = This.AxisLegend2._Width
m.lnMinLeft = m.lnLeftCaptionWidth / 2
ELSE
m.lnMinLeft = 0
m.lnLeftCaptionWidth = 0
ENDIF
LOCAL lnEstimatedX, lnXBetween
m.lnEstimatedX = This.Width - ;
(This._Rightoffset + This._Scalew + m.lnYaxisHeight + m.ln3D)
m.lnXBetween = m.lnEstimatedX / This._nRecords
IF m.lnXBetween > (m.lnLeftCaptionWidth / 2)
m.lnMinLeft = (m.lnLeftCaptionWidth / 2) && - lnXBetween
ENDIF
IF (NOT This.ShowAxis) OR (NOT This._AllowAxis)
IF This._Orientation = 1 && Vertical
This._yAxisWidth = 0 + m.lnMinLeft
ELSE && Horizontal
This._yAxisWidth = MAX(m.lnMinLeft, 0 + This._ScaleW)
ENDIF
This._XAxisHeight = This._XAxisHeight - This.XAxis._Height
RETURN
ENDIF
LOCAL lnTickWidth
m.lnTickWidth = 4
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
WITH _Screen.System.Drawing
* Determining Colors, Brushes and Pens
LOCAL lnAxisColor, lnAxisBorderColor
IF This.BrushType = 3 && Monochrome
m.lnAxisColor = RGB(255,255,255) && White
m.lnAxisBorderColor = 0 && Black
ELSE
m.lnAxisColor = This.AxisColor
m.lnAxisBorderColor = This.ChangeColor(m.lnAxisColor, -30)
ENDIF
LOCAL loAxisMainColor as xfcColor
LOCAL loAxisBorderColor as xfcColor
m.loAxisMainColor = .Color.FromARGB(This.AxisAlpha, m.lnAxisColor)
m.loAxisBorderColor = .Color.FromARGB(This.AxisAlpha, m.lnAxisBorderColor)
LOCAL loPen as xfcPen
m.loPen = .Pen.New(m.loAxisBorderColor, 1)
LOCAL loBrush as xfcSolidBrush
m.loBrush = .SolidBrush.New(m.loAxisMainColor)
ENDWITH
This._DrawYAxis(m.ln3D, m.lnMinLeft, m.lnYAxisHeight, m.loBrush, m.loPen, 1)
IF This.ChartType = 18 && DoubleAxis
This._DrawYAxis(m.ln3D, m.lnMinLeft, m.lnYAxisHeight, m.loBrush, m.loPen, 2)
IF This.ShowScale
* This._DrawScale(m.loPen, 2)
ENDIF
ENDIF
WITH _Screen.System.Drawing
m.lnHeight = This.ChartCanvas.Height - This._XAxisHeight - This._TopOffSet - m.ln3D
This._ChartY0 = This.ChartCanvas.Height - This._XAxisHeight - m.ln3D
This._ChartY1 = This._ChartY0 - m.lnHeight
* Draw the X Axis
m.lnMargin = This._yAxisWidth + This._LeftOffset
LOCAL x0, x1, y0
m.x0 = m.lnMargin
m.x1 = This.ChartCanvas.Width - This._RightOffset - This._yAxisWidth2
m.y0 = ROUND(This.ChartCanvas.Height - This._XAxisHeight + 1,0)
IF This.ShowAxis = .T.
IF m.ln3D = 0
m.loGfx.DrawLine(m.loPen, m.x0, m.y0, m.x1, m.y0)
ELSE
LOCAL laPoints(4)
m.laPoints(1) = .Point.New(m.x0, m.y0)
m.laPoints(2) = .Point.New(m.x0 + m.ln3D, m.y0 - m.ln3D)
m.laPoints(3) = .Point.New(m.x1, m.y0 - m.ln3D)
m.laPoints(4) = .Point.New(m.x1 - m.ln3D, m.y0)
m.loGfx.FillPolygon(m.loBrush, @m.laPoints)
LOCAL laPointsB(6)
m.laPointsB(1) = m.laPoints(1)
m.laPointsB(2) = m.laPoints(4)
m.laPointsB(3) = m.laPoints(3)
m.laPointsB(4) = .Point.New(m.laPoints(3).x, m.y0 - m.ln3D + 3)
m.laPointsB(5) = .Point.New(m.laPoints(4).x, m.y0 + 3)
m.laPointsB(6) = .Point.New(m.laPoints(1).x, m.y0 + 3)
m.loGfx.FillPolygon(m.loBrush, @m.laPointsB)
m.loGfx.DrawPolygon(m.loPen, @m.laPointsB)
m.loGfx.DrawLine(m.loPen, m.x0, m.y0, m.x0 + m.ln3D, m.y0 - m.ln3D)
ENDIF
ENDIF
* Draw the main X Axis caption
IF NOT EMPTY(This.XAxis.Caption)
This.XAxis.Reset()
LOCAL lnX, lnY, lnW, lnH
m.lnX = m.lnMargin
m.lnY = m.y0 + This._LegendPixHeight + 4
m.lnW = m.x1 - m.x0
m.lnH = This.XAxis._Height
This.XAxis._DrawString(m.lnX, m.lnY, m.lnW, m.lnH)
ENDIF
IF This.ShowScale
This._DrawScale(m.loPen)
ENDIF
IF This.ChartType = 18 && DoubleAxis
* This._DrawYAxis(ln3D, lnMinLeft, lnYAxisHeight, loBrush, loPen, 2)
IF This.ShowScale
This._DrawScale(m.loPen, 2)
ENDIF
ENDIF
ENDWITH
ENDPROC
PROCEDURE _drawbar
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue
m.tnHeight = ABS(m.tnHeight)
LOCAL ln3D
m.ln3D = This._3D
DO CASE
CASE This.BarType = 1 && Cylinder
This._UpdateCoordinates("Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
This._DrawCylinder(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
RETURN
CASE This.BarType = 2 && Triangle
This._UpdateCoordinates("Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
This._DrawTriangleBar(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
RETURN
OTHERWISE
This._UpdateCoordinates("Rect", m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
ENDCASE
This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex))
LOCAL loPen as xfcPen
m.loPen = This._oBorderPen
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
LOCAL loMainBrush as xfcBrush
m.loMainBrush = This._oMainBrush
LOCAL lo3dBrush as xfcBrush
m.lo3DBrush = This._o3DBrush
WITH _Screen.System.Drawing
* Draw the 3D Bar using the 3DBrush
IF m.ln3D > 0 && 3D
IF This.Shadow = .F.
* Prepare Array of points to draw the 3D part of the Bar
LOCAL laPoints(4)
m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY)
m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D)
m.laPoints(3) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D)
m.laPoints(4) = .PointF.New(m.tnX, m.tnY)
m.loGfx.FillPolygon(m.lo3DBrush, @m.laPoints)
m.loGfx.DrawPolygon(m.loPen, @m.laPoints)
* Change only Points 3 and 4
m.laPoints(3) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY + m.tnHeight - m.ln3D)
m.laPoints(4) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight)
m.loGfx.FillPolygon(m.lo3DBrush, @m.laPoints)
m.loGfx.DrawPolygon(m.loPen, @m.laPoints)
ELSE
LOCAL loShadowBrush as xfcSolidBrush
m.loShadowBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel,128,128,128))
m.loGfx.FillRectangle(m.loShadowBrush , m.tnX + m.ln3D, m.tnY + m.ln3D, m.tnWidth, m.tnHeight - m.ln3d - m.ln3d)
LOCAL laPoints(4)
m.laPoints(1) = .PointF.New(m.tnX , m.tnY + m.tnHeight)
m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth , m.tnY + m.tnHeight)
m.laPoints(3) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY + m.tnHeight - m.ln3D)
m.laPoints(4) = .PointF.New(m.tnX + m.ln3d, m.tnY + m.tnHeight - m.ln3D)
m.loGfx.FillPolygon(m.loShadowBrush , @m.laPoints)
ENDIF
ENDIF
m.loGfx.FillRectangle(m.loMainBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight)
m.loGfx.DrawRectangle(m.loPen, m.tnX, m.tnY, m.tnWidth, m.tnHeight)
IF This._GeneralType = "Bar"
This._DrawLegendinBar(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
ENDIF
ENDWITH
RETURN
ENDPROC
PROCEDURE _drawbarchart
LOCAL lnWidth, lnHeight, x1, y1, n, lnValue, lnLeftMargin, ln3D, lnTopMargin
LOCAL lnPointHeight as Number, ;
lnYBase as Number
SELECT(This._DataCursor)
m.ln3D = This._3D
m.lnWidth = This.ChartCanvas.Width - This._LeftOffset - This._RightOffset - m.ln3D - This._yAxisWidth
m.lnHeight = This.ChartCanvas.Height - This._XAxisHeight - This._TopOffSet - m.ln3D
IF (m.lnWidth <= 0) OR (m.lnHeight <= 0)
RETURN
ENDIF
m.lnLeftMargin = This._yAxisWidth + This._LeftOffset
m.lnTopMargin = This._TopOffSet + m.ln3D
LOCAL lnBarWidth, lnBarHeight, lnBetween, lnMaxValue, lnAdjust, lnChartsCount
m.lnBetween = This.BarsSpaceBetween
m.lnMaxValue = This._ScaleRange
m.lnChartsCount = This.ChartsCount
* Prepare Points
IF This._Orientation = 1 && Vertical
IF This._DeepChart
m.lnWidth = m.lnWidth - (m.ln3D * (m.lnChartsCount - 1))
ENDIF
m.lnBetween = MIN(m.lnBetween, ;
(m.lnWidth - This._nRecords) / This._nRecords)
m.lnBarWidth = (m.lnWidth - (This._nRecords - 1) * m.lnBetween) / This._nRecords
SCAN
m.n = RECNO()
m.x1 = m.lnLeftMargin + ((m.lnBarWidth + m.lnBetween) * (m.n - 1))
This._aPoints(m.n,1) = m.x1 + (m.lnBarWidth / 2)
ENDSCAN
ELSE && Horizontal
m.lnBetween = MIN(m.lnBetween, ;
(m.lnHeight - This._nRecords) / This._nRecords)
m.lnBarHeight = (m.lnHeight - (This._nRecords - 1) * m.lnBetween) / This._nRecords
SCAN
m.n = RECNO()
m.y1 = m.lnTopMargin + ((m.lnBarHeight + m.lnBetween) * (m.n - 1))
This._aPoints(m.n,2) = m.y1 + (m.lnBarHeight / 2)
ENDSCAN
This._DrawYAxisLegend()
ENDIF
This._DrawVerticalLineBack()
DO CASE
CASE This.ChartType = 7 && Simple Bar
LOCAL lnZeroY, lnValue2, lnScaleAdjustment
m.lnScaleAdjustment = This._ScaleAdjust / m.lnMaxValue * m.lnHeight
m.lnZeroY = This._TopOffSet + m.ln3D + (This._MaxScale / m.lnMaxValue * m.lnHeight)
IF This._MinScale > 0
m.lnZeroY = m.lnZeroY - (This._MinScale / m.lnMaxValue * m.lnHeight)
ENDIF
This._ChartIndex = This.ChartRow
SCAN
m.lnValue = This._GetValue(This.ChartRow, .T.)
IF ISNULL(m.lnValue) OR m.lnValue < This._MinScale
LOOP
ENDIF
IF m.lnValue < 0
m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight)
m.y1 = m.lnZeroY
ELSE
m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight) + ;
IIF(This._ScaleAdjust < 0, m.lnScaleAdjustment, 0)
m.y1 = m.lnZeroY - m.lnBarHeight
ENDIF
m.x1 = m.lnLeftMargin + ((m.lnBarWidth + m.lnBetween) * (RECNO() - 1))
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
ENDSCAN
CASE This.ChartType = 8 && Multi Bars
LOCAL i, lnOneBarWidth, lnZeroY, lnScaleAdjustment
LOCAL lnTotRow
LOCAL laValues(m.lnChartsCount)
m.lnOneBarWidth = m.lnBarWidth / m.lnChartsCount
m.lnZeroY = This._TopOffSet + m.ln3D + (This._MaxScale / m.lnMaxValue * m.lnHeight)
IF This._MinScale > 0
m.lnZeroY = m.lnZeroY - (This._MinScale / m.lnMaxValue * m.lnHeight)
ENDIF
m.lnScaleAdjustment = This._ScaleAdjust / m.lnMaxValue * m.lnHeight
SCAN
m.n = RECNO()
m.lnTotRow = 0
* Get the total for the current row
FOR m.i = 1 TO m.lnChartsCount
m.lnValue = This._GetValue(m.i, .T.)
m.laValues(m.i) = m.lnValue
m.lnTotRow = m.lnTotRow + NVL(m.lnValue, 0)
ENDFOR
FOR m.i = 1 TO m.lnChartsCount
m.lnValue = m.laValues(m.i)
IF ISNULL(m.lnValue) OR m.lnValue < This._MinScale
LOOP
ENDIF
This._ChartIndex = m.i
m.x1 = m.lnLeftMargin + ;
((m.lnBarWidth + m.lnBetween) * (m.n - 1)) + ;
((m.i-1 ) * m.lnOneBarWidth)
IF m.lnValue < 0
m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight)
m.y1 = m.lnZeroY
ELSE
m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight) + ;
IIF(This._ScaleAdjust < 0, m.lnScaleAdjustment, 0)
m.y1 = m.lnZeroY - m.lnBarHeight
ENDIF
This.ChartSum = m.lnTotRow
This._DrawBar(m.x1, m.y1, m.lnOneBarWidth, m.lnBarHeight, m.lnValue)
ENDFOR
ENDSCAN
This._ChartIndex = 1
CASE This.ChartType = 9 && Stacked Bars
m.lnYBase = This._TopOffSet + m.ln3D + m.lnHeight
SCAN
m.y1 = m.lnYBase
FOR m.i = 1 TO m.lnChartsCount
This._ChartIndex = m.i
m.lnValue = This._GetValue(m.i, .T.)
IF ISNULL(m.lnValue) OR m.lnValue = 0
LOOP
ENDIF
m.lnBarHeight = m.lnValue / m.lnMaxValue * m.lnHeight
m.x1 = m.lnLeftMargin + ;
((m.lnBarWidth + m.lnBetween) * (RECNO() - 1))
m.y1 = m.y1 - m.lnBarHeight
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
ENDFOR
ENDSCAN
This._ChartIndex = 1
CASE This.ChartType = 11 && 3D Bars
* Calculate the maximum width of the chart
m.lnHeight = m.lnHeight - (m.ln3D * (m.lnChartsCount - 1))
* Not needed any more, this is now calculated above, checking for _DeepChart
* m.lnWidth = m.lnWidth - (m.ln3D * (m.lnChartsCount - 1))
* m.lnBarWidth = (m.lnWidth - (This._nRecords - 1) * m.lnBetween) / This._nRecords
FOR m.i = 1 TO m.lnChartsCount
This._ChartIndex = m.i
m.lnAdjust = (m.ln3D * (m.lnChartsCount - m.i ))
SCAN
m.n = RECNO()
m.lnValue = This._GetValue(m.i, .T.)
m.x1 = m.lnLeftMargin + m.lnAdjust + ((m.lnBarWidth + m.lnBetween) * (RECNO() - 1))
IF m.i = m.lnChartsCount
* Prepare Points
This._aPoints(m.n,1) = m.x1 + (m.lnBarWidth / 2)
ENDIF
IF ISNULL(m.lnValue)
LOOP
ENDIF
m.lnPointHeight = m.lnValue / m.lnMaxValue * m.lnHeight
m.y1 = This._TopOffSet + (m.lnHeight - m.lnPointHeight) - m.lnAdjust + (m.ln3D * (m.lnChartsCount))
m.lnYBase = This.ChartCanvas.Height - This._xAxisHeight - m.lnAdjust
m.lnBarHeight = m.lnYBase - m.y1
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
ENDSCAN
ENDFOR
CASE This.ChartType = 12 && HORIZONTAL Simple Bar
IF m.lnBetween >= m.lnHeight / (This._nRecords - 1)
m.lnBarHeight = 1
m.lnBetween = (m.lnHeight - This._nRecords) / (This._nRecords - 1)
ENDIF
LOCAL lnZeroX, lnScaleAdjustment
m.lnZeroX = m.lnLeftMargin + IIF(This._ScaleAdjust < 0 , 0, (This._ScaleAdjust / m.lnMaxValue * m.lnWidth))
m.lnScaleAdjustment = This._ScaleAdjust / m.lnMaxValue * m.lnWidth
This._ChartIndex = This.ChartRow
SET ORDER TO Revert
SCAN
m.lnValue = This._GetValue(This.ChartRow, .T.)
IF ISNULL(m.lnValue) OR m.lnValue < This._MinScale
LOOP
ENDIF
IF m.lnValue < 0
m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth)
m.x1 = m.lnZeroX - m.lnBarWidth
ELSE
m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth) + ;
IIF(This._ScaleAdjust < 0, m.lnScaleAdjustment, 0)
m.x1 = m.lnZeroX
ENDIF
m.y1 = This._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
ENDSCAN
SET ORDER TO
CASE This.ChartType = 13 && HORIZONTAL Multi Bars
IF m.lnBetween >= m.lnHeight / (This._nRecords - 1)
m.lnBarHeight = 1
m.lnBetween = (m.lnHeight - This._nRecords) / (This._nRecords - 1)
ENDIF
m.lnBarHeight = (m.lnHeight - (This._nRecords - 1) * m.lnBetween) / This._nRecords
LOCAL i, lnOneBarHeight
m.lnOneBarHeight = m.lnBarHeight / m.lnChartsCount
LOCAL lnZeroX, lnScaleAdjustment
m.lnZeroX = m.lnLeftMargin + IIF(This._ScaleAdjust < 0 , 0, (This._ScaleAdjust / m.lnMaxValue * m.lnWidth))
m.lnScaleAdjustment = This._ScaleAdjust / m.lnMaxValue * m.lnWidth
LOCAL lnTotRow
LOCAL laValues(m.lnChartsCount)
SET ORDER TO Revert
SCAN
m.n = RECNO()
m.lnTotRow = 0
* Get the total for the current row
FOR m.i = m.lnChartsCount TO 1 STEP -1
m.lnValue = This._GetValue(m.i, .T.)
m.laValues(m.i) = m.lnValue
m.lnTotRow = m.lnTotRow + NVL(m.lnValue, 0)
ENDFOR
FOR m.i = m.lnChartsCount TO 1 STEP -1
m.lnValue = m.laValues(m.i)
IF ISNULL(m.lnValue) OR m.lnValue < This._MinScale
LOOP
ENDIF
This._ChartIndex = m.i
IF m.lnValue < 0
m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth)
m.x1 = m.lnZeroX - m.lnBarWidth
ELSE
m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth) + ;
IIF(This._ScaleAdjust < 0, m.lnScaleAdjustment, 0)
m.x1 = m.lnZeroX
ENDIF
m.y1 = This._TopOffSet + m.ln3D + ((m.lnBarHeight + m.lnBetween) * (m.n - 1)) + ;
((m.i-1 ) * m.lnOneBarHeight)
This.ChartSum = m.lnTotRow
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnOneBarHeight, m.lnValue)
ENDFOR
ENDSCAN
SET ORDER TO
This._ChartIndex = 1
CASE This.ChartType = 14 && HORIZONTAL Stacked Bars
IF m.lnBetween >= m.lnHeight / (This._nRecords - 1)
m.lnBarHeight = 1
m.lnBetween = (m.lnHeight - This._nRecords) / (This._nRecords - 1)
ENDIF
SET ORDER TO Revert
SCAN
m.x1 = m.lnLeftMargin
FOR m.i = 1 TO m.lnChartsCount
This._ChartIndex = m.i
m.lnValue = This._GetValue(m.i, .T.)
IF ISNULL(m.lnValue)
LOOP
ENDIF
m.lnBarWidth = m.lnValue / m.lnMaxValue * m.lnWidth
m.y1 = This._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
m.x1 = m.x1 + m.lnBarWidth
ENDFOR
ENDSCAN
SET ORDER TO
This._ChartIndex = 1
CASE This.ChartType = 15 && HORIZONTAL Full-Stacked Bars
IF m.lnBetween >= m.lnHeight / (This._nRecords - 1)
m.lnBarHeight = 1
m.lnBetween = (m.lnHeight - This._nRecords) / (This._nRecords - 1)
ENDIF
SET ORDER TO Revert
LOCAL lnTotRow
LOCAL laValues(m.lnChartsCount)
SCAN
m.lnTotRow = 0
* Get the total for the current row
FOR m.i = 1 TO m.lnChartsCount
m.lnValue = NVL(This._GetValue(m.i, .T.),0)
m.laValues(m.i) = m.lnValue
m.lnTotRow = m.lnTotRow + m.lnValue
ENDFOR
m.x1 = m.lnLeftMargin
FOR m.i = 1 TO m.lnChartsCount
m.lnValue = m.laValues(m.i)
IF m.lnValue = 0
LOOP
ENDIF
m.lnBarWidth = m.lnValue / m.lnTotRow * m.lnWidth
m.y1 = This._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D
This._ChartIndex = m.i
This.ChartSum = m.lnTotRow
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
m.x1 = m.x1 + m.lnBarWidth
ENDFOR
ENDSCAN
SET ORDER TO
This._ChartIndex = 1
CASE This.ChartType = 3 && Full-Stacked Bars
LOCAL lnTotRow
LOCAL laValues(m.lnChartsCount)
m.lnYBase = This._TopOffSet + m.ln3D + m.lnHeight
SCAN
m.y1 = m.lnYBase
m.lnTotRow = 0
* Get the total for the current row
FOR m.i = 1 TO m.lnChartsCount
m.lnValue = NVL(This._GetValue(m.i, .T.),0)
m.laValues(m.i) = m.lnValue
m.lnTotRow = m.lnTotRow + m.lnValue
ENDFOR
FOR m.i = 1 TO m.lnChartsCount
m.lnValue = m.laValues(m.i)
IF m.lnValue = 0
LOOP
ENDIF
m.lnBarHeight = m.lnValue / m.lnTotRow * m.lnHeight
m.x1 = m.lnLeftMargin + ;
((m.lnBarWidth + m.lnBetween) * (RECNO() - 1))
m.y1 = m.y1 - m.lnBarHeight
This._ChartIndex = m.i
This.ChartSum = m.lnTotRow
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
ENDFOR
ENDSCAN
This._ChartIndex = 1
CASE This.ChartType = 17 && PAIRED HORIZONTAL BARS
LOCAL lnZeroX, lnScaleAdjustment, lnAlign
m.lnZeroX = m.lnLeftMargin + (m.lnWidth / 2)
SET ORDER TO Revert
* Draw the left side of the chart
m.lnAlign = This.ShapeLegend.Alignment
DO CASE
CASE m.lnAlign = 0 && Left
This.ShapeLegend.Alignment = 1 && Right
CASE m.lnAlign = 1 && Right
This.ShapeLegend.Alignment = 0 && Left
OTHERWISE
ENDCASE
This._ChartIndex = 1
SCAN
m.lnValue = This._GetValue(1, .T.) && 1st column
IF ISNULL(m.lnValue) OR (m.lnValue < 0)
LOOP
ENDIF
m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth)
m.x1 = m.lnZeroX - m.lnBarWidth
m.y1 = This._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
ENDSCAN
This.ShapeLegend.Alignment = m.lnAlign && Restore to the original setting
IF m.lnChartsCount > 1
* Draw the right side of the chart
This._ChartIndex = 2
SCAN
m.lnValue = This._GetValue(2, .T.) && 2nd column
IF ISNULL(m.lnValue) OR (m.lnValue < This._MinScale) OR (m.lnValue < 0)
LOOP
ENDIF
m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth)
m.x1 = m.lnZeroX
m.y1 = This._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
ENDSCAN
ENDIF
SET ORDER TO
OTHERWISE
ENDCASE
* Draw Legends on X Axis for Vertical charts
IF This._Orientation = 1 && Vertical
IF This.BarType > 0
This._DrawXAxisLegend(m.ln3D/2)
ELSE
This._DrawXAxisLegend()
ENDIF
ENDIF
RETURN
ENDPROC
PROCEDURE _drawcylinder
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue
This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex))
LOCAL loPen as xfcPen
m.loPen = This._oBorderPen
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
LOCAL lnAlpha, lnOrigAlpha
m.lnOrigAlpha = This.AlphaChannel
m.lnAlpha = MIN(255, (This.AlphaChannel * 1.25))
This.AlphaChannel = m.lnAlpha
LOCAL loTopBrush as xfcBrush
LOCAL loBotBrush as xfcBrush
LOCAL xTopCyl
WITH _Screen.System.Drawing
DO CASE
CASE This.BrushType = 1 && SolidColors
m.loTopBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This.ChangeColor(This._nColor, - 20)))
m.loBotBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This._nColor))
CASE This.BrushType = 2 && Gradient
m.loTopBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This._nColor))
m.loBotBrush = m.loTopBrush
OTHERWISE
This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex))
m.loTopBrush = This._oMainBrush
m.loBotBrush = m.loTopBrush
ENDCASE
This.AlphaChannel = m.lnOrigAlpha
IF This._Orientation = 1 && Vertical
LOCAL yRect, ln3D, x0, yTopCyl, yBotCyl
m.ln3D = MAX(This._3d, 1)
m.yRect = m.tnY - (m.ln3D / 2)
m.yTopCyl = m.tnY - m.ln3D
m.yBotCyl = m.tnY + m.tnHeight - m.ln3D
m.x0 = m.tnX + m.ln3D / 2
* Draw the lower ellipse
m.loGfx.FillEllipse(m.loBotBrush, m.x0, m.yBotCyl, m.tnWidth, m.ln3D)
m.loGfx.FillEllipse(This._oMainBrush, m.x0, m.yBotCyl, m.tnWidth, m.ln3D)
* Draw the front shape using a GraphicsPath object
* Prepare the Main Path
LOCAL loPath as xfcGraphicsPath
m.loPath = .Drawing2D.GraphicsPath.New()
m.loPath.StartFigure()
* Bottom Arc
m.loPath.AddArc(m.x0, m.yBotCyl, m.tnWidth, m.ln3D, 0, 180)
m.loPath.Reverse()
* Right Line
m.loPath.AddLine(m.x0 + m.tnWidth, m.yRect + m.tnHeight, m.x0 + m.tnWidth, m.yRect)
* Top Arc
m.loPath.AddArc(m.x0, m.yTopCyl, m.tnWidth, m.ln3D, 0, 180)
* Draw the path
m.loGfx.FillPath(This._oMainBrush, m.loPath)
m.loGfx.DrawPath(m.loPen, m.loPath)
* Draw the upper ellipse
m.loGfx.FillEllipse(m.loTopBrush, m.x0, m.yTopCyl, m.tnWidth, m.ln3D)
m.loGfx.DrawEllipse(m.loPen , m.x0, m.yTopCyl, m.tnWidth, m.ln3D)
This._DrawLegendinBar(m.X0, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
ELSE &&_Orientation = 2 - Horizontal
LOCAL xRect, ln3D, x0
m.ln3D = MAX(This._3d, 1)
m.xRect = m.tnX && - (m.ln3D / 2)
m.xTopCyl = m.tnX + m.tnWidth && - m.ln3D / 2
* Draw the front shape using a GraphicsPath object
* Prepare the Main Path
LOCAL loPath as xfcGraphicsPath
m.loPath = .Drawing2D.GraphicsPath.New()
m.loPath.StartFigure()
* Bottom Arc
m.loPath.AddArc(m.tnX, m.tnY, m.ln3D, m.tnHeight, 270, 180)
* Bottom Line
m.loPath.AddLine(m.tnX + m.ln3D / 2, m.tnY + m.tnHeight, m.xTopCyl + m.ln3D / 2, m.tnY + m.tnHeight)
* Top Arc
m.loPath.AddArc(m.xTopCyl, m.tnY, m.ln3D, m.tnHeight, 90, 180)
* Top Line
m.loPath.AddLine(m.xTopCyl + m.ln3D / 2, m.tnY, m.tnX + m.ln3D / 2, m.tnY)
* Draw the path
m.loGfx.FillPath(This._oMainBrush, m.loPath)
m.loGfx.DrawPath(m.loPen, m.loPath)
* Draw the upper ellipse
m.loGfx.FillEllipse(m.loTopBrush, m.xTopCyl, m.tnY, m.ln3D, m.tnHeight)
m.loGfx.DrawEllipse(m.loPen , m.xTopCyl, m.tnY, m.ln3D, m.tnHeight)
* Draw the left-most ellipse
m.loGfx.FillEllipse(m.loBotBrush , m.tnX, m.tnY, m.ln3D, m.tnHeight)
m.loGfx.FillEllipse(This._oMainBrush, m.tnX, m.tnY, m.ln3D, m.tnHeight)
This._DrawLegendinBar(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
ENDIF
ENDWITH
ENDPROC
PROCEDURE _drawdoughnutslice
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnStart, tnSweep, tnValue
Local laEndPoints[1], ;
laPoints[1], ;
laPointsB[1], ;
laStartPoints[1], ;
loPoint4 as Object, ;
loPoint5 as Object, ;
loPoint6 as Object
IF m.tnWidth <= 0 OR m.tnHeight <= 0
RETURN
ENDIF
This._AdjustStartSweep(@m.tnStart, @m.tnSweep, m.tnWidth, m.tnHeight)
This._UpdateCoordinates("Pie", m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, m.tnStart, m.tnSweep)
LOCAL lnXBrush, lnYBrush
IF This.PieEnhancedDrawing
m.lnXBrush = m.tnX
m.lnYBrush = m.tnY
ELSE
m.lnXBrush = 0
m.lnYBrush = 0
ENDIF
This._PrepareBrushes(m.lnXBrush, m.lnYBrush, m.tnWidth, m.tnHeight, .F., RECNO())
LOCAL loPen as xfcPen
m.loPen = This._oBorderPen
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
LOCAL loMainBrush as xfcBrush
m.loMainBrush = This._oMainBrush
LOCAL lo3dBrush as xfcBrush
m.lo3dBrush = This._o3DBrush
LOCAL ln3d, lnFinalAngle
m.ln3d = This._3D
m.lnFinalAngle = m.tnStart + m.tnSweep
IF m.lnFinalAngle > 360
m.lnFinalAngle = m.lnFinalAngle - 360
ENDIF
IF This.PieEnhancedDrawing && New behavior for Doughnuts
&& Drawing all edges using the GraphicsPath class
WITH _Screen.System.Drawing
* Create a GraphicsPath object.
LOCAL loMainPath as xfcGraphicsPath
m.loMainPath = .Drawing2D.GraphicsPath.New()
LOCAL loRect as xfcRectangle
LOCAL loRect2 as xfcRectangle
LOCAL lnRatio
m.lnRatio = This.DonutRatio
m.loRect = .Rectangle.New(m.tnX, m.tnY, m.tnWidth, m.tnHeight)
m.loRect2 = .Rectangle.New( ;
m.tnX + (m.tnWidth * (1 - m.lnRatio) / 2), ;
m.tnY + (m.tnHeight * (1 - m.lnRatio) / 2), ;
m.tnWidth * m.lnRatio, ;
m.tnHeight * m.lnRatio)
LOCAL lnXInt, lnYInt, lnHInt, lnWInt
m.lnXInt = m.loRect2.X
m.lnYInt = m.loRect2.Y
m.lnWInt = m.loRect2.Width
m.lnHInt = m.loRect2.Height
LOCAL loPoint0 as xfcPointF
LOCAL loPoint1 as xfcPointF
LOCAL loPoint2 as xfcPointF
LOCAL loPoint3 as xfcPointF
* Obtaining the needed points
m.loMainPath.AddArc(m.loRect, m.tnStart, 0.0001)
m.loPoint0 = m.loMainPath.GetLastPoint()
m.loMainPath.AddArc(m.loRect2, m.tnStart, 0.0001)
m.loPoint3 = m.loMainPath.GetLastPoint()
m.loMainPath.AddArc(m.loRect, m.tnStart, m.tnSweep)
m.loPoint1 = m.loMainPath.GetLastPoint()
m.loMainPath.AddArc(m.loRect2, m.tnStart, m.tnSweep)
m.loPoint2 = m.loMainPath.GetLastPoint()
m.loPoint4 = .Point.New(m.loPoint3.X, m.loPoint3.Y + m.ln3d)
m.loPoint5 = .Point.New(m.loPoint0.X, m.loPoint0.Y + m.ln3d)
m.loPoint6 = .Point.New(m.loPoint1.X, m.loPoint1.Y + m.ln3d)
* Prepare the Main Path
LOCAL loPath as xfcGraphicsPath
m.loPath = .Drawing2D.GraphicsPath.New()
m.loPath.StartFigure()
m.loPath.AddArc(m.loRect2, m.tnStart, m.tnSweep)
m.loPath.Reverse()
m.loPath.AddLine(m.loPoint3.X, m.loPoint3.Y, m.loPoint0.X, m.loPoint0.Y)
m.loPath.AddArc(m.loRect, m.tnStart, m.tnSweep)
m.loPath.AddLine(m.loPoint1.X, m.loPoint1.Y, m.loPoint2.X, m.loPoint2.Y)
ENDWITH
IF m.ln3d = 0 OR This.Shadow
* Draw shadow
IF This.Shadow
* Prepare the Shadow Path
LOCAL loPath2 as xfcGraphicsPath
m.loPath2 = _Screen.System.Drawing.Drawing2D.GraphicsPath.New()
m.loPath2.StartFigure()
m.loPath2.AddArc(m.loRect2.X, m.loRect2.Y + m.ln3d, m.loRect2.Width, m.loRect2.Height, m.tnStart, m.tnSweep)
m.loPath2.Reverse()
m.loPath2.AddLine(m.loPoint3.X, m.loPoint3.Y + m.ln3d, m.loPoint0.X, m.loPoint0.Y + m.ln3d)
m.loPath2.AddArc(m.loRect.X, m.loRect.Y + m.ln3d, m.loRect.Width, m.loRect.Height, m.tnStart, m.tnSweep)
m.loPath2.AddLine(m.loPoint1.X, m.loPoint1.Y + m.ln3d, m.loPoint2.X, m.loPoint2.Y + m.ln3d)
* Prepare the shadow brush
LOCAL loShadowBrush as xfcSolidBrush
m.loShadowBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, 128, 128, 128))
* Draw the shadow
m.loGfx.FillPath(m.loShadowBrush, m.loPath2)
ENDIF
* Draw the Main doughnut slice (path)
m.loGfx.FillPath(m.loMainBrush, m.loPath)
m.loGfx.DrawPath(m.loPen, m.loPath)
RETURN
ENDIF
* Continue Drawing, for 3D chart
* Prepare the polygon points for the final part of the slice
DIMENSION m.laEndPoints(4)
m.laEndPoints(1) = m.loPoint1
m.laEndPoints(2) = m.loPoint2
m.laEndPoints(3) = _Screen.System.Drawing.Point.New(m.loPoint2.X, m.loPoint2.Y + m.ln3d)
m.laEndPoints(4) = m.loPoint6
* Prepare the polygon points for the beginning part of the slice
DIMENSION m.laStartPoints(4)
m.laStartPoints(1) = m.loPoint0
m.laStartPoints(2) = m.loPoint5
m.laStartPoints(3) = m.loPoint4
m.laStartPoints(4) = m.loPoint3
* If the slice ends in the left side, draw the Ending polygon before the top face of the slice
IF BETWEEN(m.lnFinalAngle, 90.001, 269.999)
m.loGfx.DrawPolygon(m.loPen, @m.laEndPoints)
m.loGfx.FillPolygon(m.lo3dBrush, @m.laEndPoints)
ENDIF
IF NOT (m.tnStart >= 90 AND m.tnStart <= 270)
m.loGfx.DrawPolygon(m.loPen, @m.laStartPoints)
m.loGfx.FillPolygon(m.lo3dBrush, @m.laStartPoints)
ENDIF
* Draw the external and internal paths
LOCAL lnFinalAngle
m.lnFinalAngle = m.tnStart + m.tnSweep
IF m.lnFinalAngle > 360
m.lnFinalAngle = m.lnFinalAngle - 360
ENDIF
LOCAL lnAdjStart, lnAdjSweep
m.lnAdjStart = m.tnStart
m.lnAdjSweep = m.tnSweep
LOCAL loAdjPoint0 as xfcPoint, loAdjPoint1 as xfcPoint
m.loAdjPoint0 = m.loPoint0
m.loAdjPoint1 = m.loPoint1
LOCAL loAdjPoint2 as xfcPoint, loAdjPoint3 as xfcPoint
m.loAdjPoint2 = m.loPoint3
m.loAdjPoint3 = m.loPoint2
IF m.tnStart >= 270 AND ;
m.tnStart < 360 AND ;
BETWEEN(m.lnFinalAngle, 0, 270)
LOCAL loTempPoint as xfcPoint
m.loTempPoint = _Screen.System.Drawing.Point.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight / 2)
LOCAL loTempPoint2 as xfcPoint
m.loTempPoint2 = _Screen.System.Drawing.Point.New(m.lnXInt + m.lnWInt, m.lnYInt + m.lnHInt / 2)
* External part
This._DrawSliceExternal(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, 360 - m.tnStart, m.loPoint0, m.loTempPoint)
* Internal part
This._DrawSliceExternal(m.lnXInt, m.lnYInt, m.lnWInt, m.lnHInt, m.tnStart, 360 - m.tnStart, m.loPoint3, m.loTempPoint2)
m.lnAdjStart = 0
m.lnAdjSweep = m.tnSweep - (360 - m.tnStart)
m.loAdjPoint0 = m.loTempPoint
m.loAdjPoint1 = m.loPoint1
* Internal
m.loAdjPoint2 = m.loTempPoint2
m.loAdjPoint3 = m.loPoint2
ENDIF
LOCAL llDrawExtAtEnd
m.llDrawExtAtEnd = .F.
IF (m.tnStart < 180 AND m.lnFinalAngle > 180) OR ;
(m.tnStart >= 270 AND m.lnFinalAngle > 180 AND m.lnFinalAngle < 270.01)
IF m.tnStart >= 270
m.lnAdjStart = 0
m.lnAdjSweep = 180
ELSE
m.lnAdjStart = m.tnStart
m.lnAdjSweep = 180 - m.tnStart
ENDIF
m.loAdjPoint1 = _Screen.System.Drawing.Point.New(m.tnX, m.tnY + m.tnHeight / 2)
m.loAdjPoint3 = _Screen.System.Drawing.Point.New(m.lnXInt, m.lnYInt + m.lnHInt / 2)
* External part
m.llDrawExtAtEnd = .T.
LOCAL lnStartB, lnSweepB, loPoint0B, loPoint1B
m.lnStartB = m.lnAdjStart
m.lnSweepB = m.lnAdjSweep
m.loPoint0B = m.loAdjPoint0
m.loPoint1B = m.loAdjPoint1
* Internal part
This._DrawSliceExternal(m.lnXInt, m.lnYInt, m.lnWInt, m.lnHInt, m.lnAdjStart, m.lnAdjSweep, m.loAdjPoint2, m.loAdjPoint3)
m.loAdjPoint0 = m.loAdjPoint1
m.loAdjPoint2 = m.loAdjPoint3
m.lnAdjStart = 180
m.lnAdjSweep = m.lnFinalAngle - 180
ENDIF
IF BETWEEN(m.lnFinalAngle, 0, 180)
* Internal part
This._DrawSliceExternal(m.lnXInt, m.lnYInt, m.lnWInt, m.lnHInt, m.lnAdjStart, m.lnAdjSweep, m.loAdjPoint2, m.loPoint2)
* External part
This._DrawSliceExternal(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.lnAdjStart, m.lnAdjSweep, m.loAdjPoint0, m.loPoint1)
ELSE
* External part
This._DrawSliceExternal(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.lnAdjStart, m.lnAdjSweep, m.loAdjPoint0, m.loPoint1)
* Internal part
This._DrawSliceExternal(m.lnXInt, m.lnYInt, m.lnWInt, m.lnHInt, m.lnAdjStart, m.lnAdjSweep, m.loAdjPoint2, m.loPoint2)
ENDIF
IF m.llDrawExtAtEnd
This._DrawSliceExternal(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.lnStartB, m.lnSweepB, m.loPoint0B, m.loPoint1B)
ENDIF
* Draw polygon at the beginning of the doughnut
IF m.tnStart > 90 AND m.tnStart < 270
m.loGfx.DrawPolygon(m.loPen, @m.laStartPoints)
m.loGfx.FillPolygon(m.lo3dBrush, @m.laStartPoints)
ENDIF
IF NOT BETWEEN(m.lnFinalAngle, 90, 270)
m.loGfx.DrawPolygon(m.loPen, @m.laEndPoints)
m.loGfx.FillPolygon(m.lo3dBrush, @m.laEndPoints)
ENDIF
* Draw the main path
m.loGfx.FillPath(m.loMainBrush, m.loPath)
m.loGfx.DrawPath(m.loPen, m.loPath)
ELSE && This.PieEnhancedDrawing .F. - This is the old Behavior
WITH _Screen.System.Drawing
LOCAL loBmp as xfcBitmap
m.loBmp = poTempBmp
LOCAL loTempGfx as xfcGraphics
m.loTempGfx = .Graphics.FromImage(m.loBmp)
m.loTempGfx.Clear(.Color.Transparent)
m.loTempGfx.SmoothingMode = .Drawing2D.SmoothingMode.AntiAlias
* Create a GraphicsPath object.
LOCAL loTempPath as xfcGraphicsPath
m.loTempPath = .Drawing2D.GraphicsPath.New()
LOCAL loRect as xfcRectangle
LOCAL loRect2 as xfcRectangle
LOCAL lnRatio
m.lnRatio = This.DonutRatio
m.loRect = .Rectangle.New(0, 0, m.tnWidth, m.tnHeight)
m.loRect2 = .Rectangle.New( ;
(m.tnWidth * (1 - m.lnRatio) / 2), ;
(m.tnHeight * (1 - m.lnRatio) / 2), ;
m.tnWidth * m.lnRatio, ;
m.tnHeight * m.lnRatio)
LOCAL loPoint0 as xfcPointF
LOCAL loPoint1 as xfcPointF
LOCAL loPoint2 as xfcPointF
LOCAL loPoint3 as xfcPointF
* Obtaining the needed points
m.loTempPath.AddArc(m.loRect, m.tnStart, 0.0001)
m.loPoint0 = m.loTempPath.GetLastPoint()
m.loTempPath.AddArc(m.loRect2, m.tnStart, 0.0001)
m.loPoint3 = m.loTempPath.GetLastPoint()
m.loTempPath.AddArc(m.loRect, m.tnStart, m.tnSweep)
m.loPoint1 = m.loTempPath.GetLastPoint()
m.loTempPath.AddArc(m.loRect2, m.tnStart, m.tnSweep)
m.loPoint2 = m.loTempPath.GetLastPoint()
m.loPoint4 = .Point.New(m.loPoint3.X, m.loPoint3.Y + m.ln3d)
m.loPoint5 = .Point.New(m.loPoint0.X, m.loPoint0.Y + m.ln3d)
m.loPoint6 = .Point.New(m.loPoint1.X, m.loPoint1.Y + m.ln3d)
* Prepare the Main Path
LOCAL loPath as xfcGraphicsPath
m.loPath = .Drawing2D.GraphicsPath.New()
m.loPath.StartFigure()
m.loPath.AddLine(m.loPoint0.X, m.loPoint0.Y, m.loPoint3.X, m.loPoint3.Y)
m.loPath.AddArc(m.loRect2, m.tnStart, m.tnSweep)
m.loPath.StartFigure()
m.loPath.AddArc(m.loRect, m.tnStart, m.tnSweep)
m.loPath.AddLine(m.loPoint1.X, m.loPoint1.Y, m.loPoint2.X, m.loPoint2.Y)
IF m.ln3d > 0
* Create a new Path for the 3D
LOCAL lo3DPath as xfcPath
m.lo3DPath = m.loPath.Clone()
LOCAL loMatrix as xfcMatrix
m.loMatrix = .Drawing2D.Matrix.New()
m.loMatrix.Translate(0, + 1)
* Prepare the polygon points for the final part of the slice
DIMENSION m.laPointsB(4)
m.laPointsB(1) = m.loPoint1
m.laPointsB(2) = m.loPoint2
m.laPointsB(3) = .Point.New(m.loPoint2.X, m.loPoint2.Y + m.ln3d)
m.laPointsB(4) = m.loPoint6
* If the slice ends in the left side, draw the polygon before the top face of the slice
IF BETWEEN(m.lnFinalAngle, 90, 270)
m.loTempGfx.DrawPolygon(m.loPen, @m.laPointsB)
ENDIF
LOCAL n
FOR m.n = 1 TO m.ln3d - 1
m.lo3DPath.Transform(m.loMatrix)
m.loTempGfx.FillPath(m.lo3dBrush, m.lo3DPath)
ENDFOR
* Draw the side Polygons
* Draw polygon at the beginning of the donut
IF m.tnStart > 90 AND m.tnStart < 270
DIMENSION m.laPoints(4)
m.laPoints(1) = m.loPoint0
m.laPoints(2) = m.loPoint5
m.laPoints(3) = m.loPoint4
m.laPoints(4) = m.loPoint3
m.loTempGfx.DrawPolygon(m.loPen, @m.laPoints)
ENDIF
* Draw polygon at the end of the donut
IF m.lnFinalAngle < 90 OR m.lnFinalAngle > 270
m.loTempGfx.DrawPolygon(m.loPen, @m.laPointsB)
ENDIF
ENDIF
* Draw the path
m.loTempGfx.FillPath(m.loMainBrush, m.loPath)
m.loTempGfx.DrawPath(This._oBorderPen, m.loPath)
m.loBmp.ApplyColorMatrix(poClrMatrix)
m.loGfx.DrawImage(m.loBmp, m.tnX, m.tnY)
ENDWITH
ENDIF
RETURN
ENDPROC
PROCEDURE _drawlegendinbar
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tnIndex
* Zero values in Stacked charts will not have space for drawing legends
* so we'll ignore this case
IF This._Stacked AND m.tnValue = 0
RETURN
ENDIF
This.CurrIndex = This._nIndex
LOCAL lnLeftMargin
m.lnLeftMargin = This._yAxisWidth + This._LeftOffset
*!* Other available properties
*!* This.CurrValue
*!* This.CurrLegend
*!* This.CurrObjType
*!* This.CurrRecno
*!* This.CurrColumn
IF This.Fields(This._ChartIndex).ShowValuesOnShape AND This.ShowValuesOnShapes
LOCAL lcExpr
m.lcExpr = This.ShapeLegendExpression
IF (VARTYPE(m.lcExpr) = "C") AND (NOT EMPTY(m.lcExpr))
This.ShapeLegend._Value = EVALUATE(m.lcExpr)
ELSE
IF This._SumRow AND This.ShowPercentages
* Show percentages as values
DO CASE
CASE EMPTY(This.ShapeLegend.Format) AND EMPTY(This.ShapeLegendExpression)
This.ShapeLegend._ForceFormat = ;
This._GetFieldType(This.SourceAlias, EVALUATE("This.Fields(This.ChartRow).FieldValue"), .T.) + "%"
CASE NOT "%" $ This.ShapeLegend.Format
This.ShapeLegend._ForceFormat = This.ShapeLegend.Format + "%"
ENDCASE
LOCAL lnValue
m.lnValue = ROUND(m.tnValue / This.ChartSum * 100,0)
This.ShapeLegend._Value = m.lnValue
ELSE
This.ShapeLegend._Value = m.tnValue
ENDIF
ENDIF
LOCAL lnAlign, lnDirection
m.lnAlign = This.ShapeLegend.Alignment
*!* IF This._InvertShapeLegendAlignment = .T.
*!* DO CASE
*!* CASE lnAlign = 0 && Left
*!* lnAlign = 1 && Right
*!* CASE lnAlign = 1 && Right
*!* lnAlign = 0 && Left
*!* OTHERWISE
*!* ENDCASE
*!* ENDIF
m.lnDirection = This.BarLegendDirection
IF m.lnDirection = 0 && Horizontal
* Draw the Values inside the shapes
IF This._Orientation = 1 && Vertical
IF (m.tnHeight < This.ShapeLegend._Height) AND (NOT This._Stacked)
LOCAL y0
m.y0 = This.ChartCanvas.Height - This._XAxisHeight + 1
m.tnY = m.y0 - This.ShapeLegend._Height
ENDIF
DO CASE
CASE This.ShapeLegend.Rotation <> 0 AND This.BarLegendType = 1
m.tnY = m.tnY - This.ShapeLegend._Height - 2
This.ShapeLegend._DrawString(m.tnX + m.tnWidth / 2, m.tnY)
CASE m.lnAlign = 0 && Left
This.ShapeLegend._DrawString(m.tnX, m.tnY)
CASE m.lnAlign = 1 && Right
This.ShapeLegend._DrawString(m.tnX + m.tnWidth, m.tnY)
CASE m.lnAlign = 2 && Center
This.ShapeLegend._DrawString(m.tnX + m.tnWidth / 2, m.tnY)
OTHERWISE
ENDCASE
ELSE && This._Orientation = 2 && Horizontal
DO CASE
CASE m.lnAlign = 2 && Center
* This.ShapeLegend._DrawString(tnX + tnWidth / 2, tnY)
IF This.ShapeLegend._Width > m.tnWidth && force left
This.ShapeLegend.Alignment = 0
This.ShapeLegend._DrawString(m.tnX, m.tnY)
This.ShapeLegend.Alignment = 2
ELSE
This.ShapeLegend._DrawString(m.tnX + m.tnWidth / 2, m.tnY)
ENDIF
CASE m.lnAlign = 0 AND m.tnValue >= 0 && Left
This.ShapeLegend._DrawString(m.tnX, m.tnY)
CASE m.lnAlign = 1 AND m.tnValue >= 0 && Right
IF This.ShapeLegend._Width > m.tnWidth && force left
This.ShapeLegend.Alignment = 0
This.ShapeLegend._DrawString(m.tnX, m.tnY)
This.ShapeLegend.Alignment = 1
ELSE
This.ShapeLegend._DrawString(m.tnX + m.tnWidth, m.tnY)
ENDIF
CASE m.lnAlign = 1 AND m.tnValue < 0 && Force Left
This.ShapeLegend.Alignment = 0
This.ShapeLegend._DrawString(m.tnX, m.tnY)
This.ShapeLegend.Alignment = 1
CASE m.lnAlign = 0 AND m.tnValue < 0 && Force Right
This.ShapeLegend.Alignment = 1
This.ShapeLegend._DrawString(m.tnX + m.tnWidth, m.tnY)
This.ShapeLegend.Alignment = 0
OTHERWISE
ENDCASE
ENDIF
ELSE && BarLegendDirection = 1 && Vertical
IF m.lnDirection = 2 && Invert Direction
LOCAL lnRotCenter
m.lnRotCenter = This.ShapeLegend.RotationCenter
This.ShapeLegend.RotationCenter = m.lnRotCenter + 180
ENDIF
IF m.tnValue >= 0 OR m.lnAlign = 2
This.ShapeLegend._DrawString(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .T.)
ELSE
IF m.lnAlign = 0
This.ShapeLegend.Alignment = 1
ELSE
This.ShapeLegend.Alignment = 0
ENDIF
This.ShapeLegend._DrawString(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .T.)
This.ShapeLegend.Alignment = m.lnAlign
ENDIF
IF m.lnDirection = 2 && Invert Direction
This.ShapeLegend.RotationCenter = m.lnRotCenter
ENDIF
ENDIF
ENDIF
ENDPROC
PROCEDURE _drawlinechart
LOCAL laPoints[1], ;
laPointsI[1], ;
lcType as String, ;
lnAdjust as Number, ;
lnBarHeight as Number, ;
lnBarWidth as Number
SELECT(This._DataCursor)
LOCAL lnLeftMargin, lnWidth, lnHeight, lnValue
LOCAL lnBetween, lnBetween2, n, i, j, lnMaxValue, lnPointHeight, x1, y1, ln3D, lnChartsCount
LOCAL llIsNull, lnYBase
LOCAL lnTipPixels, lnType2, lnAlignment, lnRecs
LOCAL lnMaxValue2
m.lnAlignment = This.ShapeLegend.Alignment
m.lnRecs = This._nRecords
m.lnTipPixels = This._TipPixels
m.lnLeftMargin = This._YAxisWidth + This._LeftOffset
m.ln3D = This._3D
m.lnChartsCount = This.ChartsCount
* Calculate the maximum width of the chart
m.lnWidth = This.ChartCanvas.Width - This._YAxisWidth - This._LeftOffset - (m.ln3D * m.lnChartsCount) - This._RightOffset - THIS._yAxisWidth2
m.lnHeight = This.ChartCanvas.Height - This._XAxisHeight - This._TopOffSet - (m.ln3D * m.lnChartsCount)
IF m.lnWidth < 10 OR m.lnHeight < 10 OR m.lnRecs < 1
RETURN
ENDIF
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
* Get the maximum value of the chart
m.lnMaxValue = This._ScaleRange
m.lnMaxValue2 = This._ScaleRange2
LOCAL loBrush as xfcBrush
IF This.BrushType = 1
m.loBrush = "This._o3dbrush"
ELSE
m.loBrush = "This._oMainBrush"
ENDIF
* Prepare array of points
* 1st column is the current point object
* 2nd column is the global index number for the coordinates array
LOCAL lnArrayLength
IF INLIST(This.ChartType, 5, 18) && Line
m.lnArrayLength = m.lnRecs
ELSE && Area
m.lnArrayLength = m.lnRecs + 3
ENDIF
DIMENSION m.laPoints(m.lnArrayLength)
DIMENSION m.laPointsI(m.lnArrayLength)
WITH _Screen.System.Drawing
FOR m.i = 1 TO m.lnChartsCount
This._ChartIndex = m.i
m.lnType2 = EVALUATE("This.Fields(i).ChartType")
m.lnAdjust = (m.ln3D * (m.lnChartsCount - m.i ))
m.lnYBase = This._TopOffSet + m.lnHeight - m.lnAdjust + (m.ln3D * m.lnChartsCount)
* If MultiChart mode, the chart needs to start half a position further
IF This.Multichart AND This.MultiChartMargin
m.lnBetween = m.lnWidth / (m.lnRecs)
ELSE
m.lnBetween = m.lnWidth / (m.lnRecs - IIF(m.lnRecs = 1, 0, 1))
ENDIF
m.lnBetween2 = m.lnBetween + m.lnAdjust
&& the X distance between the points to be used when drawing the legends in the X axis
SCAN
m.n = RECNO()
m.x1 = m.lnLeftMargin + (m.lnBetween * (m.n - 1)) + ;
m.lnAdjust + IIF(This.Multichart AND This.MultiChartMargin, ;
(m.lnBetween / 2), 0)
m.lnValue = This._GetValue(m.i, .T.)
m.llIsNull = ISNULL(m.lnValue)
IF m.llIsNull
m.lnValue = 0
ENDIF
IF This.Fields(m.i).AxisIndex = 2 AND This.ChartType = 18
m.lnValue = m.lnValue + This._ScaleAdjust2
m.lnPointHeight = m.lnValue / m.lnMaxValue2 * m.lnHeight
m.y1 = m.lnYBase - m.lnPointHeight
This._aPoints(m.n, 1) = m.x1 + m.ln3D
This._aPoints(m.n, 2) = m.y1
This._aPoints(m.n, 3) = m.lnValue - This._ScaleAdjust2 && Restore the original value
ELSE && This.Fields(i).AxisIndex = 1
IF m.llIsNull AND (m.n > 1) AND (This.LineIgnoreNULLs) && Special situation to Tamar Granor
This._aPoints(m.n, 1) = This._aPoints(m.n - 1, 1)
This._aPoints(m.n, 2) = This._aPoints(m.n - 1, 2)
This._aPoints(m.n, 3) = This._aPoints(m.n - 1, 3)
* Extra checking to avoid drawing a line if the starting values are NULLs
IF VARTYPE(m.laPoints(m.n - 1)) = "L"
m.laPoints(RECNO()) = .F.
ELSE
m.laPoints(RECNO()) = .Point.New(This._aPoints(m.n, 1) - m.ln3D, This._aPoints(m.n, 2))
ENDIF
LOOP
ENDIF
m.lnValue = m.lnValue + This._ScaleAdjust
m.lnPointHeight = m.lnValue / m.lnMaxValue * m.lnHeight
m.y1 = m.lnYBase - m.lnPointHeight
This._aPoints(m.n, 1) = m.x1 + m.ln3D
This._aPoints(m.n, 2) = m.y1
This._aPoints(m.n, 3) = m.lnValue - This._ScaleAdjust && Restore the original value
ENDIF
m.laPoints(RECNO()) = IIF(m.llIsNull, .F., .Point.New(m.x1, m.y1))
ENDSCAN
GO TOP
* Draw the vertical line only for the first line
IF m.i = 1
This._DrawVerticalLineBack()
ENDIF
DO CASE
*-- 2010-11-26
*-- Fix by Paulo Henrique de Almeida (Casion)
CASE m.lnType2 = 3 && Single Bar
m.lnBarWidth = (m.lnWidth - (m.lnRecs - 1) * This.BarsSpaceBetween) / m.lnRecs
FOR m.n = 1 TO m.lnRecs
IF VARTYPE(m.laPoints(m.n)) <> "O"
LOOP
ENDIF
* changed by paulo henrique
m.x1 = This._aPoints(m.n, 1) - m.lnBarWidth / 2 - m.ln3D
m.y1 = This.Height - ((0 - This._MinScale) / m.lnMaxValue * m.lnHeight) - This._XAxisHeight
m.lnValue = This._aPoints(m.n, 3)
m.lnBarHeight = m.y1 - This._aPoints(m.n, 2)
m.y1 = min(m.y1, This._aPoints(m.n, 2))
* end - changed by paulo henrique
This._CurrentRow = m.n
This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue)
m.laPointsI(m.n) = This._nIndex
ENDFOR
*--
CASE This.ChartType = 4 OR m.lnType2 = 4 && Point / Secondary Point
FOR m.n = 1 TO m.lnRecs
IF VARTYPE(m.laPoints(m.n)) <> "O"
LOOP
ENDIF
This._DrawShape(m.laPoints(m.n).X, m.laPoints(m.n).Y, This._aPoints(m.n, 3))
m.laPointsI(m.n) = This._nIndex
This._CurrentRow = m.n
ENDFOR
OTHERWISE && ChartType <> 4 - Line or Area
IF This.ChartType = 6 && Area
This._PrepareBrushes(0, 0, This.ChartCanvas.Width, This.ChartCanvas.Height, .F., m.i)
ENDIF
LOCAL laPolygon(4)
LOCAL laPolygonB(4)
IF m.ln3D = 0
* Create pen.
LOCAL loLinePen as xfcPen
LOCAL lnColor
IF This.BrushType = 3 && Monochrome
m.lnColor = 0
m.loLinePen = .Pen.New(This._oClrBlack, 3)
m.loLinePen.DashStyle = m.i - 1 && _Screen.System.Drawing.Drawing2D.DashStyle.Dash
ELSE
m.lnColor = This.aColors(m.i)
m.loLinePen = .Pen.New(.Color.FromRGB(m.lnColor), 2)
ENDIF
FOR m.n = 1 TO m.lnRecs - 1
This._CurrentRow = m.n
m.lcType = VARTYPE(m.laPoints(m.n)) + VARTYPE(m.laPoints(m.n + 1))
DO CASE
CASE m.lcType = "LO" OR m.lcType = "LL"
LOOP
CASE m.lcType = "OL"
m.loGfx.Drawline(m.loLinePen, m.laPoints(m.n).X, m.laPoints(m.n).Y, m.laPoints(m.n).X + 1, m.laPoints(m.n).Y + 1)
This._UpdateCoordinates("Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ;
This._aPoints(m.n, 3), m.n)
m.laPointsI(m.n) = This._nIndex
LOOP
OTHERWISE
m.loGfx.Drawline(m.loLinePen, m.laPoints(m.n), m.laPoints(m.n + 1))
ENDCASE
IF This.ChartType = 6 && Area
* Draw the area
m.laPolygonB(1) = m.laPoints(m.n)
m.laPolygonB(2) = m.laPoints(m.n + 1)
m.laPolygonB(3) = .Point.New(m.laPolygonB(2).X, m.lnYBase)
m.laPolygonB(4) = .Point.New(m.laPolygonB(1).X, m.lnYBase)
m.loGfx.FillPolygon(This._oMainBrush, @m.laPolygonB)
IF This.AreaDrawBorders
m.loGfx.DrawPolygon(This._oBorderPen, @m.laPolygonB)
ENDIF
ENDIF
This._UpdateCoordinates("Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ;
This._aPoints(m.n, 3))
m.laPointsI(m.n) = This._nIndex
ENDFOR
IF VARTYPE(m.laPoints(m.n)) = "O"
This._CurrentRow = m.n
This._UpdateCoordinates( ;
"Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, ;
m.lnTipPixels, m.lnTipPixels, This._aPoints(m.n, 3))
m.laPointsI(m.n) = This._nIndex
ENDIF
* Draw the shapes after (over) the lines
IF This.LineCaps = .T. AND INLIST(This.ChartType, 5, 18) && Line
FOR m.j = 1 TO m.lnRecs
IF VARTYPE(m.laPoints(m.j)) <> "O" OR ;
VARTYPE(m.laPoints(m.j).X) + VARTYPE(m.laPoints(m.j).Y) <> "NN"
LOOP
ENDIF
This._DrawShape(m.laPoints(m.j).X, m.laPoints(m.j).Y, This._aPoints(m.j, 3))
m.laPointsI(m.n) = This._nIndex
This._CurrentRow = m.j
ENDFOR
ENDIF
ELSE && m.ln3D <> 0
* Store a big area brush that will be used for the main area part of the shapes
LOCAL loAreaBrush, llDrawPointLine
m.loAreaBrush = This._oMainBrush
FOR m.n = 1 TO m.lnRecs - 1
This._CurrentRow = m.n
m.lcType = VARTYPE(m.laPoints(m.n)) + VARTYPE(m.laPoints(m.n + 1))
DO CASE
CASE m.lcType = "LO" OR m.lcType = "LL"
LOOP
CASE m.lcType = "OL"
m.llDrawPointLine = .T.
OTHERWISE
m.llDrawPointLine = .F.
ENDCASE
IF This.ChartType = 6 ; && Area
AND "L" $ m.lcType
IF m.lcType = "OL"
This._UpdateCoordinates("Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ;
This._aPoints(m.n, 3))
m.laPointsI(m.n) = This._nIndex
ENDIF
LOOP
ENDIF
IF INLIST(This.ChartType, 5, 18) OR (This.ChartType = 6 AND This.Area3dTop)
m.laPolygon(1) = m.laPoints(m.n)
m.laPolygon(2) = .Point.New(m.laPoints(m.n).X + m.ln3D, m.laPoints(m.n).Y - m.ln3D)
IF m.llDrawPointLine
LOCAL lnColor, loLinePen as xfcPen
m.lnColor = This.aColors(m.i)
m.loLinePen = .Pen.New(.Color.FromRGB(m.lnColor), 2)
m.loGfx.Drawline(m.loLinePen, m.laPolygon(1), m.laPolygon(2))
This._UpdateCoordinates("Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ;
This._aPoints(m.n, 3))
m.laPointsI(m.n) = This._nIndex
LOOP
ENDIF
m.laPolygon(3) = .Point.New(m.laPoints(m.n + 1).X + m.ln3D, m.laPoints(m.n + 1).Y - m.ln3D)
m.laPolygon(4) = m.laPoints(m.n + 1)
This._PrepareBrushes(m.laPoints(m.n).X, m.laPoints(m.n).Y - m.ln3D, ;
m.laPoints(m.n + 1).X + m.ln3D - m.laPoints(m.n).X, ;
MAX(2, ABS(m.laPoints(m.n).Y - m.laPoints(m.n + 1).Y)), .F., m.i)
m.loGfx.FillPolygon(This._oMainBrush, @m.laPolygon)
m.loGfx.DrawPolygon(This._oBorderPen, @m.laPolygon)
ENDIF
IF This.ChartType = 6 && Area
* Draw the area
m.laPolygonB(1) = m.laPoints(m.n)
m.laPolygonB(2) = m.laPoints(m.n + 1)
m.laPolygonB(3) = .Point.New(m.laPolygonB(2).X, m.lnYBase)
m.laPolygonB(4) = .Point.New(m.laPolygonB(1).X, m.lnYBase)
m.loGfx.FillPolygon(m.loAreaBrush, @m.laPolygonB)
IF This.AreaDrawBorders
m.loGfx.DrawPolygon(This._oBorderPen, @m.laPolygonB)
ENDIF
* Draw the right 3d edge of the Area
IF This.Area3dTop
m.laPolygonB(1) = .Point.New(m.laPolygonB(2).X + m.ln3D, m.laPolygonB(2).Y - m.ln3D)
m.laPolygonB(4) = .Point.New(m.laPolygonB(3).X + m.ln3D, m.laPolygonB(3).Y - m.ln3D)
m.loGfx.FillPolygon(This._o3dbrush, @m.laPolygonB)
m.loGfx.DrawPolygon(This._oBorderPen, @m.laPolygonB)
ENDIF
ENDIF && ChartType = 6 - Area
This._UpdateCoordinates("Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ;
This._aPoints(m.n, 3))
m.laPointsI(m.n) = This._nIndex
ENDFOR
This._CurrentRow = m.n
IF VARTYPE(m.laPoints(m.n)) = "O"
This._UpdateCoordinates("Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ;
This._aPoints(m.n, 3))
m.laPointsI(m.n) = This._nIndex
ENDIF
ENDIF && m.ln3D = 0
ENDCASE
* Reset Row counter
This._CurrentRow = 0
* Adjust _aPoints Array to show the information in the correct position
FOR m.n = 1 TO m.lnRecs
This._aPoints(m.n, 1) = This._aPoints(m.n, 1) - m.ln3D
ENDFOR
IF This.ShowValuesOnShapes AND This.Fields(m.i).ShowValuesOnShape
LOCAL lnIndex
* Draw Legends above the points
FOR m.n = 1 TO m.lnRecs
* Adjust _aPoints Array to show the information in the correct position
This._aPoints(m.n, 1) = This._aPoints(m.n, 1) - m.ln3D
IF VARTYPE(m.laPoints(m.n)) = "L"
LOOP
ENDIF
m.x1 = This._aPoints(m.n, 1)
m.y1 = This._aPoints(m.n, 2)
m.lnIndex = m.laPointsI(m.n)
This._DrawShapeLegend(m.x1, m.y1, m.lnIndex)
ENDFOR
ENDIF
ENDFOR
This._DrawXAxisLegend(.F., m.lnBetween2)
ENDWITH
This.ShapeLegend.Alignment = m.lnAlignment
RETURN
ENDPROC
PROCEDURE _drawpiechart
LOCAL lnDetachAngle as Number, ;
lnTempStart as Number, ;
lnTempSweep as Number, x1, y1
SELECT(This._DataCursor)
LOCAL lnDetachPixels, lnStart, lnSweep, lnAngle, ln3D, lnValue
LOCAL lnWidth, lnHeight, lnX, lnY, lnTotal, lnMaxWidth, lnMaxHeight
m.lnDetachPixels = This.PieDetachPixels
m.lnMaxWidth = This.ChartCanvas.Width - This._LeftOffset - This._RightOffset - (lnDetachPixels * 2)
m.lnMaxHeight = This.ChartCanvas.Height - (This.Margin * 2) - This.MarginBottom - ;
This.MarginTop - This._TitleHeight - This._3d - ;
(lnDetachPixels * 2) - ;
IIF(This.LegendPosition > 4, This._LegendHeight, 0)
m.lnWidth = MIN(lnMaxWidth, lnMaxHeight)
m.lnHeight = m.lnWidth
IF NOT This.PieForceCircle
* Adjust the maximum width in order to ensure that the chart will retain
LOCAL lnFactor
m.lnFactor = 0.80
IF m.lnMaxWidth <= m.lnWidth / m.lnFactor
m.lnWidth = lnMaxWidth
ELSE
m.lnWidth = m.lnWidth / m.lnFactor
ENDIF
ENDIF
m.ln3D = This._3d
IF This.PieCompensateAngles
m.lnWidth = m.lnMaxWidth
ELSE
ENDIF
IF m.lnWidth <= 10 OR ;
lnHeight <= 10 OR ;
lnHeight <= ln3D
RETURN
ENDIF
* Calculate the chart basic positions
lnX = lnDetachPixels + This.Margin + This._LeftOffset + ((lnMaxWidth - m.lnWidth) / 2)
lnY = This.Margin + This._TopOffSet + ((lnMaxHeight - m.lnHeight) / 2) + lnDetachPixels
lnTotal = This.ChartSum
IF NOT This.PieEnhancedDrawing && Draws without taking care of slices edges
* Prepare the Gdi+ objects
WITH _Screen.System.Drawing
PRIVATE poTempBmp as xfcBitmap
PRIVATE poClrMatrix as xfcColorMatrix
poTempBmp = .Bitmap.New(m.lnWidth + m.ln3D + 2, m.lnHeight + m.ln3D + 2)
poClrMatrix = .Imaging.ColorMatrix.New()
poClrMatrix.Matrix33 = This.AlphaChannel / 255
ENDWITH
ENDIF
LOCAL laLegends(This._nRecords + 1, 3)
LOCAL lnRec, llHidden, llDrawLegend
LOCAL lnPixelsOut
llDrawLegend = This.ShowValuesonShapes
lnRec = 1
This._ChartIndex = This.ChartRow
This._Pie1stDetached = .F.
IF This.PieDirection = 1 && Anticlockwise
SET ORDER TO Revert
ENDIF
* Draw the pie
* Draw the RIGHT side of the pie
lnStart = 270
SCAN FOR lnStart < 450
x1 = lnX
y1 = lnY
* Calculate Start point and Sweep
lnValue = This._GetValue(This.ChartRow)
IF lnValue <= 0
LOOP
ENDIF
lnSweep = lnValue / lnTotal * 360
IF lnSweep > 359.99
lnSweep = 359.99
ENDIF
llHidden = lSliceHidden
IF lDetach = .T.
IF lnRec = 1
This._Pie1stDetached = .T.
This._PieX0 = x1
This._PieY0 = y1
ENDIF
IF RECNO() = This._PieAnimatedRec
lnPixelsOut = This._PieAnimationPix
ELSE
lnPixelsOut = lnDetachPixels
ENDIF
lnTempStart = lnStart
lnTempSweep = lnSweep
This._AdjustStartSweep(@lnTempStart, @lnTempSweep, m.lnWidth, m.lnHeight)
lnDetachAngle = 360 - (lnTempStart + (lnTempSweep / 2))
x1 = lnX + (COS(DTOR(lnDetachAngle)) * lnPixelsOut)
y1 = lnY - (SIN(DTOR(lnDetachAngle)) * lnPixelsOut)
ELSE
x1 = lnX
y1 = lnY
ENDIF
IF lnStart + lnSweep > 450
EXIT
ENDIF
IF NOT llHidden
IF This.ChartType = 1 && Pie
This._DrawSlice(x1, y1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnValue)
ELSE && 2 - Doughnut
This._DrawDoughnutSlice(x1, y1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnValue)
ENDIF
IF llDrawLegend
This._PrepareLegendinSlice(@x1, @y1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnValue)
laLegends(lnRec, 1) = x1
laLegends(lnRec, 2) = y1
laLegends(lnRec, 3) = lnValue
lnRec = lnRec + 1
ENDIF
ENDIF
lnStart = lnStart + lnSweep
ENDSCAN
* Draw the LEFT side of the pie
GO BOTTOM
lnStart = 270
DO WHILE lnStart >= 90
x1 = lnX
y1 = lnY
* Calculate Start point and Sweep
lnValue = This._GetValue(This.ChartRow)
IF lnValue <= 0
IF BOF()
EXIT
ENDIF
SKIP -1
IF BOF()
EXIT
ENDIF
LOOP
ENDIF
lnSweep = lnValue / lnTotal * 360
IF lnSweep > 359.99
lnSweep = 359.99
ENDIF
lnStart = lnStart - lnSweep
llHidden = lSliceHidden
IF lDetach = .T.
lnTempStart = lnStart
lnTempSweep = lnSweep
IF lnStart + lnSweep >= 269.9
This._Pie1stDetached = .T.
This._PieX0 = x1
This._PieY0 = y1
ENDIF
IF RECNO() = This._PieAnimatedRec
lnPixelsOut = This._PieAnimationPix
ELSE
lnPixelsOut = lnDetachPixels
ENDIF
This._AdjustStartSweep(@lnTempStart, @lnTempSweep, m.lnWidth, m.lnHeight)
lnDetachAngle = 360 - (lnTempStart + (lnTempSweep / 2))
x1 = lnX + (COS(DTOR(lnDetachAngle)) * lnPixelsOut)
y1 = lnY - (SIN(DTOR(lnDetachAngle)) * lnPixelsOut)
ENDIF
IF NOT llHidden
IF This.ChartType = 1 && Pie
This._DrawSlice(x1, y1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnValue)
ELSE && 2 - Doughnut
This._DrawDoughnutSlice(x1, y1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnValue)
ENDIF
IF llDrawLegend
This._PrepareLegendinSlice(@x1, @y1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnValue)
laLegends(lnRec, 1) = x1
laLegends(lnRec, 2) = y1
laLegends(lnRec, 3) = lnValue
lnRec = lnRec + 1
ENDIF
ENDIF
SKIP -1
IF BOF()
EXIT
ENDIF
ENDDO
* Draw the legends at the end of the process in order to avoid
* a slice hiding a legend
IF This.Fields(This._ChartIndex).ShowValuesOnShape
IF llDrawLegend
LOCAL lnOrigAlign, n
lnOrigAlign = This.ShapeLegend.Alignment
This.ShapeLegend.Alignment = 2 && Force Center
FOR n = 1 TO lnRec - 1
TRY
LOCAL lcExpr
lcExpr = This.ShapeLegendExpression
IF (VARTYPE(lcExpr) = "C") AND (NOT EMPTY(lcExpr))
*!* Other available properties
*!* This.CurrValue
*!* This.CurrLegend
*!* This.CurrObjType
*!* This.CurrRecno
*!* This.CurrColumn
This.CurrIndex = n
lnValue = EVALUATE(lcExpr)
ELSE
IF This.PieShowPercent
DO CASE
CASE EMPTY(This.ShapeLegend.Format) AND EMPTY(lcExpr)
This.ShapeLegend._ForceFormat = ;
This._GetFieldType(This.SourceAlias, EVALUATE("This.Fields(This.ChartRow).FieldValue"), .T.) + "%"
CASE NOT "%" $ This.ShapeLegend.Format
This.ShapeLegend._ForceFormat = This.ShapeLegend.Format + "%"
ENDCASE
lnValue = (laLegends(n, 3) / lnTotal) * 100
ELSE
lnValue = laLegends(n, 3)
ENDIF
ENDIF
CATCH
ERROR "Invalid Expression in 'ShapeLegendExpressionProperty' !"
ENDTRY
This.ShapeLegend._Value = lnValue
x1 = laLegends(n, 1)
IF VARTYPE(x1) <> "N"
EXIT
ENDIF
y1 = laLegends(n, 2)
* Draw the Text
This.ShapeLegend._DrawString(x1, y1)
ENDFOR
This.ShapeLegend._ForceFormat = ""
This.ShapeLegend.Alignment = lnOrigAlign
ENDIF
ENDIF
IF This.PieDirection = 1 && Anticlockwise
SET ORDER TO
ENDIF
ENDPROC
PROCEDURE _drawscale
LPARAMETERS toPen, tnAxisIndex
LOCAL lnScaleNumber as Number, ;
lnScaleWidth as Number, ;
lnThisScale as Number, ;
lnValue as Number, ;
lnWidth as Number, x
m.tnAxisIndex = EVL(m.tnAxisIndex, 1)
* Draw the scale in the Y Axis
Local ln3D, lnHeight, lnMargin, lnScaleValue, llShowLineZero
IF This.ChartType = 17 && Paired
m.llShowLineZero = .F.
ELSE
m.llShowLineZero = This.ShowLineZero
ENDIF
IF This._DeepChart && Point, Line or Area
m.ln3D = This._3D * This.ChartsCount
ELSE
m.ln3D = This._3D
ENDIF
LOCAL lnMaxValue, lnScale, lnScaleAdjust, lnMinScale, lnMaxScale
m.lnMaxValue = IIF(m.tnAxisIndex = 1, This._ScaleRange, This._ScaleRange2)
m.lnScale = IIF(m.tnAxisIndex = 1, This._Scale, This._Scale2)
m.lnScaleAdjust = IIF(m.tnAxisIndex = 1, This._ScaleAdjust, This._ScaleAdjust2)
m.lnMinScale = IIF(m.tnAxisIndex = 1, This._MinScale, This._MinScale2)
m.lnMaxScale = IIF(m.tnAxisIndex = 1, This._MaxScale, This._MaxScale2)
LOCAL loGfx AS xfcGraphics
m.loGfx = This.oGfx
LOCAL loBackBrush AS xfcSolidBrush
LOCAL loBackPen AS xfcPen
LOCAL loBlackPen AS xfcPen
LOCAL llDrawBack, lnOneScale, lnxWidth
m.loBlackPen = This._oBlackPen
m.llDrawBack = .T.
This.ScaleLegend._Setup()
If This._Orientation = 1 && Vertical
Local lnRectColor, lnLineColor
If This.BrushType = 3 && Monochrome
m.lnRectColor = Rgb(255, 255, 255) && White
m.lnLineColor = 0 && Black
Else
m.lnRectColor = This.ScaleBackColor
m.lnLineColor = This.ScaleLineColor
Endif
With _Screen.System.Drawing
m.loBackBrush = .SolidBrush.New(.Color.FromARGB(This.ScaleBackAlpha, m.lnRectColor))
This._oBlackPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, m.lnLineColor), This.ScaleBackLinesWidth - 1)
Endwith
Local lnDashValue
m.lnDashValue = This.ScaleBackLinesDash
If m.lnDashValue > 0
This._oBlackPen.DashStyle = m.lnDashValue && _Screen.System.Drawing.Drawing2D.DashStyle.Dash
Endif
m.lnHeight = This.Height - This._XAxisHeight - This._TopOffSet - m.ln3D
m.lnOneScale = m.lnScale / m.lnMaxValue * m.lnHeight
m.lnxWidth = This.Width - This._LeftOffset - This._RightOffset - This._yAxisWidth - m.ln3D - This._yAxisWidth2
Local x0, x1, y0, y1, lnScaleHeight, N, Y
m.y0 = This.Height - This._XAxisHeight
m.x0 = IIF(m.tnAxisIndex = 1, ;
This._yAxisWidth + This._LeftOffset, ;
This.ChartCanvas.Width - This._RightOffset - m.ln3D + 2 + 2 - This._yAxisWidth2)
****************************************************************
* Jim Nelson 10/10/08
*
* Loop now calls method GetScaleValue (and its cousin GetScaleLegend) to get the
* scale values and associated legends. lnScaleNumber = 0 returns highest scale
* Save original Alignment settings
LOCAL lnOrigAlignment, lcOrigScaleFormat
m.lnOrigAlignment = This.ScaleLegend.Alignment
m.lcOrigScaleFormat = This.ScaleLegend._ForceFormat
* CCHALOM 2013-02-21
* Fix in getting a nice Scale legend format for both axes
* New properties inserted: _ScaleLegAxis1ForceFormat , _ScaleLegAxis2ForceFormat
This.ScaleLegend._ForceFormat = IIF(m.tnAxisIndex = 1, This._ScaleLegAxis1ForceFormat, This._ScaleLegAxis2ForceFormat)
For m.lnScaleNumber = 0 To 1000
m.lnValue = This.GetScaleValue (m.lnScaleNumber, m.tnAxisIndex)
If "N" # Vartype(m.lnValue)
Exit
Endif
m.lnScaleHeight = (m.lnValue - m.lnMinScale) / m.lnMaxValue * m.lnHeight
m.Y = This.Height - m.lnScaleHeight - This._XAxisHeight
m.x1 = IIF(m.tnAxisIndex = 1, ;
This._yAxisWidth + This._LeftOffset - 7, ;
This.ChartCanvas.Width - This._RightOffset - m.ln3D + 6 - This._yAxisWidth2)
m.y1 = m.Y - (This._ScaleH/2)
m.lnScaleValue = m.lnValue - m.lnScaleAdjust
* 2nd Y Axis
IF m.tnAxisIndex = 1
This.ScaleLegend.Alignment = 1 && Force Right alignment
ELSE
This.ScaleLegend.Alignment = 0 && Force Left alignment
ENDIF
This.ScaleLegend._Value = This.GetScaleLegend(m.lnScaleNumber, (m.lnValue / This.ScaleDivider))
This.ScaleLegend._DrawString(m.x1, m.y1)
* Draw the horizontal scale (tick) line in the Y Axis
m.loGfx.DrawLine(m.toPen, m.x0, m.Y, m.x0 + m.ln3D, m.Y - m.ln3D)
m.loGfx.DrawLine(m.loBlackPen, m.x0 - 0, m.Y, m.x0 - This.TicLength, m.Y)
* Chack if finished drawing
IF "N" # VARTYPE(This.GetScaleValue (m.lnScaleNumber + 1))
EXIT
ENDIF
* Draw the scale background
Local x1Scale, y1Scale
m.x1Scale = m.x0 + m.ln3D
m.y1Scale = m.Y - m.ln3D
If m.llDrawBack AND m.tnAxisIndex = 1
****************************************************************
* Jim Nelson 10/11/08
*
* Calculate height to next scale
m.lnThisScale = (This.GetScaleValue (m.lnScaleNumber) - This.GetScaleValue (m.lnScaleNumber+1)) / m.lnMaxValue * m.lnHeight
IF INLIST(This.ScaleBackBarsType, 1, 3) && Horizontal, Both
****************************************************************
* Jim Nelson 10/11/08
*
* Calculate the height of this horizontal bar (allowing for case where not all bars are same height)
* loGfx.FillRectangle(loBackBrush, x1Scale, y1Scale, lnxWidth, lnOneScale)
m.loGfx.FillRectangle(m.loBackBrush, m.x1Scale, m.y1Scale, m.lnxWidth, m.lnThisScale)
ENDIF
IF INLIST(This.ScaleBackLinesType, 1, 3) && Horizontal, Both
****************************************************************
* Jim Nelson 10/10/08
*
* Do NOT draw the line if its the zero line (see below)
IF NOT ( ;
m.llShowLineZero ;
AND ABS(m.lnValue) < m.lnScale / 100 ;
AND m.lnMaxScale > 0 ;
AND m.lnMinScale < 0 ;
AND m.ln3D = 0 ;
)
m.loGfx.DrawLine(This._oBlackPen, m.x1Scale, m.y1Scale, m.x1Scale + m.lnxWidth, m.y1Scale)
m.loGfx.DrawLine(This._oBlackPen, m.x1Scale, m.y1Scale + m.lnThisScale, m.x1Scale + m.lnxWidth, m.y1Scale + m.lnThisScale)
ENDIF
ENDIF
ENDIF
m.llDrawBack = Not m.llDrawBack
IF m.llShowLineZero AND m.tnAxisIndex = 1
* Draw the ZERO line
IF ABS(m.lnValue) < m.lnScale / 100 And m.lnMaxScale > 0 And m.lnMinScale < 0
WITH _Screen.System.Drawing
LOCAL loZeroPen As xfcPen
m.loZeroPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, This.ScaleLineZeroColor), 1)
If m.ln3D = 0
m.loGfx.DrawLine(m.loZeroPen, ;
m.x1Scale, m.y1Scale, m.x1Scale + m.lnxWidth, m.y1Scale)
Else
* Following line moved; does not apply to case m.ln3D = 0
m.y1Scale = m.y1Scale + 1
Local laPolygon(4)
m.laPolygon(1) = .Point.New(m.x1Scale, m.y1Scale)
m.laPolygon(2) = .Point.New(m.x1Scale + m.lnxWidth, m.y1Scale)
m.laPolygon(3) = .Point.New(m.x1Scale + m.lnxWidth - m.ln3D, m.y1Scale + m.ln3D)
m.laPolygon(4) = .Point.New(m.x1Scale - m.ln3D, m.y1Scale + m.ln3D)
Local loZeroBrush As xfcSolidBrush
m.loZeroBrush = .SolidBrush.New(.Color.FromARGB(64, This.ScaleLineZeroColor))
m.loGfx.FillPolygon(m.loZeroBrush, @m.laPolygon)
m.loGfx.DrawPolygon(m.loZeroPen, @m.laPolygon)
Endif
Endwith
Endif
Endif
Endfor
This._ChartY0 = This.Height - This._XAxisHeight - m.ln3D
This._ChartY1 = This._ChartY0 - m.lnHeight
* Restore original Alignment settings
This.ScaleLegend.Alignment = m.lnOrigAlignment
This.ScaleLegend._ForceFormat = m.lcOrigScaleFormat
Else && _Orientation = 2 HORIZONTAL
Local x0, x1, y0, y1
m.lnMargin = This._yAxisWidth + This._LeftOffset
m.y0 = This._TopOffSet
m.y1 = This.Height - This._XAxisHeight + 6
m.x0 = m.lnMargin
m.x1 = This.Width - This._RightOffset && This._LegendWidth
m.lnWidth = This.Width - This._LeftOffset - This._RightOffset - This._yAxisWidth - m.ln3D
Local llDrawBack, lnOneScale
m.llDrawBack = .T.
Local lnRectColor, lnLineColor
If This.BrushType = 3 && Monochrome
m.lnRectColor = Rgb(255, 255, 255) && White
m.lnLineColor = 0 && Black
Else
m.lnRectColor = This.ScaleBackColor
m.lnLineColor = This.ScaleLineColor
Endif
With _Screen.System.Drawing
m.loBackBrush = .SolidBrush.New(.Color.FromARGB(This.ScaleBackAlpha, m.lnRectColor))
This._oBlackPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, m.lnLineColor), This.ScaleBackLinesWidth - 1)
Endwith
Local lnDashValue
m.lnDashValue = This.ScaleBackLinesDash
If m.lnDashValue > 0
This._oBlackPen.DashStyle = m.lnDashValue && _Screen.System.Drawing.Drawing2D.DashStyle.Dash
Endif
m.lnOneScale = m.lnScale / m.lnMaxValue * m.lnWidth
****************************************************************
* Jim Nelson 10/10/08
*
* Loop now calls method GetScaleValue (and its cousin GetScaleLegend) to get the
* scale values and associated legends. lnScaleNumber = 0 returns highest scale
For m.lnScaleNumber = 0 To 1000
m.lnValue = This.GetScaleValue (m.lnScaleNumber)
If "N" # Vartype( m.lnValue)
Exit
Endif
m.lnScaleWidth = (m.lnValue - m.lnMinScale) / m.lnMaxValue * m.lnWidth
m.x = m.x0 + m.lnScaleWidth
m.lnScaleValue = This.GetScaleLegend (m.lnScaleNumber, m.lnValue)
IF VARTYPE(m.lnScaleValue) = "C"
This.ScaleLegend._Value = m.lnScaleValue
ELSE
This.ScaleLegend._Value = IIF(This._AbsoluteScaleValues, ABS(m.lnScaleValue), m.lnScaleValue)
ENDIF
If This.ScaleLegend.Rotation = 0
This.ScaleLegend._DrawString(m.x, m.y1, .T.) && Force Center
Else
This.ScaleLegend._DrawString(m.x, m.y1)
Endif
* Draw the horizontal scale line in the Y Axis
m.loGfx.DrawLine(m.toPen, m.x, m.y1 - 5, m.x + m.ln3D, m.y1 - 5 - m.ln3D)
m.loGfx.DrawLine(m.loBlackPen, m.x, m.y1, m.x, m.y1 - This.TicLength)
* Draw the scale background
Local x1Scale, y1Scale
m.x1Scale = m.x + m.ln3D
m.y1Scale = m.y1 - m.ln3D - 3
If m.llDrawBack and "N" = Vartype (This.GetScaleValue (m.lnScaleNumber+1))
****************************************************************
* Jim Nelson 10/11/08
*
* Calculate width to next scale
m.lnThisScale = (This.GetScaleValue (m.lnScaleNumber) - This.GetScaleValue (m.lnScaleNumber+1)) / m.lnMaxValue * m.lnWidth
If Inlist(This.ScaleBackBarsType, 2, 3) && Vertical, Both
****************************************************************
* Jim Nelson 10/11/08
*
* Calculate the widtht of this horizontal bar (allowing for case where not all bars are same height)
m.loGfx.FillRectangle(m.loBackBrush, m.x1Scale - m.lnThisScale, m.y0, m.lnThisScale, m.y1Scale - m.y0)
Endif
If Inlist(This.ScaleBackLinesType, 2, 3) && Vertical, Both
****************************************************************
* Jim Nelson 10/10/08
*
* Do NOT draw the line if its the zero line (see below)
If Not ( ;
m.llShowLineZero ;
and Abs(m.lnValue) < m.lnScale / 100 ;
And m.lnMaxScale > 0 ;
And m.lnMinScale < 0 ;
and m.ln3D = 0 ;
)
m.loGfx.DrawLine(This._oBlackPen, m.x1Scale, m.y0, m.x1Scale, m.y1Scale)
m.loGfx.DrawLine(This._oBlackPen, m.x1Scale - m.lnThisScale, m.y0, m.x1Scale - m.lnThisScale, m.y1Scale)
Endif
Endif
Endif
m.llDrawBack = Not m.llDrawBack
If m.llShowLineZero
* Draw the ZERO line
If Abs(m.lnValue) < m.lnScale / 100 And m.lnMaxScale > 0 And m.lnMinScale < 0
With _Screen.System.Drawing
Local loZeroPen As xfcPen
m.loZeroPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, This.ScaleLineZeroColor), 1)
If m.ln3D = 0
m.loGfx.DrawLine(m.loZeroPen, m.x1Scale, m.y0, m.x1Scale, m.y1Scale)
Else
* Following line moved; does not apply to case m.ln3D = 0
m.y1Scale = m.y1Scale + 1
Local laPolygon(4)
m.laPolygon(1) = .Point.New(m.x1Scale, m.y0)
m.laPolygon(2) = .Point.New(m.x1Scale, m.y1Scale)
m.laPolygon(3) = .Point.New(m.x1Scale - m.ln3D, m.y1Scale + m.ln3D)
m.laPolygon(4) = .Point.New(m.x1Scale - m.ln3D, m.y0 + m.ln3D)
Local loZeroBrush As xfcSolidBrush
m.loZeroBrush = .SolidBrush.New(.Color.FromARGB(64, This.ScaleLineZeroColor))
m.loGfx.FillPolygon(m.loZeroBrush, @m.laPolygon)
m.loGfx.DrawPolygon(m.loZeroPen, @m.laPolygon)
Endif
Endwith
Endif
Endif
Endfor
Endif
Return
ENDPROC
PROCEDURE _drawshape
LPARAMETERS tnX, tnY, tnValue, tcObjType
LOCAL x1, y1
IF EMPTY(m.tcObjType)
m.tcObjType = "Rect"
ENDIF
LOCAL luShape, lcType, lnIndex, lnTipPixels
m.lnTipPixels = This._TipPixels
m.lnIndex = This._ChartIndex
* IF This.ChartType = 5 AND NOT EMPTY(This.LineCapsShape) && (VARTYPE(This.LineCapsShape) <> "L") && Line
IF NOT EMPTY(This.LineCapsShape)
m.luShape = This.LineCapsShape
ELSE
m.luShape = This.Fields(m.lnIndex).Shape
ENDIF
m.lcType = VARTYPE(m.luShape)
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
LOCAL loObject as Object
DO CASE
CASE m.lcType = "N" OR m.lcType = "O" && Graphics path using predefined Shape
LOCAL loPath as xfcGraphicsPath
LOCAL lnWidth, lnHeight
m.lnWidth = 0
m.lnHeight = 0
IF VARTYPE(This._aShapes(m.lnIndex, 1)) = "O"
m.loPath = This._aShapes(m.lnIndex, 1)
ELSE
IF m.lcType = "O"
m.loPath = m.luShape.Clone()
This._CenterPath(m.loPath, .T., @m.lnWidth, @m.lnHeight)
ELSE
m.loPath = This._GetShapePath(m.luShape)
This._CenterPath(m.loPath, .T., @m.lnWidth, @m.lnHeight)
ENDIF
ENDIF
*!* loRect = loPath.GetBounds()
*!* lnWidth = loRect.Width
*!* lnHeight = loRect.Height
*!* SET STEP ON
*!* * Replacement for the GetBounds function
*!* #DEFINE EMPTY_FLOAT 0h00000000
*!* #DEFINE EMPTY_LONG 0h00000000
*!* #DEFINE EMPTY_SHORT 0h0000
*!* #DEFINE EMPTY_RECTANGLE EMPTY_LONG+EMPTY_LONG+EMPTY_LONG+EMPTY_LONG
*!* #DEFINE EMPTY_RECTANGLEF EMPTY_FLOAT+EMPTY_FLOAT+EMPTY_FLOAT+EMPTY_FLOAT
*!* LOCAL lqRect, x, y, w, h
*!* lqRect = REPLICATE(CHR(0),16)
*!* * lqRect = EMPTY_RECTANGLEF
*!* DECLARE Long GdipGetPathWorldBounds IN GDIPLUS.DLL AS ;
*!* xfcGdipGetPathWorldBounds2 Long path, String @bounds, Long matrix, Long pen
*!* =xfcGdipGetPathWorldBounds2(loPath.Handle, @lqRect, 0, 0)
*!* *!* This.SetStatus(xfcGdipGetPathWorldBoundsI(This.Handle, @lcBounds, m.lhMatrix, m.lhPen))
*!* *X = CTOBIN(SUBSTR(lqRect,1,4),"4rs")
*!* *Y = CTOBIN(SUBSTR(lqRect,5,4),"4rs")
*!* W = CTOBIN(SUBSTR(lqRect,9,4),"4rs")
*!* H = CTOBIN(SUBSTR(lqRect,13,4),"4rs")
*!* * loRect = _Screen.System.Drawing.RectangleF.New(x,y,w,h)
*!* lnWidth = W
*!* lnHeight = H
LOCAL lnColor
IF This.BrushType = 3 && Monochrome
m.lnColor = 0
ELSE
m.lnColor = This.aColors(m.lnIndex)
ENDIF
LOCAL loBrush as xfcSolidBrush
m.loBrush = _Screen.System.Drawing.SolidBrush.New(_Screen.System.Drawing.Color.FromRGB(m.lnColor))
LOCAL loAdjPath as xfcGraphicsPath
LOCAL loMatrix as xfcMatrix
m.loAdjPath = m.loPath.Clone()
m.loMatrix = _Screen.System.Drawing.Drawing2D.Matrix.New()
m.loMatrix.Translate(m.tnX, m.tnY)
m.loAdjPath.Transform(m.loMatrix)
m.loGfx.FillPath(m.loBrush, m.loAdjPath)
m.x1 = m.tnX - (m.lnWidth / 2)
m.y1 = m.tnY - (m.lnHeight / 2)
m.loObject = m.loPath
CASE m.lcType = "C" && Image File
LOCAL loBmp as xfcBitmap
LOCAL lnWidth, lnHeight
IF VARTYPE(This._aShapes(m.lnIndex, 1)) = "O"
m.loBmp = This._aShapes(m.lnIndex, 1)
m.lnWidth = This._aShapes(m.lnIndex, 2)
m.lnHeight = This._aShapes(m.lnIndex, 3)
ELSE
m.loBmp = _Screen.System.Drawing.Bitmap.FromVarbinary(FILETOSTR(m.luShape))
m.lnWidth = m.loBmp.Width
m.lnHeight = m.loBmp.Height
ENDIF
m.x1 = m.tnX - (m.lnWidth /2)
m.y1 = m.tnY - (m.lnHeight /2)
m.loGfx.DrawImage(m.loBmp, m.x1, m.y1)
m.loObject = m.loBmp
OTHERWISE
ENDCASE
*!* This._UpdateCoordinates(tcObjType, x1, y1, ;
*!* MAX(lnTipPixels, m.lnWidth), MAX(lnTipPixels, lnHeight), tnValue)
* Fix by Anal Roy Chowdhurry
IF NOT (This.LineCaps = .T. AND INLIST(This.ChartType, 5, 18))
This._UpdateCoordinates(m.tcObjType, m.x1, m.y1, ;
m.lnWidth, m.lnHeight, m.tnValue)
ENDIF
* End of Revision new checking
This._aShapes(m.lnIndex, 1) = m.loObject
This._aShapes(m.lnIndex, 2) = m.lnWidth
This._aShapes(m.lnIndex, 3) = m.lnHeight
RETURN
ENDPROC
PROCEDURE _drawshapelegend
LPARAMETERS tnX, tnY, tnIndex
LOCAL lcExpr, luValue, lnValue
m.lcExpr = This.ShapeLegendExpression
This.CurrIndex = m.tnIndex
m.lnValue = This.CurrValue
IF (VARTYPE(m.lcExpr) = "C") AND (NOT EMPTY(m.lcExpr))
*!* Other available properties
*!* This.CurrValue
*!* This.CurrLegend
*!* This.CurrObjType
*!* This.CurrRecno
*!* This.CurrColumn
m.luValue = EVALUATE(m.lcExpr)
ELSE
IF This._SumRow AND This.ShowPercentages
* Show percentages as values
DO CASE
CASE EMPTY(This.ShapeLegend.Format) AND EMPTY(This.ShapeLegendExpression)
This.ShapeLegend._ForceFormat = ;
This._GetFieldType(This.SourceAlias, EVALUATE("This.Fields(This.ChartRow).FieldValue"), .T.) + "%"
CASE NOT "%" $ This.ShapeLegend.Format
This.ShapeLegend._ForceFormat = This.ShapeLegend.Format + "%"
ENDCASE
m.luValue = ROUND(m.lnValue / This.aCoord(m.tnIndex, 12) * 100, 0)
ELSE
m.luValue = m.lnValue
ENDIF
ENDIF
This.ShapeLegend._Value = m.luValue
* Measure the legend height
IF INLIST(This.ChartType, 10, 16) && Stacked area
m.tnY = m.tnY - (This.ShapeLegend._Height / 2) && Draw in center
ELSE
m.tnY = m.tnY - (This.ShapeLegend._Height) && Draw above
ENDIF
This.ShapeLegend._DrawString(m.tnX, m.tnY)
RETURN
ENDPROC
PROCEDURE _drawsidelegends
*!* Property LegendPosition
*!* Numeric,
*!* Determines the position where the side legend wiil be drawn in the canvas.
*1* 0 - No Legend
*!* 1 - Vertical Top Left
*!* 2 - Vertical Bottom Left
*!* 3 - Vertical Top Right
*!* 4 - Vertical Bottom Right
*!* 5 - Horiz Top Left
*!* 6 - Horiz Top Center
*!* 7 - Horiz Top Right
*!* 8 - Horiz Bottom Left
*!* 9 - Horiz Bottom Center
*!* 10 - Horiz Bottom Right
*!* 11 - Vertical Center Left
*!* 12 - Vertical Center Right
LOCAL lnPosition, lnOrigAlignment
m.lnPosition = This.LegendPosition
IF NOT This.ShowSideLegend OR m.lnPosition = 0
RETURN
ENDIF
* Force left alignment for the side legend - this value will be restored at the end of this method
m.lnOrigAlignment = This.SideLegend.Alignment
This.SideLegend.Alignment = 0 && Left
This._InLegend = .T.
LOCAL lnLegendHeight, i, lnExternalMargin, lnCount, lnTopMargin, lnVertHeight
LOCAL x1, y1, lnAvailableHeight, lnNeededHeight, lnMargin, lnWidth, lnHeight, llHorizontal
m.llHorizontal = INLIST(m.lnPosition, 5, 6, 7, 8, 9, 10) && Horizontal Top or Bottom
m.lnLegendHeight = This.SideLegend._Height
m.lnExternalMargin = This._LegendExternalMargin
m.lnCount = ALEN(This._aSideLegends, 1)
m.lnTopMargin = This.MarginTop + This.Margin + This._TitleHeight
* Check if we have enough space for legends
m.lnAvailableHeight = This.ChartCanvas.Height - m.lnTopMargin - This.Margin
m.lnNeededHeight = (m.lnCount * m.lnLegendHeight) + (This.Margin * m.lnCount - 1)
IF m.lnNeededHeight > m.lnAvailableHeight
* Recalculate the Margin
m.lnMargin = (m.lnAvailableHeight - (m.lnCount * m.lnLegendHeight)) / m.lnCount
ELSE
m.lnMargin = 3
ENDIF
STORE m.lnLegendHeight TO m.lnWidth, m.lnHeight
m.lnLegendHeight = m.lnLegendHeight + MIN(m.lnMargin, m.lnLegendHeight / 2)
m.lnVertHeight = m.lnCount * m.lnLegendHeight
DO CASE
CASE m.lnPosition = 1 && Vertical Top Left Side
m.x1 = This.Margin + This.MarginLeft + m.lnExternalMargin
m.y1 = m.lnTopMargin
CASE m.lnPosition = 2 && Vertical Bottom Left Side
m.x1 = This.Margin + This.MarginLeft + m.lnExternalMargin
m.y1 = This.ChartCanvas.Height - This.MarginBottom - This.Margin - m.lnVertHeight
CASE m.lnPosition = 11 && Vertical Center Left Side
m.x1 = This.Margin + This.MarginLeft + m.lnExternalMargin
m.y1 = (This.ChartCanvas.Height - This.MarginBottom - m.lnTopMargin - m.lnVertHeight) / 2 + m.lnTopMargin
CASE m.lnPosition = 3 && Vertical Top Right Side (Default)
m.x1 = This.ChartCanvas.Width - This._RightOffset + m.lnExternalMargin + This._Axis2ScaleWidth
m.y1 = m.lnTopMargin
CASE m.lnPosition = 4 && Vertical Bottom Right Side (Default)
m.x1 = This.ChartCanvas.Width - This._RightOffset + m.lnExternalMargin + This._Axis2ScaleWidth
m.y1 = This.ChartCanvas.Height - This.MarginBottom - This.Margin - m.lnVertHeight
CASE m.lnPosition = 12 && Vertical Center Right Side
m.x1 = This.ChartCanvas.Width - This._RightOffset + m.lnExternalMargin + This._Axis2ScaleWidth
m.y1 = (This.ChartCanvas.Height - This.MarginBottom - m.lnTopMargin - m.lnVertHeight) / 2 + m.lnTopMargin
CASE m.llHorizontal && Horizontal Top or Bottom
* Calculate the whole legends width in order to obtain the starting point
LOCAL lnLength, lnStart
m.lnLength = 0
m.lnStart = 0
* Obtain the needed width for the whole horizontal legend
FOR m.i = 1 TO m.lnCount
This.SideLegend.Caption = This._aSideLegends(m.i, 1)
m.lnLength = m.lnLength + m.lnWidth + 10 + This.SideLegend._Width
ENDFOR
DO CASE
CASE INLIST(m.lnPosition, 5, 8) && Left aligned
&& do nothing
CASE INLIST(m.lnPosition, 6, 9) && Center
m.lnStart = This._LeftOffset + (This.ChartCanvas.Width - This._LeftOffset - This._RightOffset - m.lnLength) / 2
CASE INLIST(m.lnPosition, 7, 10) && Right
m.lnStart = This.ChartCanvas.Width - This._RightOffset - m.lnLength
ENDCASE
m.x1 = This._LeftOffset + m.lnStart
IF INLIST(m.lnPosition, 5, 6, 7) && Horizontal Top
m.y1 = m.lnTopMargin + m.lnExternalMargin
ELSE && Horizontal Bottom
m.y1 = This.ChartCanvas.Height - This._LegendHeight - This.Margin - This.MarginBottom + This._LegendExternalMargin
ENDIF
OTHERWISE
ENDCASE
LOCAL lcCaption, lnOrigIndex
LOCAL loLinePen as xfcPen
* Save the current _CharIndex
m.lnOrigIndex = This._ChartIndex
FOR m.i = 1 TO m.lnCount
IF m.y1 <= 0
EXIT
ENDIF
This._ChartIndex = m.i
m.lcCaption = This._aSideLegends(m.i, 1)
IF EMPTY(m.lcCaption)
LOOP
ENDIF
This.SideLegend.Caption = m.lcCaption
This.SideLegend._DrawString(m.x1 + m.lnWidth + 3, m.y1)
This._UpdateCoordinates("Legend", m.x1, m.y1, m.lnWidth + This.SideLegend._Width + 5, m.lnLegendHeight, m.i, m.lcCaption)
DO CASE
CASE INLIST(This.ChartType, 5, 18) ;
AND This._3D = 0 ;
AND This.BrushType = 3 ; && Line, Plain, Monochrome
and not This.Multichart
m.loLinePen = _Screen.System.Drawing.Pen.New(This._oClrBlack, 3)
m.loLinePen.DashStyle = m.i - 1 && _Screen.System.Drawing.Drawing2D.DashStyle.Dash
This.oGfx.DrawLine(m.loLinePen, m.x1, m.y1 + m.lnHeight / 2, m.x1 + m.lnWidth, m.y1 + m.lnHeight / 2)
CASE (This.ChartType = 4 ; && Point
or (INLIST(This.ChartType, 5, 18) and This._3D = 0 and This.LineCaps = .T.)) ; && Plain line
and not This.Multichart
LOCAL loPath as xfcGraphicsPath
m.loPath = This._aShapes(m.i, 1)
IF VARTYPE(m.loPath) <> "O"
RETURN
ENDIF
IF INLIST(LOWER(m.loPath.Class), "xfcbitmap", "xfcimage")
This.oGfx.DrawImage(m.loPath, m.x1, m.y1, m.lnWidth, m.lnHeight)
ELSE
This._DrawShape(m.x1 + m.lnWidth / 2, m.y1 + m.lnHeight / 2, 0, "Legend")
IF This._aShapes(m.i, 3) > m.lnLegendHeight
m.lnLegendHeight = This._aShapes(m.i, 3) + 1
* y1 = y1 + This._aShapes(i,3) + 3
ENDIF
ENDIF
OTHERWISE
This._PrepareBrushes(m.x1, m.y1, m.lnWidth, m.lnHeight, .T., m.i)
THIS.oGfx.FillRectangle(This._oMainBrush, m.x1, m.y1, m.lnWidth, m.lnHeight)
THIS.oGfx.DrawRectangle(This._oBorderPen, m.x1, m.y1, m.lnWidth, m.lnHeight)
ENDCASE
IF m.llHorizontal && Horizontal side legends
m.x1 = m.x1 + m.lnWidth + 10 + This.SideLegend._Width
ELSE
m.y1 = m.y1 + m.lnLegendHeight
ENDIF
ENDFOR
* Restore the current _CharIndex
This._ChartIndex = m.lnOrigIndex
This.SideLegend.Top = m.lnTopMargin
This.SideLegend.Left = m.x1
This.SideLegend.Width = This._LegendWidth
This.SideLegend.Height = MAX(0, m.y1 - m.lnTopMargin)
This._InLegend = .F.
* Restore the alignment value to the original
This.SideLegend.Alignment = m.lnOrigAlignment
RETURN
*!* Property LegendPosition
*!* Numeric,
*!* Determines the position where the side legend wiil be drawn in the canvas.
*1* 0 - No Legend
*!* 1 - Vertical Top Left
*!* 2 - Vertical Bottom Left
*!* 3 - Vertical Top Right
*!* 4 - Vertical Bottom Right
*!* 5 - Horiz Top Left
*!* 6 - Horiz Top Center
*!* 7 - Horiz Top Right
*!* 8 - Horiz Bottom Left
*!* 9 - Horiz Bottom Center
*!* 10 - Horiz Bottom Right
*!* 11 - Vertical Center Left
*!* 12 - Vertical Center Right
LOCAL lnPosition, lnOrigAlignment
m.lnPosition = This.LegendPosition
IF NOT This.ShowSideLegend OR m.lnPosition = 0
RETURN
ENDIF
* Force left alignment for the side legend - this value will be restored at the end of this method
m.lnOrigAlignment = This.SideLegend.Alignment
This.SideLegend.Alignment = 0 && Left
This._InLegend = .T.
LOCAL lnLegendHeight, i, lnExternalMargin, lnCount, lnTopMargin, lnVertHeight
LOCAL x1, y1, lnAvailableHeight, lnNeededHeight, lnMargin, lnWidth, lnHeight, llHorizontal
m.llHorizontal = INLIST(m.lnPosition, 5, 6, 7, 8, 9, 10) && Horizontal Top or Bottom
m.lnLegendHeight = This.SideLegend._Height
m.lnExternalMargin = This._LegendExternalMargin
m.lnCount = ALEN(This._aSideLegends, 1)
m.lnTopMargin = This.MarginTop + This.Margin + This._TitleHeight
* Check if we have enough space for legends
m.lnAvailableHeight = This.ChartCanvas.Height - m.lnTopMargin - This.Margin
m.lnNeededHeight = (m.lnCount * m.lnLegendHeight) + (This.Margin * m.lnCount - 1)
IF m.lnNeededHeight > m.lnAvailableHeight
* Recalculate the Margin
m.lnMargin = (m.lnAvailableHeight - (m.lnCount * m.lnLegendHeight)) / m.lnCount
ELSE
m.lnMargin = 3
ENDIF
STORE m.lnLegendHeight TO m.lnWidth, m.lnHeight
m.lnLegendHeight = m.lnLegendHeight + MIN(m.lnMargin, m.lnLegendHeight / 2)
m.lnVertHeight = m.lnCount * m.lnLegendHeight
DO CASE
CASE m.lnPosition = 1 && Vertical Top Left Side
m.x1 = This.Margin + This.MarginLeft + m.lnExternalMargin
m.y1 = m.lnTopMargin
CASE m.lnPosition = 2 && Vertical Bottom Left Side
m.x1 = This.Margin + This.MarginLeft + m.lnExternalMargin
m.y1 = This.ChartCanvas.Height - This.MarginBottom - This.Margin - m.lnVertHeight
CASE m.lnPosition = 11 && Vertical Center Left Side
m.x1 = This.Margin + This.MarginLeft + m.lnExternalMargin
m.y1 = (This.ChartCanvas.Height - This.MarginBottom - m.lnTopMargin - m.lnVertHeight) / 2 + m.lnTopMargin
CASE m.lnPosition = 3 && Vertical Top Right Side (Default)
m.x1 = This.ChartCanvas.Width - This._RightOffset + m.lnExternalMargin + This._Axis2ScaleWidth
m.y1 = m.lnTopMargin
CASE m.lnPosition = 4 && Vertical Bottom Right Side (Default)
m.x1 = This.ChartCanvas.Width - This._RightOffset + m.lnExternalMargin + This._Axis2ScaleWidth
m.y1 = This.ChartCanvas.Height - This.MarginBottom - This.Margin - m.lnVertHeight
CASE m.lnPosition = 12 && Vertical Center Right Side
m.x1 = This.ChartCanvas.Width - This._RightOffset + m.lnExternalMargin + This._Axis2ScaleWidth
m.y1 = (This.ChartCanvas.Height - This.MarginBottom - m.lnTopMargin - m.lnVertHeight) / 2 + m.lnTopMargin
CASE m.llHorizontal && Horizontal Top or Bottom
* Calculate the whole legends width in order to obtain the starting point
LOCAL lnLength, lnStart
m.lnLength = 0
m.lnStart = 0
* Obtain the needed width for the whole horizontal legend
FOR m.i = 1 TO m.lnCount
This.SideLegend.Caption = This._aSideLegends(m.i, 1)
m.lnLength = m.lnLength + m.lnWidth + 10 + This.SideLegend._Width
ENDFOR
DO CASE
CASE INLIST(m.lnPosition, 5, 8) && Left aligned
&& do nothing
CASE INLIST(m.lnPosition, 6, 9) && Center
m.lnStart = This._LeftOffset + (This.ChartCanvas.Width - This._LeftOffset - This._RightOffset - m.lnLength) / 2
CASE INLIST(m.lnPosition, 7, 10) && Right
m.lnStart = This.ChartCanvas.Width - This._RightOffset - m.lnLength
ENDCASE
m.x1 = This._LeftOffset + m.lnStart
IF INLIST(m.lnPosition, 5, 6, 7) && Horizontal Top
m.y1 = m.lnTopMargin + m.lnExternalMargin
ELSE && Horizontal Bottom
m.y1 = This.ChartCanvas.Height - This._LegendHeight - This.Margin - This.MarginBottom + This._LegendExternalMargin
ENDIF
OTHERWISE
ENDCASE
LOCAL lcCaption, lnOrigIndex
LOCAL loLinePen as xfcPen
* Save the current _CharIndex
m.lnOrigIndex = This._ChartIndex
FOR m.i = 1 TO m.lnCount
IF m.y1 <= 0
EXIT
ENDIF
This._ChartIndex = m.i
m.lcCaption = This._aSideLegends(m.i, 1)
IF EMPTY(m.lcCaption)
LOOP
ENDIF
This.SideLegend.Caption = m.lcCaption
This.SideLegend._DrawString(m.x1 + m.lnWidth + 3, m.y1)
This._UpdateCoordinates("Legend", m.x1, m.y1, m.lnWidth + This.SideLegend._Width + 5, m.lnLegendHeight, m.i, m.lcCaption)
DO CASE
CASE INLIST(This.ChartType, 5, 18) ;
AND This._3D = 0 ;
AND This.BrushType = 3 ; && Line, Plain, Monochrome
and not This.Multichart
m.loLinePen = _Screen.System.Drawing.Pen.New(This._oClrBlack, 3)
m.loLinePen.DashStyle = m.i - 1 && _Screen.System.Drawing.Drawing2D.DashStyle.Dash
This.oGfx.DrawLine(m.loLinePen, m.x1, m.y1 + m.lnHeight / 2, m.x1 + m.lnWidth, m.y1 + m.lnHeight / 2)
CASE (This.ChartType = 4 ; && Point
or (INLIST(This.ChartType, 5, 18) and This._3D = 0 and This.LineCaps = .T.)) ; && Plain line
and not This.Multichart
LOCAL loPath as xfcGraphicsPath
m.loPath = This._aShapes(m.i, 1)
IF VARTYPE(m.loPath) <> "O"
RETURN
ENDIF
IF INLIST(LOWER(m.loPath.Class), "xfcbitmap", "xfcimage")
This.oGfx.DrawImage(m.loPath, m.x1, m.y1, m.lnWidth, m.lnHeight)
ELSE
This._DrawShape(m.x1 + m.lnWidth / 2, m.y1 + m.lnHeight / 2, 0, "Legend")
IF This._aShapes(m.i, 3) > m.lnLegendHeight
m.lnLegendHeight = This._aShapes(m.i, 3) + 1
* y1 = y1 + This._aShapes(i,3) + 3
ENDIF
ENDIF
OTHERWISE
This._PrepareBrushes(m.x1, m.y1, m.lnWidth, m.lnHeight, .T., m.i)
THIS.oGfx.FillRectangle(This._oMainBrush, m.x1, m.y1, m.lnWidth, m.lnHeight)
THIS.oGfx.DrawRectangle(This._oBorderPen, m.x1, m.y1, m.lnWidth, m.lnHeight)
ENDCASE
IF m.llHorizontal && Horizontal side legends
m.x1 = m.x1 + m.lnWidth + 10 + This.SideLegend._Width
ELSE
m.y1 = m.y1 + m.lnLegendHeight
ENDIF
ENDFOR
* Restore the current _CharIndex
This._ChartIndex = m.lnOrigIndex
This.SideLegend.Top = m.lnTopMargin
This.SideLegend.Left = m.x1
This.SideLegend.Width = This._LegendWidth
This.SideLegend.Height = MAX(0, m.y1 - m.lnTopMargin)
This._InLegend = .F.
* Restore the alignment value to the original
This.SideLegend.Alignment = m.lnOrigAlignment
RETURN
ENDPROC
PROCEDURE _drawslice
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnStart, tnSweep, tnValue
LOCAL llAdjLeft as Boolean, ;
llAdjRight as Boolean, h, w
IF m.tnWidth <=0 OR m.tnHeight <=0
RETURN
ENDIF
This._AdjustStartSweep(@m.tnStart, @m.tnSweep, m.tnWidth, m.tnHeight)
This._UpdateCoordinates("Pie", m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, m.tnStart, m.tnSweep)
LOCAL lnXBrush, lnYBrush
IF This.PieEnhancedDrawing
m.lnXBrush = m.tnX
m.lnYBrush = m.tnY
ELSE
m.lnXBrush = 0
m.lnYBrush = 0
ENDIF
This._PrepareBrushes(m.lnXBrush, m.lnYBrush, m.tnWidth, m.tnHeight, .F., RECNO())
LOCAL loPen as xfcPen
m.loPen = This._oBorderPen
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
LOCAL loMainBrush as xfcBrush
m.loMainBrush = This._oMainBrush
LOCAL lo3dBrush as xfcBrush
m.lo3dBrush = This._o3DBrush
LOCAL lnFinalAngle
m.lnFinalAngle = m.tnStart + m.tnSweep
IF m.lnFinalAngle > 360
m.lnFinalAngle = m.lnFinalAngle - 360
ENDIF
LOCAL ln3D
m.ln3D = This._3D
WITH _Screen.System.Drawing
IF This.PieEnhancedDrawing
* Draw the 3D Slice using the GraphicsPath class
IF m.ln3D > 0 AND (This.Shadow = .F.)
m.x = m.tnX
m.y = m.tnY
m.w = m.tnWidth
m.h = m.tnHeight
* Draw the bottom slice
m.loGfx.FillPie(m.loMainBrush, m.x, m.y + m.ln3D, m.w, m.h, m.tnStart, m.tnSweep)
m.loGfx.DrawPie(m.loPen, m.x, m.y, m.w, m.h, m.tnStart, m.tnSweep)
* Get the start point
LOCAL loPath as xfcGraphicsPath
LOCAL loPoint1 as xfcPoint, loPoint2 as xfcPoint
m.loPath = _Screen.System.Drawing.Drawing2D.GraPHICSPATH.New()
m.loPath.AddPie(m.x,m.y,m.w,m.h, m.tnStart, 0.0001)
m.loPoint1 = m.loPath.GetLastpoint()
m.loPath.AddPie(m.x,m.y,m.w,m.h, m.tnStart, m.tnSweep)
m.loPoint2 = m.loPath.GetLastpoint()
* Draw side Polygon 1
LOCAL laPointsA(4)
LOCAL lnCenterX, lnCenterY
m.lnCenterX = m.x + (m.w/2)
m.lnCenterY = m.y + (m.h/2)
m.laPointsA(1) = .Point.New(m.lnCenterX, m.lnCenterY)
m.laPointsA(2) = .Point.New(m.lnCenterX, m.lnCenterY + m.ln3D)
m.laPointsA(3) = .Point.New(m.loPoint1.x, m.loPoint1.Y + m.ln3D)
m.laPointsA(4) = m.loPoint1
* Draw side Polygon 2
LOCAL laPointsB(4)
m.laPointsB(1) = m.laPointsA(1)
m.laPointsB(2) = m.laPointsA(2)
m.laPointsB(3) = .Point.New(m.loPoint2.x, m.loPoint2.Y + m.ln3D)
m.laPointsB(4) = m.loPoint2
IF m.tnStart <= 90 OR m.tnStart > 270
m.loGfx.DrawPolygon(m.loPen, @m.laPointsA)
m.loGfx.FillPolygon(m.lo3dBrush, @m.laPointsA)
ENDIF
IF m.lnFinalAngle < 270 AND m.lnFinalAngle > 90
m.loGfx.FillPolygon(m.lo3dBrush, @m.laPointsB)
m.loGfx.DrawPolygon(m.loPen, @m.laPointsB)
ENDIF
* Draw the external 3d Face
LOCAL loPath2 as xfcGraphicsPath
m.loPath2 = _Screen.System.Drawing.Drawing2D.GraPHICSPATH.New()
m.loPath2.FillMode = _Screen.System.Drawing.Drawing2D.FILLMODE.winding
m.loPath2.StartFigure()
LOCAL lnAdjStart, lnAdjSweep
m.lnAdjStart = m.tnStart
m.lnAdjSweep = m.tnSweep
IF m.tnStart >= 270 AND ;
m.tnStart < 360 AND ;
BETWEEN(m.lnFinalAngle, 0, 270)
m.llAdjRight = .T.
* Create a new partial path for the 1st part
LOCAL loPath3 as xfcGraphicsPath
m.loPath3 = _Screen.System.Drawing.Drawing2D.GraPHICSPATH.New()
m.loPath3.StartFigure()
m.loPath3.AddArc(m.x,m.y,m.w,m.h, m.tnStart, 360 - m.tnStart)
m.loPath3.Reverse()
m.loPath3.AddLine(m.loPoint1.x, m.loPoint1.Y, m.loPoint1.x, m.loPoint1.Y + m.ln3D)
m.loPath3.AddArc(m.x,m.y + m.ln3D, m.w, m.h, m.tnStart, 360 - m.tnStart)
m.loPath3.AddLine(m.tnX + m.tnWidth, m.lnCenterY + m.ln3D, m.tnX + m.tnWidth, m.lnCenterY)
m.loGfx.FillPath(m.lo3dBrush, m.loPath3)
m.loGfx.DrawPath(m.loPen, m.loPath3)
m.loPoint1 = .Point.New(m.tnX + m.tnWidth, m.lnCenterY)
m.lnAdjStart = 0
m.lnAdjSweep = m.tnSweep - (360 - m.tnStart)
ENDIF
IF (m.tnStart < 180 AND m.lnFinalAngle > 180) OR ;
(m.tnStart >= 270 AND m.lnFinalAngle > 180 AND m.lnFinalAngle < 270.01)
* IF (m.tnStart < 180 AND lnFinalAngle > 180) OR ;
(m.tnStart >= 270 AND lnFinalAngle > 180 AND lnFinalAngle < 269.9999)
m.llAdjLeft = .T.
* Create a new partial path for the 1st part
LOCAL loPath4 as xfcGraphicsPath
m.loPath4 = _Screen.System.Drawing.Drawing2D.GraphicsPath.New()
m.loPath4.StartFigure()
IF m.tnStart >= 270
m.lnAdjStart = 0
m.lnAdjSweep = 180
ELSE
m.lnAdjStart = m.tnStart
m.lnAdjSweep = 180 - m.tnStart
ENDIF
m.loPath4.AddArc(m.x,m.y,m.w,m.h, m.lnAdjStart, m.lnAdjSweep)
m.loPath4.Reverse()
m.loPath4.AddLine(m.loPoint1.x, m.loPoint1.Y, m.loPoint1.x, m.loPoint1.Y + m.ln3D)
m.loPath4.AddArc(m.x,m.y + m.ln3D, m.w, m.h, m.lnAdjStart, m.lnAdjSweep)
m.loPath4.AddLine(m.tnX, m.lnCenterY + m.ln3D, m.tnX, m.lnCenterY)
m.loGfx.FillPath(m.lo3DBrush, m.loPath4)
m.loGfx.DrawPath(m.loPen, m.loPath4)
m.loPoint1 = .Point.New(m.tnX, m.lnCenterY)
m.lnAdjStart = 180
m.lnAdjSweep = m.lnFinalAngle - 180
ENDIF
m.loPath2.AddArc(m.x,m.y,m.w,m.h, m.lnAdjStart, m.lnAdjSweep)
m.loPath2.Reverse()
m.loPath2.AddLine(m.loPoint1.x, m.loPoint1.Y, m.loPoint1.x, m.loPoint1.Y + m.ln3D)
m.loPath2.AddArc(m.x,m.y + m.ln3D, m.w, m.h, m.lnAdjStart, m.lnAdjSweep)
m.loPath2.AddLine(m.loPoint2.x, m.loPoint2.Y + m.ln3D, m.loPoint2.x, m.loPoint2.Y)
m.loGfx.FillPath(m.lo3dBrush, m.loPath2)
m.loGfx.DrawPath(m.loPen, m.loPath2)
IF m.tnStart > 90 AND m.tnStart < 270
m.loGfx.DrawPolygon(m.loPen, @m.laPointsA)
m.loGfx.FillPolygon(m.lo3dBrush, @m.laPointsA)
ENDIF
IF m.lnFinalAngle > 270 OR m.lnFinalAngle <= 90
m.loGfx.FillPolygon(m.lo3dBrush, @m.laPointsB)
m.loGfx.DrawPolygon(m.loPen, @m.laPointsB)
ENDIF
* Draw the top slice
m.loGfx.FillPie(m.loMainBrush, m.x, m.y, m.w, m.h, m.tnStart, m.tnSweep)
m.loGfx.DrawPie(m.loPen, m.x, m.y, m.w, m.h, m.tnStart, m.tnSweep)
ELSE
* Draw shadow
IF This.Shadow
LOCAL loShadowBrush as xfcSolidBrush
m.loShadowBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel,128,128,128))
m.loGfx.FillPie(m.loShadowBrush, m.tnX, m.tnY + m.ln3d, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
ENDIF
* Draw the main slice
m.loGfx.FillPie(m.loMainBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
m.loGfx.DrawPie(m.loPen, m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
ENDIF
ELSE
*** This is the old behavior for Pie slices
LOCAL loBmp as xfcBitmap
m.loBmp = poTempBmp
LOCAL loTempGfx as xfcGraphics
m.loTempGfx = .Graphics.FromImage(m.loBmp)
m.loTempGfx.Clear(.Color.Transparent)
m.loTempGfx.SmoothingMode = .Drawing2D.SmoothingMode.AntiAlias
* Draw the 3D Slice using the Hatch Brush
IF m.ln3D > 0
LOCAL y1, n
m.y1 = m.ln3D
* Draw the contour of the 3D Slice
m.loTempGfx.FillPie(m.loMainBrush, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
m.loTempGfx.DrawPie(m.loPen, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
FOR m.n = 1 TO m.ln3D
m.y1 = m.y1 - 1
* Draw the Normal Slice using the Solid Brush
m.loTempGfx.FillPie(m.lo3dBrush, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) && draw the slice
IF m.tnStart > 90
m.loTempGfx.DrawArc(m.loPen, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart, 0.25)
ENDIF
m.loTempGfx.DrawArc(m.loPen, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart + m.tnSweep - .25, 0.35)
ENDFOR
m.loTempGfx.FillPie(m.loMainBrush, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) && draw the slice
* Draw border line from center of pie
LOCAL x, y
m.x = (m.tnWidth / 2)
m.y = (m.tnHeight / 2) + m.y1
IF m.tnStart > 90
m.loTempGfx.DrawLine(m.loPen, m.x, m.Y, m.x, m.Y + m.ln3D)
ENDIF
m.loTempGfx.DrawPie(m.loPen, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
m.loTempGfx.FillPie(m.loMainBrush, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
m.loTempGfx.DrawPie(m.loPen, 0, m.y1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
* Draw the Image
m.loBmp.ApplyColorMatrix(poClrMatrix)
m.loGfx.DrawImage(m.loBmp, m.tnX, m.tnY)
ELSE
m.loGfx.FillPie(m.loMainBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
m.loGfx.DrawPie(m.loPen, m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
ENDIF
ENDIF
ENDWITH
RETURN
ENDPROC
PROCEDURE _drawsliceexternal
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnStart, tnSweep, toPoint1, toPoint2
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
LOCAL lo3DBrush as xfcSolidBrush
m.lo3DBrush = This._o3dBrush
LOCAL loPen as xfcPen
m.loPen = This._oBorderPen
LOCAL ln3D
m.ln3D = This._3d
* Draw the external 3d Face
LOCAL loPath as xfcGraphicsPath
m.loPath = _Screen.System.Drawing.Drawing2D.GraphicsPath.New()
m.loPath.StartFigure()
m.loPath.AddArc(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
m.loPath.Reverse()
m.loPath.AddLine(m.toPoint1.x, m.toPoint1.Y, m.toPoint1.x, m.toPoint1.Y + m.ln3D)
m.loPath.AddArc(m.tnX, m.tnY + m.ln3D, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
m.loPath.AddLine(m.toPoint2.X, m.toPoint2.Y + m.ln3D, m.toPoint2.x, m.toPoint2.Y)
m.loPath.CloseFigure()
m.loGfx.FillPath(m.lo3dBrush, m.loPath)
m.loGfx.DrawPath(m.loPen, m.loPath)
ENDPROC
PROCEDURE _drawstackedareachart
* Generates Stacked and Full-Stacked area Charts (ChartTypes and 16)
SELECT(This._DataCursor)
LOCAL lnMargin, lnWidth, lnHeight, lnValue, lnRecs
LOCAL lnBetween, n, i, lnMaxValue, lnPointHeight, ln3D, lnYBase, lnTipPixels, x1, y1
LOCAL lnTipPixels
LOCAL llMultiChart
m.llMultiChart = .F.
m.lnTipPixels = This._TipPixels
m.lnMargin = This.Margin
m.ln3D = This._3D
m.lnRecs = This._nRecords
* Calculate the maximum width of the chart
m.lnHeight = This.ChartCanvas.Height - This._XAxisHeight - This._TopOffSet - This._3d
m.lnWidth = This.ChartCanvas.Width - This._YAxisWidth - This._LeftOffset - m.ln3D - This._RightOffset
IF m.lnWidth < 10 OR m.lnHeight < 10 OR This._nRecords < 2
RETURN
ENDIF
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
* Get the maximum value of the chart
m.lnMaxValue = This._ScaleRange
* Get the lower Y point
m.lnYBase = This.ChartCanvas.Height - This._xAxisHeight
* If MultiChart mode, the chart needs to start half a position further
IF m.llMultiChart
m.lnBetween = m.lnWidth / (m.lnRecs)
ELSE
m.lnBetween = m.lnWidth / (m.lnRecs - 1)
ENDIF
* Prepare array of points
* All the main points will be defined here
LOCAL laPointsX(lnRecs)
LOCAL laPointsY(lnRecs, This.ChartsCount)
LOCAL laPointsYAV(lnRecs, This.ChartsCount)
LOCAL laPointsI(lnRecs, This.ChartsCount) && Points Index
LOCAL lnPrevPoint
LOCAL lnTotRow
LOCAL laValues(This.ChartsCount)
SCAN
m.n = RECNO()
m.lnPrevPoint = 0
m.x1 = This._YAxisWidth + (m.lnBetween * (m.n - 1)) + IIF(m.llMultiChart, (m.lnBetween / 2), 0) + This._LeftOffset && lnMargin
m.laPointsX(m.n) = m.x1
* This._aPoints(n,1) = laPointsX(n)
This._aPoints(m.n,1) = m.x1 + m.ln3D
m.lnTotRow = 0
* Get the total for the current row
FOR m.i = 1 TO This.ChartsCount
m.lnValue = This._GetValue(m.i)
m.laValues(m.i) = m.lnValue
m.lnTotRow = m.lnTotRow + m.lnValue
ENDFOR
FOR m.i = 1 TO This.ChartsCount
m.lnValue = m.laValues(m.i)
This._ChartIndex = m.i
IF This.ChartType = 16 && Full-stacked Area
m.lnPointHeight = m.lnValue / m.lnTotRow * m.lnHeight
ELSE
m.lnPointHeight = m.lnValue / m.lnMaxValue * m.lnHeight
ENDIF
m.y1 = m.lnYBase - (m.lnPointHeight + m.lnPrevPoint)
m.laPointsY(m.n, m.i) = m.y1
m.laPointsYAV(m.n, m.i) = m.lnYBase - (m.lnPointHeight / 2 + m.lnPrevPoint)
m.lnPrevPoint = m.lnPointHeight + m.lnPrevPoint
IF m.lnValue = 0
This._UpdateCoordinates("Rect", 0, 0, 0, 0, m.lnValue, m.lnTotRow)
ELSE
This._UpdateCoordinates("Rect", m.X1 - m.lnTipPixels/2, m.Y1, m.lnTipPixels, m.lnPointHeight, m.lnValue, m.lnTotRow)
ENDIF
m.laPointsI(m.n,m.i) = This._nIndex
ENDFOR
ENDSCAN
* Draw the vertical line only for the first line
This._DrawVerticalLineBack()
LOCAL laMainPolygon(lnRecs * 2)
LOCAL laLinePolygon(4)
LOCAL laSidePolygon(4)
LOCAL lnCompl
LOCAL loBrush as xfcBrush
IF This.BrushType = 1
m.loBrush = "This._o3dbrush"
ELSE
m.loBrush = "This._oMainBrush"
ENDIF
WITH _Screen.System.Drawing
FOR m.i = 1 TO This.ChartsCount
* Fill the main polygon
FOR m.n = 1 TO m.lnRecs
m.lnCompl = (m.lnRecs * 2) - m.n + 1
m.laMainPolygon(m.n) = .Point.New(m.laPointsX(m.n), m.laPointsY(m.n, m.i))
IF m.i = 1
m.laMainPolygon(m.lnCompl) = .Point.New(m.laPointsX(m.n), m.lnYBase)
ELSE
m.laMainPolygon(m.lnCompl) = .Point.New(m.laPointsX(m.n), m.laPointsY(m.n, m.i-1))
ENDIF
ENDFOR
This._PrepareBrushes(0,0,This.ChartCanvas.Width, This.ChartCanvas.Height, .F., m.i)
m.loGfx.FillPolygon(This._oMainBrush, @m.laMainPolygon)
m.loGfx.DrawPolygon(This._oBorderPen, @m.laMainPolygon)
IF m.ln3D > 0
* Draw the 3D line above the main polygon
FOR m.n = 1 TO m.lnRecs - 1
m.laLinePolygon(1) = m.laMainPolygon(m.n)
m.laLinePolygon(2) = .Point.New(m.laMainPolygon(m.n).X + m.ln3D, m.laMainPolygon(m.n).Y - m.ln3D)
m.laLinePolygon(3) = .Point.New(m.laMainPolygon(m.n+1).X + m.ln3D, m.laMainPolygon(m.n+1).Y - m.ln3D)
m.laLinePolygon(4) = m.laMainPolygon(m.n+1)
This._PrepareBrushes(m.laMainPolygon(m.n).X, m.laMainPolygon(m.n).Y - m.ln3D, ;
m.laMainPolygon(m.n+1).X + m.ln3D - m.laMainPolygon(m.n).X, ;
MAX(2,ABS(m.laMainPolygon(m.n).Y - m.laMainPolygon(m.n+1).Y)), .F., m.i)
m.loGfx.FillPolygon(EVALUATE(m.loBrush), @m.laLinePolygon)
m.loGfx.DrawPolygon(This._oBorderPen, @m.laLinePolygon)
ENDFOR
* Fill the right-most external side of the area
* Draw the last 3D polygon, to fill the Area
m.laSidePolygon(1) = m.laLinePolygon(3)
m.laSidePolygon(2) = m.laLinePolygon(4)
m.laSidePolygon(3) = m.laMainPolygon(m.lnRecs + 1)
m.laSidePolygon(4) = .Point.New(m.laSidePolygon(3).X + m.ln3D, m.laSidePolygon(3).Y - m.ln3D)
This._PrepareBrushes(m.laSidePolygon(2).X, m.laSidePolygon(1).Y, ;
m.ln3D, 2, .F., m.i)
m.loGfx.FillPolygon(EVALUATE(m.loBrush), @m.laSidePolygon)
m.loGfx.DrawPolygon(This._oBorderPen, @m.laSidePolygon)
ENDIF
ENDFOR
* Adjust _aPoints Array to show the information in the correct position
FOR m.n = 1 TO m.lnRecs
This._aPoints(m.n,1) = This._aPoints(m.n,1) - m.ln3D
ENDFOR
IF This.ShowValuesOnShapes
LOCAL lnIndex
FOR m.i = 1 TO This.ChartsCount
IF This.Fields(m.i).ShowValuesOnShape
*** Draw Legends above the points
FOR m.n = 1 TO m.lnRecs
m.x1 = m.laPointsX(m.n)
m.y1 = m.laPointsYAV(m.n, m.i)
m.lnIndex = m.laPointsI(m.n,m.i)
This._DrawShapeLegend(m.x1, m.y1, m.lnIndex)
ENDFOR
ENDIF
ENDFOR
ENDIF
This._DrawXAxisLegend()
ENDWITH
ENDPROC
PROCEDURE _drawtrianglebar
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue
Local loLeftBrush as Object, ;
loRightBrush as Object
This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex))
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
LOCAL lnAlpha, lnOrigAlpha
m.lnOrigAlpha = This.AlphaChannel
m.lnAlpha = MIN(255, (This.AlphaChannel * 1.25))
This.AlphaChannel = m.lnAlpha
LOCAL loTopBrush as xfcBrush
LOCAL loBotBrush as xfcBrush
WITH _Screen.System.Drawing
LOCAL lnColor, ln3D
LOCAL loPen as xfcPen
m.lnColor = This.ChangeColor(This._nColor, + 60)
m.ln3D = MAX(This._3d, 1)
m.loPen = .Pen.New(.Color.FromRGB(m.lnColor))
DO CASE
CASE This.BrushType = 1 && SolidColors
m.loTopBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This.ChangeColor(This._nColor, - 20)))
m.loBotBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This._nColor))
m.loLeftBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This.ChangeColor(This._nColor, - 20)))
m.loRightBrush = This._oMainBrush
CASE This.BrushType = 2 && Gradient
m.loTopBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This._nColor))
m.loBotBrush = m.loTopBrush
m.loLeftBrush = m.loTopBrush
m.loRightBrush = This._oMainBrush
OTHERWISE
This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex))
m.loTopBrush = This._oMainBrush
m.loBotBrush = m.loTopBrush
m.loLeftBrush = m.loTopBrush
m.loRightBrush = This._oMainBrush
ENDCASE
This.AlphaChannel = m.lnOrigAlpha
IF This._Orientation = 1 && Vertical
LOCAL lnCenterX, x0, x1
m.x0 = m.tnX + m.ln3D / 2
m.x1 = m.x0 + m.tnWidth
m.lnCenterX = m.x0 + (m.tnWidth / 2)
* Prepare the top triangle
LOCAL laTopPoints(3)
m.laTopPoints(1) = .Point.New(m.lnCenterX, m.tnY)
m.laTopPoints(2) = .Point.New(m.x0, m.tnY - m.ln3D)
m.laTopPoints(3) = .Point.New(m.x1, m.tnY - m.ln3D)
m.loGfx.DrawPolygon(m.loPen, @m.laTopPoints)
m.loGfx.FillPolygon(m.loTopBrush, @m.laTopPoints)
* Prepare the bottom triangle
LOCAL yBott
m.yBott = m.tnY + m.tnHeight
LOCAL laBotPoints(3)
m.laBotPoints(1) = .Point.New(m.lnCenterX, m.yBott)
m.laBotPoints(2) = .Point.New(m.x0, m.yBott - m.ln3D)
m.laBotPoints(3) = .Point.New(m.x1, m.yBott - m.ln3D)
m.loGfx.DrawPolygon(m.loPen, @m.laBotPoints)
m.loGfx.FillPolygon(m.loBotBrush, @m.laBotPoints)
* Prepare the LEFT face of the 3d triangle (polygon)
LOCAL laLeftPoints(4)
m.laLeftPoints(1) = m.laTopPoints(1)
m.laLeftPoints(2) = m.laTopPoints(2)
m.laLeftPoints(3) = m.laBotPoints(2)
m.laLeftPoints(4) = m.laBotPoints(1)
m.loGfx.DrawPolygon(m.loPen, @m.laLeftPoints)
m.loGfx.FillPolygon(m.loLeftBrush, @m.laLeftPoints)
* Prepare the RIGHT face of the 3d triangle (polygon)
LOCAL laRightPoints(4)
m.laRightPoints(1) = m.laTopPoints(1)
m.laRightPoints(2) = m.laTopPoints(3)
m.laRightPoints(3) = m.laBotPoints(3)
m.laRightPoints(4) = m.laBotPoints(1)
m.loGfx.DrawPolygon(m.loPen, @m.laRightPoints)
m.loGfx.FillPolygon(m.loRightBrush, @m.laRightPoints)
ELSE && Horizontal
LOCAL lnCenterY, y0, y1, ln3D
m.ln3D = MAX(This._3d, 1)
m.x0 = m.tnX
m.x1 = m.x0 + m.tnWidth
m.lnCenterY = m.tnY + (m.tnHeight / 2)
* Prepare the right (top) triangle
LOCAL laRightPoints(3)
m.laRightPoints(1) = .Point.New(m.X1, m.lnCenterY)
m.laRightPoints(2) = .Point.New(m.X1 + m.ln3d, m.tnY)
m.laRightPoints(3) = .Point.New(m.X1 + m.ln3d, m.tnY + m.tnHeight)
m.loGfx.DrawPolygon(m.loPen, @m.laRightPoints)
m.loGfx.FillPolygon(m.loTopBrush, @m.laRightPoints)
* Prepare the Left triangle
LOCAL laLeftPoints(3)
m.laLeftPoints(1) = .Point.New(m.X0, m.lnCenterY)
m.laLeftPoints(2) = .Point.New(m.X0 + m.ln3d, m.tnY)
m.laLeftPoints(3) = .Point.New(m.X0 + m.ln3d, m.tnY + m.tnHeight)
m.loGfx.DrawPolygon(m.loPen, @m.laLeftPoints)
m.loGfx.FillPolygon(m.loBotBrush, @m.laLeftPoints)
* Prepare the Top face of the 3d triangle (polygon)
LOCAL laTopPoints(4)
m.laTopPoints(1) = m.laLeftPoints(1)
m.laTopPoints(2) = m.laLeftPoints(2)
m.laTopPoints(3) = m.laRightPoints(2)
m.laTopPoints(4) = m.laRightPoints(1)
m.loGfx.DrawPolygon(m.loPen, @m.laTopPoints)
m.loGfx.FillPolygon(m.loLeftBrush, @m.laTopPoints)
* Prepare the BOTTOM face of the 3d triangle (polygon)
LOCAL laBotPoints(4)
m.laBotPoints(1) = m.laLeftPoints(1)
m.laBotPoints(2) = m.laLeftPoints(3)
m.laBotPoints(3) = m.laRightPoints(3)
m.laBotPoints(4) = m.laRightPoints(1)
m.loGfx.DrawPolygon(m.loPen, @m.laBotPoints)
m.loGfx.FillPolygon(m.loRightBrush, @m.laBotPoints)
ENDIF
* Draw the Values inside the shapes
This._DrawLegendinBar(m.X0, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
ENDWITH
RETURN
ENDPROC
PROCEDURE _drawverticallineback
IF This._Orientation = 2
RETURN
ENDIF
LOCAL n, x0, x1, lnLineColor, lnRectColor, lnDashValue
LOCAL loBackPen as xfcPen
LOCAL loBackBrush as xfcSolidBrush
LOCAL llDrawBack, llDrawLines
LOCAL ln3D
IF This._DeepChart && AND This._GeneralType = "Bar" && Point, Line, 3d Bars or Area
m.ln3D = This._3D * This.ChartsCount
ELSE
m.ln3D = This._3D
ENDIF
m.llDrawBack = .T.
m.llDrawLines = INLIST(This.ScaleBackLinesType, 2, 3) && Vertical, Both
WITH _Screen.System.Drawing
IF This.BrushType = 3 && Monochrome
m.lnRectColor = RGB(255,255,255) && White
m.lnLineColor = 0 && Black
ELSE
m.lnRectColor = This.ScaleBackColor
m.lnLineColor = This.ScaleLineColor
ENDIF
m.loBackBrush = .SolidBrush.New(.Color.FromARGB(This.ScaleBackAlpha, m.lnRectColor))
m.loBackPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, m.lnLineColor),This.ScaleBackLinesWidth - 1)
ENDWITH
m.lnDashValue = This.ScaleBackLinesDash
IF m.lnDashValue > 0
m.loBackPen.DashStyle = m.lnDashValue && _Screen.System.Drawing.Drawing2D.DashStyle.Dash
ENDIF
LOCAL lnLinesDistance, lnRecs
m.lnRecs = This._nRecords
IF m.lnRecs > 1
m.lnLinesDistance = This._aPoints(2,1) - This._aPoints(1,1)
ELSE
m.lnLinesDistance = 0
ENDIF
IF m.llDrawBack OR m.llDrawLines
FOR m.n = 1 TO m.lnRecs
m.x0 = This._aPoints(m.n,1) + IIF(This._GeneralType = "Bar", m.ln3D, 0)
IF m.llDrawBack AND (m.n < m.lnRecs)
* Draw the rectangle bar on the back
IF INLIST(This.ScaleBackBarsType, 2, 3) && Vertical, Both
This.oGfx.FillRectangle(m.loBackBrush, m.x0, This._ChartY1, m.lnLinesDistance, This._ChartY0 - This._ChartY1)
ENDIF
ENDIF
IF m.llDrawLines && Vertical, Both
* Draw the diagonal line in the X axis
IF m.ln3D > 0
This.oGfx.DrawLine(m.loBackPen, m.x0, This._ChartY0, m.x0 - m.ln3D, This._ChartY0 + m.ln3D)
ENDIF
* Draw the vertical line on the back
This.oGfx.DrawLine(m.loBackPen, m.x0, This._ChartY0, m.x0, This._ChartY1)
ENDIF
m.llDrawBack = NOT m.llDrawBack
ENDFOR
ENDIF
ENDPROC
PROCEDURE _drawxaxislegend
LPARAMETERS tn3D, tnDistance
Local lnAdjust as Number
IF EMPTY(This.FieldAxis2)
RETURN
ENDIF
IF VARTYPE(m.tn3D) = "N"
m.lnAdjust = m.tn3D
ELSE
m.lnAdjust = 0
ENDIF
* Draw Legends on the X Axis
LOCAL loSize as xfcSize
LOCAL y0, x0, x1, y1, lcText, lnXPoint, lnXStart
m.Y0 = ROUND(This.ChartCanvas.Height - This._XAxisHeight,0)
m.y1 = m.y0 + 6
This.AxisLegend2._Setup()
m.lnXStart = This._aPoints(1,1)
SCAN
* Measure the legend width
m.lcText = cAxis2
This.AxisLegend2.Caption = m.lcText
IF NOT EMPTY(m.tnDistance)
m.X0 = m.lnXStart + ((RECNO() - 1) * m.tnDistance)
ELSE
m.X0 = This._aPoints(RECNO(),1)
ENDIF
IF VARTYPE(m.X0) <> "N"
LOOP
ENDIF
* Draw the tic mark
IF This.ShowAxis2Tics
This.oGfx.DrawLine(This._oBlackPen, m.x0 + m.lnAdjust, m.y0, m.x0 + m.lnAdjust, m.y0 + This.TicLength)
ENDIF
m.x1 = m.X0 + m.lnAdjust
This.AxisLegend2._DrawString(m.x1, m.y1)
ENDSCAN
ENDPROC
PROCEDURE _drawyaxis
LPARAMETERS tn3D, tnMinLeft, tnYAxisHeight, toBrush, toPen, tnIndex
LOCAL ln3d, lnMinLeft, lnYAxisHeight
LOCAL loBrush AS xfcBrush, loPen AS xfcPen, loGfx AS xfcGraphics
m.loBrush = m.toBrush
m.loPen = m.toPen
m.loGfx = THIS.oGfx
m.lnMinLeft = m.tnMinLeft
m.ln3d = m.tn3D
m.lnYAxisHeight = m.tnYAxisHeight
**************************************************************************************
* DRAWING THE Y Axis
LOCAL x0, x1, y0, y1
m.y0 = ROUND(THIS.ChartCanvas.HEIGHT - THIS._XAxisHeight,0)
m.y1 = ROUND(THIS._TopOffSet,0)
IF m.y0 - m.y1 < m.ln3d
RETURN
ENDIF
IF THIS.ShowAxis = .T.
* Draw the main Y Axis caption
IF tnIndex = 1
IF EMPTY(THIS.YAxis.CAPTION)
This._yAxisWidth = 0
ELSE
LOCAL lnYaxisWidth
m.lnYaxisWidth = m.y0 - m.y1
IF m.lnYaxisWidth < 5 OR m.lnYAxisHeight < 5
RETURN
ENDIF
THIS._yAxisWidth = MAX(m.lnMinLeft, THIS.YAxis._Height + 3 + THIS._ScaleW)
THIS.YAxis.ROTATION = 270
THIS.YAxis._DrawString(THIS._LeftOffset, m.y1 + m.lnYaxisWidth, m.lnYaxisWidth, m.lnYAxisHeight)
ENDIF
ENDIF && tnIndex = 1
IF tnIndex = 2
IF EMPTY(THIS.YAxis2.CAPTION)
This._yAxisWidth2 = 0
ELSE
LOCAL lnYaxisWidth2
m.lnYaxisWidth2 = m.y0 - m.y1
IF m.lnYaxisWidth2 < 5 OR m.lnYAxisHeight < 5
RETURN
ENDIF
This.YAxis2.Reset()
THIS._yAxisWidth2 = THIS.YAxis2._Height && + THIS._ScaleW
THIS.YAxis2.ROTATION = 270
* Draw the main Y Axis2 caption
LOCAL lcYText2
m.lcYText2 = This.YAxis2.Caption
m.lnYaxisHeight = CEILING(This.YAxis2._Height)
m.x0 = THIS.ChartCanvas.WIDTH - THIS._RightOffset - m.ln3d - m.lnYaxisHeight + This._ScaleW2 + 6
THIS.YAxis2._DrawString(x0, m.y1 + m.lnYaxisWidth2, m.lnYaxisWidth2, m.lnYAxisHeight)
ENDIF
ENDIF && tnIndex = 2
LOCAL lnMaxValue
m.lnMaxValue = THIS._ScaleRange
WITH _SCREEN.SYSTEM.Drawing
* Draw the Y Axis
IF m.tnIndex = 2
m.x0 = THIS.ChartCanvas.WIDTH - THIS._RightOffset - m.ln3d + 2 - THIS._yAxisWidth2
ELSE
m.x0 = THIS._yAxisWidth + THIS._LeftOffset
ENDIF
m.x1 = m.x0 + m.ln3d + THIS._ScaleW
IF m.ln3d = 0
m.loGfx.DrawLine(m.loPen, m.x0 - 1, m.y0, m.x0 - 1, m.y1)
ELSE
LOCAL laPoints(4)
m.laPoints(1) = .POINT.New(m.x0, m.y0)
m.laPoints(2) = .POINT.New(m.x0, THIS._TopOffSet + m.ln3d)
m.laPoints(3) = .POINT.New(m.x0 + m.ln3d, THIS._TopOffSet)
m.laPoints(4) = .POINT.New(m.x0 + m.ln3d, m.y0 - m.ln3d)
m.loGfx.FillPolygon(m.loBrush, @m.laPoints)
m.loGfx.DrawPolygon(m.loPen, @m.laPoints)
LOCAL laPointsB(6)
m.laPointsB(1) = .POINT.New(m.x0, m.y0 + 4)
m.laPointsB(2) = .POINT.New(m.x0 - 4, m.y0 + 4)
m.laPointsB(3) = .POINT.New(m.x0 - 4, THIS._TopOffSet + m.ln3d)
m.laPointsB(4) = .POINT.New(m.x0 - 4 + m.ln3d, THIS._TopOffSet)
m.laPointsB(5) = .POINT.New(m.x0 + m.ln3d, THIS._TopOffSet)
m.laPointsB(6) = .POINT.New(m.x0, THIS._TopOffSet + m.ln3d)
m.loGfx.FillPolygon(m.loBrush, @m.laPointsB)
m.loGfx.DrawPolygon(m.loPen, @m.laPointsB)
ENDIF
ENDWITH
ENDIF
ENDPROC
PROCEDURE _drawyaxislegend
* Draws the Y axis legends and the chart background horizontal lines and bars
LOCAL lnHeight as Number, ;
lnXWidth as Number
IF EMPTY(This.FieldAxis2)
RETURN
ENDIF
SELECT(This._DataCursor)
* Draw Legends on the Y Axis
LOCAL x1, y1, lcText
m.y1 = This.ChartCanvas.Height - This._XAxisHeight + 6
This.AxisLegend2._Setup()
* Save original Alignment settings
LOCAL lnOrigAlignment
m.lnOrigAlignment = This.AxisLegend2.Alignment
* Force Right alignment
This.AxisLegend2.Alignment = 1 && Right
SCAN
* Measure the legend width
m.lcText = cAxis2
This.AxisLegend2.Caption = m.lcText
m.x1 = This._Yaxiswidth + This._LeftOffset - 6
m.y1 = This._aPoints(RECNO(),2) - This.AxisLegend2._Height / 2
This.AxisLegend2._DrawString(m.x1, m.y1)
ENDSCAN
* Restore original Alignment settings
This.AxisLegend2.Alignment = m.lnOrigAlignment
* There's no need to continue drawing scales if the Axis is not present
IF NOT This.ShowAxis
RETURN
ENDIF
* Continue drawing the scales and background lines or bars
LOCAL ln3D
m.ln3D = This._3d
LOCAL lnRectColor, lnLineColor
IF This.BrushType = 3 && Monochrome
m.lnRectColor = RGB(255,255,255) && White
m.lnLineColor = 0 && Black
ELSE
m.lnRectColor = This.ScaleBackColor
m.lnLineColor = This.ScaleLineColor
ENDIF
* A thin black pen to draw the ticks in the Y Axis
LOCAL loBlackPen as xfcPen
m.loBlackPen = This._oBlackPen
LOCAL loBackBrush as xfcSolidBrush
LOCAL loBackPen as xfcPen
LOCAL loPen as xfcPen
LOCAL lnDashValue
LOCAL loGfx as xfcGraphics
m.loGfx = This.oGfx
WITH _Screen.System.Drawing
m.loBackBrush = .SolidBrush.New(.Color.FromARGB(This.ScaleBackAlpha, m.lnRectColor))
m.loBackPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, m.lnLineColor),This.ScaleBackLinesWidth - 1)
m.lnDashValue = This.ScaleBackLinesDash
IF m.lnDashValue > 0
m.loBackPen.DashStyle = m.lnDashValue && _Screen.System.Drawing.Drawing2D.DashStyle.Dash
ENDIF
LOCAL lnAxisBorderColor
m.lnAxisBorderColor = This.ChangeColor(This.AxisColor, -30)
LOCAL loAxisBorderColor as xfcColor
m.loAxisBorderColor = .Color.FromARGB(This.AxisAlpha, m.lnAxisBorderColor)
m.loPen = .Pen.New(m.loAxisBorderColor, 1)
ENDWITH
m.lnHeight = This.ChartCanvas.Height - This._XAxisHeight - This._TopOffSet - m.ln3D
m.lnXWidth = This.ChartCanvas.Width - This._LeftOffset - This._RightOffset - This._yAxisWidth - m.ln3D
LOCAL x0, y0, n, y, llDrawBack
m.llDrawBack = .T.
m.y0 = This.ChartCanvas.Height - This._XAxisHeight
m.x0 = This._yAxisWidth + This._LeftOffset
LOCAL lnOneScale
IF This._nRecords = 1
m.lnOneScale = 0
ELSE
m.lnOneScale = This._aPoints(2,2) - This._aPoints(1,2)
ENDIF
FOR m.n = 1 TO This._nRecords
m.x1 = This._yAxisWidth + This._LeftOffset
m.y1 = This._aPoints(m.n,2)
m.y = ROUND(m.y1,0)
* Draw the tic mark
IF This.ShowAxis2Tics
m.loGfx.DrawLine(m.loBlackPen, m.x0 - 0, m.y, m.x0 - This.TicLength, m.y)
ENDIF
IF m.n = This._nRecords
EXIT
ENDIF
m.loGfx.DrawLine(m.loPen, m.x0, m.y, m.x0 + m.ln3D, m.y - m.ln3D)
* Draw the scale background
LOCAL x1Scale, y1Scale
m.x1Scale = m.x0 + m.ln3D
m.y1Scale = m.y - m.ln3D
IF m.llDrawBack
IF INLIST(This.ScaleBackBarsType, 1, 3) && Horizontal, Both
m.loGfx.FillRectangle(m.loBackBrush, m.x1Scale, m.y1Scale, m.lnxWidth, m.lnOneScale)
ENDIF
ENDIF
IF INLIST(This.ScaleBackLinesType, 1, 3) && Horizontal, Both
IF m.n = 1
m.loGfx.DrawLine(m.loBackPen, m.x1Scale, (m.y1Scale), m.x1Scale + m.lnxWidth, (m.y1Scale))
ENDIF
m.loGfx.DrawLine(m.loBackPen, m.x1Scale, (m.y1Scale + m.lnOneScale), m.x1Scale + m.lnxWidth, (m.y1Scale + m.lnOneScale))
ENDIF
m.llDrawBack = NOT m.llDrawBack
ENDFOR
RETURN
ENDPROC
PROCEDURE _getadjustedangle
LPARAMETERS tnAngle, tnWidth, tnHeight
IF m.tnAngle > 360
m.tnAngle = m.tnAngle - 360
ENDIF
IF m.tnAngle < 0
m.tnAngle = m.tnAngle + 360
ENDIF
* Fix by Christof Wollenhaupt 2008-10-28
* http://www.codeplex.com/VFPX/WorkItem/View.aspx?WorkItemId=19211
* when the angle is around 270.0000001, this passes the test of BETWEEN(tnAngle,90,270),
* but fails on the following TAN() function.
m.tnAngle = ROUND(m.tnAngle, 4)
LOCAL lnNewAngle
DO CASE
CASE BETWEEN(m.tnAngle, 90, 270)
m.lnNewAngle = RTOD(ATN2(TAN(DTOR(m.tnAngle)) * m.tnHeight, m.tnWidth)) + 180
OTHERWISE
m.lnNewAngle = RTOD(ATN2(TAN(DTOR(m.tnAngle)) * m.tnHeight, m.tnWidth))
ENDCASE
IF m.lnNewAngle < 0
m.lnNewAngle = m.lnNewAngle + 360
ENDIF
IF m.lnNewAngle - m.tnAngle > 170
m.lnNewAngle = m.lnNewAngle - 180
ENDIF
RETURN m.lnNewAngle
ENDPROC
PROCEDURE _getbasiccolor
* From LMGRAPH, from Luis Maria Guayan, MVP, Argentina
* www.portalfox.com
LPARAMETERS tn
LOCAL la(28)
m.tn = MOD(m.tn-1,28)+1
m.la(1) = RGB(255,0,0) && Rojo
m.la(2) = RGB(255,255,0) && Amarillo
m.la(3) = RGB(0,0,255) && Azul
m.la(4) = RGB(0,128,0) && Verde Oscuro
m.la(5) = RGB(255,128,0) && Anaranjado
m.la(6) = RGB(255,0,255) && Magenta
m.la(7) = RGB(128,0,255) && Violeta
m.la(8) = RGB(0,255,255) && Cyan
m.la(9) = RGB(128,64,0) && Marr<72>n
m.la(10) = RGB(192,192,0) && Amarillo Oscuro
m.la(11) = RGB(192,0,0) && Rojo Oscuro
m.la(12) = RGB(0,255,0) && Verde
m.la(13) = RGB(0,0,128) && Azul Oscuro
m.la(14) = RGB(255,192,0) && Anaranjado Claro
m.la(15) = RGB(0,192,255) && Azul claro
m.la(16) = RGB(128,128,0) && Marr<72>n Claro
m.la(17) = RGB(255,192,255) && Magenta Claro
m.la(18) = RGB( 64,128,128) && Verde Azulado
m.la(19) = RGB(255,0,128) && Fucsia
m.la(20) = RGB(255,255,192) && Amarillo Claro
m.la(21) = RGB(192,0,255) && Violeta Claro
m.la(22) = RGB(192,255,192) && Verde Claro
m.la(23) = RGB(128,0,128) && Violeta Oscuro
m.la(24) = RGB(192,255,255) && Cyan Claro
m.la(25) = RGB(128,128,128) && Gris Oscuro
m.la(26) = RGB(255,255,255) && Blanco
m.la(27) = RGB(192,192,192) && Gris
m.la(28) = RGB(0,0,0) && Negro
RETURN m.la(m.tn)
ENDPROC
PROCEDURE _getcenterpoint
LPARAMETERS tnX, tnY, tnWidth, tnHeight
* Calculate positions
LOCAL lnCenterX, lnCenterY
m.lnCenterX = (m.tnWidth / 2)
m.lnCenterY = (m.tnHeight / 2)
* Create a GraphicsPath object.
LOCAL lnAngle, lnDistance, xAdjust, yAdjust
m.lnAngle = This.PieGradCenterAngle
LOCAL loTempPath as xfcGraphicsPath
LOCAL loPoint as xfcPointF
LOCAL loRect as xfcRectangle
m.loTempPath = _Screen.System.Drawing.Drawing2D.GraphicsPath.New()
* Obtaining the needed points
m.lnDistance = This.PieGradCenterDistance
m.xAdjust = (1 - m.lnDistance) / 2
m.yAdjust = (1 - m.lnDistance) / 2
m.loRect = _Screen.System.Drawing.Rectangle.New(m.tnX + m.xAdjust * m.tnWidth, ;
m.tnY + m.yAdjust * m.tnHeight, ;
m.lnDistance * m.tnWidth, ;
m.lnDistance * m.tnHeight)
m.loTempPath.AddArc(m.loRect, m.lnAngle, 0.0001)
m.loPoint = m.loTempPath.GetLastPoint()
RETURN m.loPoint
ENDPROC
PROCEDURE _getchartprop
Lparameters toPropertiesList, tcProperty, tnType, toSavedProps, lcDescription, tlShowDescriptions
Local lcCRLF
Local lcName as String, ;
lcType as String, ;
lcValue as String, ;
lxValue
m.lcCRLF = Chr(13)
Local lbChanged, lcNewType, lcOldType, lnBlue, lnDope, lnGreen, lnPos, lnRed
Do Case
Case m.tnType = 1
m.lbChanged = .T.
Case m.tnType = 2
If "." $ m.tcProperty
m.lnPos = Rat (".", m.tcProperty)
m.lbChanged = Pemstatus ( Evaluate ("This." + Left(m.tcProperty, m.lnPos - 1)), Substr(m.tcProperty, m.lnPos + 1), 0)
Else
m.lbChanged = Pemstatus(This, m.tcProperty, 5) And Pemstatus(This, m.tcProperty, 0)
* lbChanged = Pemstatus (This, tcProperty, 0)
Endif
Case m.tnType = 3
m.lcNewType = Vartype(Evaluate("toPropertiesList." + m.tcProperty))
m.lcOldType = Vartype(Evaluate("toSavedProps." + m.tcProperty))
m.lbChanged = (m.lcNewType # m.lcOldType) Or Not ;
EVALUATE("toPropertiesList." + m.tcProperty) == Evaluate("toSavedProps." + m.tcProperty)
Endcase
If Not m.lbChanged
Return ''
Endif
m.lcName = Trim(m.tcProperty)
m.lxValue = Evaluate ("toPropertiesList." + m.tcProperty)
m.lcType = Vartype (m.lxValue)
Do Case
Case m.lcType = 'C'
m.lxValue = Trim(m.lxValue)
Do Case
Case Not ['] $ m.lxValue
m.lcValue = ['] + m.lxValue + [']
Case Not ["] $ lxValue
m.lcValue = ["] + m.lxValue + ["]
Otherwise
m.lcValue = '[' + m.lxValue + ']'
Endcase
Case m.lcType = "O"
m.lcValue = " " + Chr(38) + Chr(38) + "Custom object - " + m.lxValue.Name
Return "* ." + m.lcName + " = " + m.lcValue + m.lcCRLF
Case m.lcType = "N"
LOCAL lcUpName
m.lcUpName = UPPER(m.lcName)
m.lnDope = At('***', m.lcDescription)
If Inlist(ALLTRIM(Right('.' + m.lcUpName,10)), ;
'.FORECOLOR', '.BACKCOLOR') Or ;
('BACKCOLOR2' $ m.lcUpName) OR ;
(').COLOR' $ m.lcUpName) OR ;
(m.lnDope > 0 And "COLOR" == Upper(Alltrim(Substr(m.lcDescription, m.lnDope + 3))))
m.lnRed = Bitand(m.lxValue, 255)
m.lnGreen = Bitrshift(Bitand(m.lxValue, 256 * 255), 8)
m.lnBlue = Bitrshift(Bitand(m.lxValue, 256 * 256 * 255), 16)
m.lcValue = 'RGB(' + Transform(m.lnRed) + ',' + Transform(m.lnGreen) + ',' + Transform(m.lnBlue) + ')'
Else
m.lcValue = Transform(m.lxValue)
Endif
Otherwise
m.lcValue = Transform(m.lxValue)
Endcase
Return Iif (Empty (m.lcDescription) or not m.tlShowDescriptions, '', '* ' + m.lcDescription + m.lcCRLF) + "." + m.lcName + " = " + m.lcValue + m.lcCRLF
ENDPROC
PROCEDURE _getchartproperties
****************************************************************
* Jim Nelson 10/20/2008
*
* Returns an object with current settings of all FoxCharts properties
Local loProperties
Local laProperties(1), laSubProperties(1), lcProperty
Local lcProperties, lcName, lcType, loObject, lnI, lnJ, laFieldMembers(1), lcFieldMem, loData
Local luPropValue, lcPropType
Local loFields as "Collection"
m.loProperties = Createobject("Empty")
m.lcProperties = "Format, FontName, FontSize, FontBold, FontItalic, FontUnderline, FontCharSet, ForeColor, ForeColorAlpha, BackColor, BackColorAlpha, Alignment, Rotation, RotationCenter"
Alines (laSubProperties, m.lcProperties, 5, ',')
With This
Local laProperties(1), lcProperty
Amembers(m.laProperties, This, 3)
AddProperty (m.loProperties, "_Descriptions(1)", m.laProperties)
Acopy(m.laProperties, m.loProperties._Descriptions)
For m.lnI = 1 To Alen (m.laProperties,1)
m.lcName = Proper(m.laProperties(m.lnI,1))
m.lcType = Proper(m.laProperties(m.lnI,2))
Do Case
Case m.lcType = 'Property' ; && the list of ReadOnly properties
And Not Inlist (Upper (m.lcName), "VERSION", "VERSIONA", "CHARTSUM", ;
"OBMP", "OGFX", "ACOORD", "ACOLORS", "SINGLEDATA", ;
"CURRINDEX", "CURRVALUE", "CURRLEGEND", "CURROBJTYPE", ;
"CURRCOLUMN", "CURRRECNO", "LEGEND1", "COLOR1", "FIELDVALUE1", "SHAPE1",;
"CHARTTYPE1", "SHOWVALUESONSHAPE1", "FIELDXAXIS", "APALETTECOLORS", "DEBUG") ;
and "_" # Left(m.lcName, 1) ;
And (Pemstatus(This, m.lcName, 4) Or ;
Inlist( Upper(m.lcName), 'BACKCOLOR', 'FORECOLOR', 'MARGIN', 'SHOWTIPS', 'WIDTH', 'HEIGHT'))
AddProperty (m.loProperties, m.lcName, Evaluate ("This." + m.lcName))
Case m.lcName = 'Fields'
m.loFields = Createobject("Collection")
For m.lnJ = 1 To This.Fields.Count
m.loData = Createobject("Empty")
Amembers(laFieldMembers, This.Fields(m.lnJ))
For Each m.lcFieldMem In m.laFieldMembers
m.luPropValue = Evaluate("This.Fields(lnJ)." + m.lcFieldMem)
m.lcPropType = VARTYPE(m.luPropValue)
IF (m.lcFieldMem = "CHARTTYPE" AND m.lcPropType = "N" AND m.luPropValue = 0) OR ;
(m.lcFieldMem = "SHOWVALUESONSHAPE" AND m.lcPropType = "L" AND m.luPropValue = .T.) OR ;
(m.lcFieldMem = "SHAPE" AND m.lcPropType = "N" AND m.luPropValue = 0)
LOOP
ENDIF
AddProperty(m.loData, m.lcFieldMem, m.luPropValue)
Endfor
m.loFields.Add(m.loData)
Next m.lnJ
AddProperty (m.loProperties, m.lcName, m.loFields)
Case m.lcType = 'Object' ;
and Inlist (m.lcName, "Title", "Subtitle", "Xaxis", "Axislegend2", "Yaxis", "Shapelegend", "Scalelegend", "Sidelegend", "Yaxis2")
* create an object
AddProperty (m.loProperties, m.lcName, Createobject("Empty"))
m.loObject = Evaluate ("loProperties." + m.lcName)
* conditionally add caption
If Not Inlist (m.lcName, "Axislegend2", "Shapelegend", "Scalelegend", "Sidelegend")
AddProperty (m.loObject, "Caption", Evaluate ("This." + m.lcName + ".Caption"))
Endif
* and add other properties of that objecgt
For Each m.lcProperty In m.laSubProperties
AddProperty (m.loObject, m.lcProperty, Evaluate ("This." + m.lcName + "." + m.lcProperty))
Endfor
Endcase
Endfor
Endwith
Return m.loProperties
ENDPROC
PROCEDURE _getchartscript && Returns a complete script to reproduce the current chart in a separate PRG.
LOCAL loChart AS FoxCharts OF "FoxCharts.vcx"
Local laFields[1], ;
lcField as String
m.loChart = This
LOCAL lcSource, lcCRLF, lcTAB, n, i
m.lcCRLF = CHR(13) + CHR(10)
m.lcTAB = CHR(9)
m.lcSource = m.loChart.SourceAlias
SELECT (m.lcSource)
* If using Random colors, convert the chart to custom colors,
* and set the colors to the same of the current chart
IF m.loChart.ColorType = 2 && Random
m.loChart.ColorType = 1 && Custom colors
IF m.loChart.SingleData
SELECT (m.lcSource)
SCAN
REPLACE (m.lcSource + "." + ALLTRIM(m.loChart.FieldColor)) WITH m.loChart.aColors(RECNO())
ENDSCAN
ELSE
FOR m.n = 1 TO m.loChart.ChartsCount
m.loChart.Fields(m.n).Color = m.loChart.aColors(m.n)
ENDFOR
ENDIF
ENDIF
LOCAL lcAlias, lcFldType, lcSQL, lnFields, lcFldName, lcFldType, lnFldInteger, lnFldDecimals
m.lcAlias = ALLTRIM(m.lcSource) && "TempCursor"
m.lcSQL = "CREATE CURSOR " + m.lcAlias + "( ;" + m.lcCRLF
m.lnFields = AFIELDS(laFields, m.lcSource) && Create array.
m.lcField = ""
FOR m.n = 1 TO m.lnFields
m.lcFldName = m.laFields(m.n,1)
m.lcFldType = m.laFields(m.n,2)
m.lnFldInteger = m.laFields(m.n,3)
m.lnFldDecimals = m.laFields(m.n,4)
m.lcField = m.lcField + ;
m.lcTAB + ;
m.lcFldName + " " + m.lcFldType + ;
IIF(m.lnFldInteger = 0 or INLIST(m.lcFldType,"I", "L", "D", "T", "M", "W"), " ", " (" + TRANSFORM(m.lnFldInteger) + ;
IIF(m.lnFldDecimals = 0, ")", "," + TRANSFORM(m.lnFldDecimals) + ")") ) + ;
" NULL , ;" + m.lcCRLF
ENDFOR
m.lcField = LEFT(m.lcField, LEN(m.lcField) -5 )
m.lcSQL = m.lcSQL + m.lcField + ')' + m.lcCRLF + m.lcCRLF
LOCAL lcInserts, lcFields, i, luValue, lcType, lcExpr, lcScript, lcChartScript
m.lcInserts = ""
SCAN
m.lcFields = ""
FOR m.i = 1 TO m.lnFields
m.luValue = EVALUATE(TRANSFORM(FIELD(m.I)))
m.lcType = VARTYPE(m.luValue)
DO CASE
CASE ISNULL(m.luValue)
m.lcExpr = "NULL"
CASE m.lcType = "C"
m.lcExpr = ["] + ALLTRIM(m.luValue) + ["]
CASE m.lcType = "L"
m.lcExpr = TRANSFORM(m.luValue)
CASE m.lcType = "N"
m.lcExpr = TRANSFORM(m.luValue)
OTHERWISE
ENDCASE
m.lcFields = m.lcFields + m.lcExpr + ", "
ENDFOR
m.lcFields = LEFT(m.lcFields, LEN(m.lcFields) -2)
m.lcInserts = m.lcInserts + 'INSERT INTO ' + m.lcAlias + " VALUES (" + m.lcFields + ")" + m.lcCRLF
ENDSCAN
m.lcScript = m.lcSQL + m.lcInserts
LOCAL lcChartScript, lcFormInit, lcFormEnd
m.lcChartScript = m.loChart.GetChartProperties(2) && Only non default properties
TEXT TO m.lcFormInit NOSHOW
SET CLASSLIB TO LOCFILE("FoxCharts.vcx")
PUBLIC oForm as Form
oForm = CREATEOBJECT("Form")
oForm.Newobject("oChart", "FoxCharts", "FoxCharts.vcx")
LOCAL loChart as FoxCharts OF "FoxCharts.vcx"
m.loChart = oForm.oChart
WITH m.loChart
ENDTEXT
TEXT TO m.lcFormEnd NOSHOW
m.loChart.DrawChart()
m.loChart.Visible = .T.
ENDWITH
oForm.Width = m.loChart.Width
oForm.Height = m.loChart.Height
oForm.Show()
ENDTEXT
LOCAL lcFullScript
m.lcFullScript = m.lcScript + m.lcCRLF + m.lcCRLF + m.lcFormInit + m.lcChartScript + m.lcFormEnd
RETURN m.lcFullScript
ENDPROC
PROCEDURE _getcursorpos
LPARAMETERS tnX, tnY
* This works better than using MROW() and MCOL() when FoxCharts is not at the active window
LOCAL lqPoint AS String
DECLARE INTEGER GetCursorPos IN win32api AS FoxCharts_GetCursorPos STRING @lqPoint
m.lqPoint = 0h0000000000000000
FoxCharts_GetCursorPos(@m.lqPoint)
m.tnx = CTOBIN(SUBSTR(m.lqPoint, 1, 4), "4rs")
m.tny = CTOBIN(SUBSTR(m.lqPoint, 5, 4), "4rs")
ENDPROC
PROCEDURE _getfieldtype
LPARAMETERS tcAlias, tcField, tlMask
LOCAL gnFieldcount, lnCount, lcCurrField, lnInteger, lnDecimals, lcType
LOCAL ARRAY gaMyArray[1]
m.gnFieldcount = AFIELDS(gaMyArray, m.tcAlias) && Create array.
FOR m.lnCount = 1 TO m.gnFieldcount
m.lcCurrField = ALLTRIM(m.gaMyArray(m.lnCount,1)) && Display field names.
IF UPPER(m.lcCurrField) = ALLTRIM(UPPER(m.tcField))
m.lnInteger = m.gaMyArray(m.lnCount,3)
m.lnDecimals = m.gaMyArray(m.lnCount,4)
IF m.tlMask && Return the mask for the format property
m.lcType = REPLICATE("9", m.lnInteger) + ;
IIF(m.lnDecimals > 0, "." + REPLICATE("9", m.lnDecimals), "")
ELSE && Return the field type - eg N(8,2)
m.lcType = "N(" + ALLTRIM(STR(m.lnInteger)) + "," + ALLTRIM(STR(m.lnDecimals)) + ")"
ENDIF
EXIT
ENDIF
ENDFOR
RETURN m.lcType
*!* Column number Field info Data type
*!* 1
*!* Field name
*!* Character
*!*
*!* 2
*!* Field type:
*!* C = Character
*!* Y = Currency
*!* D = Date
*!* T = DateTime
*!* B = Double
*!* F = Float
*!* G = General
*!* I = Integer
*!* L = Logical
*!* M = Memo
*!* N = Numeric
*!* Q = Varbinary
*!* V = Varchar and Varchar (Binary)
*!* W = Blob Character
*!*
*!* 3
*!* Field width
*!* Numeric
*!*
*!* 4
*!* Decimal places
*!* Numeric
ENDPROC
PROCEDURE _getgradientcolor
LPARAMETERS tnCount
LOCAL lnBasicColor, lnNewColor
m.lnBasicColor = This.Fields(1).Color
m.tnCount = m.tnCount - 1
IF INLIST(This.ChartType, 5, 6) && Line or Area
m.lnNewColor = This.ChangeColor(lnBasicColor, 100 * m.tnCount / This.ChartsCount)
ELSE
m.lnNewColor = This.ChangeColor(lnBasicColor, 100 * m.tnCount / This._nRecords)
ENDIF
RETURN m.lnNewColor
ENDPROC
PROCEDURE _getpalettecolor
LPARAMETERS tnPalette, tnIndex
LOCAL lnPosition, lnMaxColors
m.lnPosition = (m.tnPalette * 8) + m.tnIndex
m.lnMaxColors = This._PaletteColors
IF m.lnPosition > m.lnMaxColors
m.lnPosition = m.lnPosition - m.lnMaxColors
ENDIF
RETURN This.aPaletteColors(m.lnPosition)
ENDPROC
PROCEDURE _getrandomcolor
RETURN RGB(;
INT(RAND() * 255), ;
INT(RAND() * 255), ;
INT(RAND() * 255))
ENDPROC
PROCEDURE _getrelativepositions
IF This._InsideForm
This._xRelative = This._OBJTOCLIENTex(This, 2) && Left
This._yRelative = This._OBJTOCLIENTex(This, 1) && Top
ELSE
This._xRelative = OBJTOCLIENT(This, 2) && Left
This._yRelative = OBJTOCLIENT(This, 1) && Top
ENDIF
ENDPROC
PROCEDURE _getrgb
LPARAMETERS tuColor
Local lnColor as Number
IF VARTYPE(m.tuColor) = "N"
RETURN m.tuColor
ENDIF
IF VARTYPE(m.tuColor) = "C"
DO CASE
CASE LEFT(m.tuColor,1) = "="
m.lnColor = EVALUATE(SUBSTR(m.tuColor,2))
CASE EMPTY(m.tuColor)
m.lnColor = 0
OTHERWISE
m.lnColor = EVALUATE("RGB(" + m.tuColor + ")")
ENDCASE
RETURN m.lnColor
ENDIF
ENDPROC
PROCEDURE _getshapepath
LPARAMETERS tnShape
WITH _Screen.System.Drawing
LOCAL loPath as xfcGraphicsPath
m.loPath = _Screen.System.Drawing.Drawing2D.GraphicsPath.New()
m.loPath.StartFigure()
LOCAL lnShape, lcType
m.lcType = VARTYPE(m.tnShape)
IF m.lcType = "N"
IF m.tnShape = 0 && NO shape selected - go in Automatic mode
m.lnShape = This._ChartIndex
ELSE
m.lnShape = m.tnShape
ENDIF
ENDIF
DO CASE
CASE m.lcType = "O"
m.loPath = m.tnShape
CASE m.lnShape = 1 && Round
m.loPath.AddEllipse(0, 0, 6, 6)
CASE m.lnShape = 2 && Square
m.loPath.AddRectangle(0,0,6,6)
CASE m.lnShape = 3 && Triangle
LOCAL laPoints(3)
m.laPoints(1) = .Point.New(3,0)
m.laPoints(2) = .Point.New(0,6)
m.laPoints(3) = .Point.New(6,6)
m.loPath.AddPolygon(@m.laPoints)
CASE m.lnShape = 4 && Cross
m.loPath.AddLine(2,0, 4,0)
m.loPath.AddLine(4,0, 4,2)
m.loPath.AddLine(4,2, 6,2)
m.loPath.AddLine(6,2, 6,4)
m.loPath.AddLine(6,4, 4,4)
m.loPath.AddLine(4,4, 4,6)
m.loPath.AddLine(4,6, 2,6)
m.loPath.AddLine(2,6, 2,4)
m.loPath.AddLine(2,4, 0,4)
m.loPath.AddLine(0,4, 0,2)
m.loPath.AddLine(0,2, 2,2)
m.loPath.AddLine(2,2, 2,0)
CASE m.lnShape = 5 && Star
LOCAL lnRadius, lnPi, lnRadian72, n
m.lnRadius = 6.0
m.lnPi = 3.141592
m.lnRadian72 = (m.lnPi * 4.0 ) / 5.0
LOCAL laPoints(5), n
FOR m.n = 1 TO 5
m.laPoints(m.n) = .Point.New(;
+ m.lnRadius * SIN( m.n * m.lnRadian72 ) + 3, ;
- m.lnRadius * COS( m.n * m.lnRadian72 ) + 2)
ENDFOR
m.loPath.AddPolygon(@m.laPoints)
m.loPath.FillMode = _Screen.System.Drawing.Drawing2D.FillMode.Winding
CASE m.lnShape = 6 && Cross 2
m.loPath.AddRectangle(0,0,7,7)
m.loPath.AddRectangle(1,1,2,2)
m.loPath.AddRectangle(4,1,2,2)
m.loPath.AddRectangle(1,4,2,2)
m.loPath.AddRectangle(4,4,2,2)
CASE m.lnShape = 7 && Box
m.loPath.FillMode = _Screen.System.Drawing.Drawing2D.FillMode.Alternate
m.loPath.AddRectangle(0,0,6,6)
m.loPath.AddRectangle(2,2,2,2)
CASE m.lnShape = 8 && Button
m.loPath.AddEllipse(0, 0, 6, 6)
m.loPath.StartFigure()
m.loPath.AddEllipse(2,2,2,2)
m.loPath.FillMode = _Screen.System.Drawing.Drawing2D.FillMode.Alternate
CASE m.lnShape = 9 && Box2
m.loPath.AddLine(9,0,6,5)
m.loPath.AddLine(6,5,10,4)
m.loPath.AddLine(10,4,2,10)
m.loPath.AddLine(2,10,3,5)
m.loPath.AddLine(3,5,0,6)
m.loPath.AddLine(0,6,6,0)
m.loPath.AddLine(6,0,9,0)
CASE m.lnShape = 10 && Small Man
m.loPath.AddEllipse(3, 0, 3, 3)
m.loPath.AddLine(2, 4, 8, 4)
m.loPath.AddLine(10, 10, 8, 10)
m.loPath.AddLine(7, 6, 7, 10)
m.loPath.AddLine(9, 19, 7, 19)
m.loPath.AddLine(5, 12, 4, 19)
m.loPath.AddLine(2, 19, 3, 10)
m.loPath.AddLine(3, 6, 2, 10)
m.loPath.AddLine(0, 10, 2, 4)
CASE m.lnShape = 55 && Big Man
m.loPath.AddEllipse(23, 1, 14, 14)
m.loPath.AddLine(18, 16, 42, 16)
m.loPath.AddLine(50, 40, 44, 42)
m.loPath.AddLine(38, 25, 37, 42)
m.loPath.AddLine(45, 75, 37, 75)
m.loPath.AddLine(30, 50, 23, 75)
m.loPath.AddLine(16, 75, 23, 42)
m.loPath.AddLine(22, 25, 16, 42)
m.loPath.AddLine(10, 40, 18, 16)
CASE m.lnShape = 98 && GDI+X Graphics Path
CASE m.lnShape = 99 && Image
OTHERWISE
* 2013-02-21 CCHALOM
* If no valid shape number was sent, then we'll use a basic circle
* Like Shape #1 above
m.loPath.AddEllipse(0, 0, 6, 6)
ENDCASE
ENDWITH
RETURN m.loPath
ENDPROC
PROCEDURE _getvalue
LPARAMETERS tiIndex, tlAcceptNULL
LOCAL luValue, llIsNull
m.luValue = EVALUATE((This._DataCursor) + ".nValue" + This._Str(m.tiIndex))
IF ISNULL(m.luValue) AND NOT m.tlAcceptNULL
m.luValue = 0
ENDIF
RETURN m.luValue
ENDPROC
PROCEDURE _getylegendsize
LPARAMETERS tnAxis
tnAxis = EVL(tnAxis, 1)
Local lnScaleW, lnScaleH
Local lnWidth as Number
If This._Orientation = 1 && Vertical
If This.ShowScale
****************************************************************
* Jim Nelson 10/13/2008
*
* Modified to call GetScaleLegend to get representative used to calculate maximum width
LOCAL luLegend
IF tnAxis = 2
m.luLegend = TRANSFORM(This._MaxScale2)
ELSE
m.luLegend = This.GetScaleLegend(-1)
ENDIF
IF VARTYPE(m.luLegend) = "N"
This.ScaleLegend._Value = m.luLegend
ELSE
This.ScaleLegend.Caption = m.luLegend
ENDIF
m.lnScaleW = This.ScaleLegend._Width + 2
m.lnScaleH = This.ScaleLegend._Height
Else
m.lnScaleW = 0
m.lnScaleH = 0
Endif
ELSE && Horizontal
Local lnMaxWidth, lcText
Local loFont As xfcFont
Local loSize As xfcSize
This.AxisLegend2._Setup()
m.loFont = This.AxisLegend2._oFont
m.lnMaxWidth = 0
Scan
* Measure the legend width
m.lcText = cAxis2
This.AxisLegend2.Caption = m.lcText
m.lnWidth = This.AxisLegend2._Width
m.lnMaxWidth = Max(m.lnMaxWidth, m.lnWidth)
Endscan
m.lnScaleH = This.AxisLegend2._Width
m.lnScaleW = m.lnMaxWidth
Endif
IF tnAxis = 1
This._ScaleH = m.lnScaleH
This._ScaleW = m.lnScaleW
ELSE && tnAxis = 2
This._ScaleH2 = m.lnScaleH
This._ScaleW2 = m.lnScaleW
ENDIF
Return
ENDPROC
PROCEDURE _initchart
IF TYPE("Thisform.Name") = "C"
This._InsideForm = .T.
* Add the tooltips object to the form
IF NOT PEMSTATUS(Thisform, "FoxChartsToolTip", 5)
Thisform.AddObject("FoxChartsToolTip", "Label")
ENDIF
ELSE
This._InsideForm = .F.
ENDIF
This.BorderWidth = 0
This.BackStyle = 0 && Transparent
IF VARTYPE(This._3D) = "L" && Undefined
This._Using3D = .F.
This._3D = This.Depth
ELSE
This._Using3D = .T.
This.Depth = This._3D
ENDIF
* Prepare basic color objects
This._oClrBlack = _Screen.System.Drawing.Color.FromRGB(0)
This._oClrWhite = _Screen.System.Drawing.Color.FromRGB(255,255,255)
* A thin black pen to draw the ticks in the Y Axis
LOCAL loBlackPen As xfcPen
m.loBlackPen = _Screen.System.Drawing.Pen.New(This._oClrBlack, 0)
This._oBlackPen = m.loBlackPen
* Store the original Mouse Pointer
This._OrigMousePointer = This.MousePointer
* Initialize the color palettes
This._InitPalettes()
*!* * GdiPlus API call declarations
*!* * to ensure compatibility with all GdiPlusX versions
* They are being "Redeclared" here to avoid compiling errors.
DECLARE Long GdipSetPathGradientSurroundColorsWithCount IN GDIPLUS.DLL AS xfcGdipSetPathGradientSurroundColorsWithCount Long brush, String @Argb, Long @Count
DECLARE Long GdipSetPathGradientCenterPoint IN GDIPLUS.DLL AS xfcGdipSetPathGradientCenterPoint Long brush, String pPoint
This.ChartCanvas.ZOrder(0)
* Prepare the Fields collection, forcing at least 1 item
* for not obliging users to set .ChartsCount in "SingleData" charts
IF This.ChartsCount = 0
This._SetFieldsCount(1)
ENDIF
This._Started = .T.
IF _VFP.StartMode = 0
SET ASSERTS ON
ENDIF
DODEFAULT()
ENDPROC
PROCEDURE _initpalettes
LOCAL lnMaxColors
m.lnMaxColors = 184
This._PaletteColors = m.lnMaxColors
DIMENSION This.aPaletteColors(m.lnMaxColors)
WITH This
.aPaletteColors(1) = RGB(151,186,235) && In a fog
.aPaletteColors(2) = RGB(239,158,169)
.aPaletteColors(3) = RGB(214,164,225)
.aPaletteColors(4) = RGB(165,159,230)
.aPaletteColors(5) = RGB(242,199,152)
.aPaletteColors(6) = RGB(224,218,142)
.aPaletteColors(7) = RGB(166,224,144)
.aPaletteColors(8) = RGB(147,217,210)
.aPaletteColors(9) = RGB(166,141,45) && Apex
.aPaletteColors(10) = RGB(102,124,76)
.aPaletteColors(11) = RGB(52,133,162)
.aPaletteColors(12) = RGB(44,80,166)
.aPaletteColors(13) = RGB(72,51,159)
.aPaletteColors(14) = RGB(116,68,146)
.aPaletteColors(15) = RGB(222,208,153)
.aPaletteColors(16) = RGB(187,202,172)
.aPaletteColors(17) = RGB(181,88,4) && Aspect
.aPaletteColors(18) = RGB(109,24,33)
.aPaletteColors(19) = RGB(15,60,88)
.aPaletteColors(20) = RGB(51,93,42)
.aPaletteColors(21) = RGB(64,47,84)
.aPaletteColors(22) = RGB(156,113,52)
.aPaletteColors(23) = RGB(248,170,93)
.aPaletteColors(24) = RGB(209,84,97)
.aPaletteColors(25) = RGB(49,138,210) && Chameleon
.aPaletteColors(26) = RGB(203,181,112)
.aPaletteColors(27) = RGB(212,120,185)
.aPaletteColors(28) = RGB(189,223,120)
.aPaletteColors(29) = RGB(109,181,229)
.aPaletteColors(30) = RGB(212,196,136)
.aPaletteColors(31) = RGB(209,135,189)
.aPaletteColors(32) = RGB(172,202,117)
.aPaletteColors(33) = RGB(167,60,35) && Civic
.aPaletteColors(34) = RGB(148,129,0)
.aPaletteColors(35) = RGB(85,126,127)
.aPaletteColors(36) = RGB(98,85,76)
.aPaletteColors(37) = RGB(87,128,83)
.aPaletteColors(38) = RGB(173,105,36)
.aPaletteColors(39) = RGB(185,123,108)
.aPaletteColors(40) = RGB(255,228,40)
.aPaletteColors(41) = RGB(26,111,134) && Concourse
.aPaletteColors(42) = RGB(159,18,24)
.aPaletteColors(43) = RGB(172,62,11)
.aPaletteColors(44) = RGB(33,60,101)
.aPaletteColors(45) = RGB(42,44,75)
.aPaletteColors(46) = RGB(81,35,45)
.aPaletteColors(47) = RGB(92,190,216)
.aPaletteColors(48) = RGB(233,101,107)
.aPaletteColors(49) = RGB(158,47,13) && Equity / Brick
.aPaletteColors(50) = RGB(107,26,18)
.aPaletteColors(51) = RGB(112,96,66)
.aPaletteColors(52) = RGB(95,60,48)
.aPaletteColors(53) = RGB(96,85,85)
.aPaletteColors(54) = RGB(89,59,59)
.aPaletteColors(55) = RGB(235,114,76)
.aPaletteColors(56) = RGB(214,76,61)
.aPaletteColors(57) = RGB(7,71,137) && Flow
.aPaletteColors(58) = RGB(0,108,156)
.aPaletteColors(59) = RGB(5,134,41)
.aPaletteColors(60) = RGB(7,132,95)
.aPaletteColors(61) = RGB(67,146,43)
.aPaletteColors(62) = RGB(125,152,44)
.aPaletteColors(63) = RGB(66,156,240)
.aPaletteColors(64) = RGB(57,197,255)
.aPaletteColors(65) = RGB(76,124,80) && Foundry
.aPaletteColors(66) = RGB(86,139,86)
.aPaletteColors(67) = RGB(67,140,161)
.aPaletteColors(68) = RGB(123,118,94)
.aPaletteColors(69) = RGB(150,136,64)
.aPaletteColors(70) = RGB(190,61,61)
.aPaletteColors(71) = RGB(150,183,154)
.aPaletteColors(72) = RGB(182,207,182)
.aPaletteColors(73) = RGB(61,115,162) && Median
.aPaletteColors(74) = RGB(179,81,27)
.aPaletteColors(75) = RGB(109,115,73)
.aPaletteColors(76) = RGB(159,118,33)
.aPaletteColors(77) = RGB(70,111,102)
.aPaletteColors(78) = RGB(108,98,98)
.aPaletteColors(79) = RGB(165,193,217)
.aPaletteColors(80) = RGB(231,168,130)
.aPaletteColors(81) = RGB(81,150,29) && Metro
.aPaletteColors(82) = RGB(169,11,81)
.aPaletteColors(83) = RGB(181,124,1)
.aPaletteColors(84) = RGB(0,108,142)
.aPaletteColors(85) = RGB(51,75,146)
.aPaletteColors(86) = RGB(14,123,107)
.aPaletteColors(87) = RGB(162,222,117)
.aPaletteColors(88) = RGB(240,102,155)
.aPaletteColors(89) = RGB(224,165,57) && Nature
.aPaletteColors(90) = RGB(113,178,30)
.aPaletteColors(91) = RGB(207,80,34)
.aPaletteColors(92) = RGB(217,184,56)
.aPaletteColors(93) = RGB(120,211,64)
.aPaletteColors(94) = RGB(160,60,26)
.aPaletteColors(95) = RGB(9,141,8)
.aPaletteColors(96) = RGB(165,165,0)
.aPaletteColors(97) = RGB(49,116,216) && Northern lights
.aPaletteColors(98) = RGB(215,59,165)
.aPaletteColors(99) = RGB(75,202,249)
.aPaletteColors(100) = RGB(205,45,222)
.aPaletteColors(101) = RGB(142,184,242)
.aPaletteColors(102) = RGB(238,139,207)
.aPaletteColors(103) = RGB(147,213,244)
.aPaletteColors(104) = RGB(212,115,222)
.aPaletteColors(105) = RGB(46,89,140) && Office
.aPaletteColors(106) = RGB(138,45,43)
.aPaletteColors(107) = RGB(102,130,47)
.aPaletteColors(108) = RGB(77,58,101)
.aPaletteColors(109) = RGB(38,115,137)
.aPaletteColors(110) = RGB(207,89,6)
.aPaletteColors(111) = RGB(134,168,208)
.aPaletteColors(112) = RGB(215,148,145)
.aPaletteColors(113) = RGB(132,138,70) && Opulent
.aPaletteColors(114) = RGB(124,56,139)
.aPaletteColors(115) = RGB(162,62,20)
.aPaletteColors(116) = RGB(194,123,4)
.aPaletteColors(117) = RGB(154,44,104)
.aPaletteColors(118) = RGB(208,82,3)
.aPaletteColors(119) = RGB(206,112,144)
.aPaletteColors(120) = RGB(204,159,213)
.aPaletteColors(121) = RGB(71,80,115) && Origin
.aPaletteColors(122) = RGB(71,113,149)
.aPaletteColors(123) = RGB(161,172,41)
.aPaletteColors(124) = RGB(228,167,5)
.aPaletteColors(125) = RGB(129,77,60)
.aPaletteColors(126) = RGB(93,73,67)
.aPaletteColors(127) = RGB(154,162,187)
.aPaletteColors(128) = RGB(174,195,213)
.aPaletteColors(129) = RGB(106,127,83) && Paper
.aPaletteColors(130) = RGB(205,109,10)
.aPaletteColors(131) = RGB(169,131,15)
.aPaletteColors(132) = RGB(153,60,90)
.aPaletteColors(133) = RGB(94,64,135)
.aPaletteColors(134) = RGB(61,96,140)
.aPaletteColors(135) = RGB(189,201,176)
.aPaletteColors(136) = RGB(246,190,124)
.aPaletteColors(137) = RGB(225,102,82) && Pastel Kit
.aPaletteColors(138) = RGB(49,141,206)
.aPaletteColors(139) = RGB(239,203,78)
.aPaletteColors(140) = RGB(147,219,103)
.aPaletteColors(141) = RGB(177,223,252)
.aPaletteColors(142) = RGB(244,140,77)
.aPaletteColors(143) = RGB(145,111,189)
.aPaletteColors(144) = RGB(189,189,189)
.aPaletteColors(145) = RGB(34,100,117) && Solstice
.aPaletteColors(146) = RGB(195,133,1)
.aPaletteColors(147) = RGB(131,25,26)
.aPaletteColors(148) = RGB(80,107,28)
.aPaletteColors(149) = RGB(97,39,2)
.aPaletteColors(150) = RGB(44,58,95)
.aPaletteColors(151) = RGB(97,179,199)
.aPaletteColors(152) = RGB(255,206,91)
.aPaletteColors(153) = RGB(244,213,46) && Technic
.aPaletteColors(154) = RGB(68,117,134)
.aPaletteColors(155) = RGB(140,118,4)
.aPaletteColors(156) = RGB(86,83,110)
.aPaletteColors(157) = RGB(68,80,55)
.aPaletteColors(158) = RGB(105,96,70)
.aPaletteColors(159) = RGB(82,87,94)
.aPaletteColors(160) = RGB(152,186,197)
.aPaletteColors(161) = RGB(217,98,64) && Terracotta
.aPaletteColors(162) = RGB(174,139,76)
.aPaletteColors(163) = RGB(212,121,18)
.aPaletteColors(164) = RGB(252,193,168)
.aPaletteColors(165) = RGB(240,227,176)
.aPaletteColors(166) = RGB(247,204,116)
.aPaletteColors(167) = RGB(231,146,122)
.aPaletteColors(168) = RGB(186,156,101)
.aPaletteColors(169) = RGB(126,195,71) && Trees
.aPaletteColors(170) = RGB(208,153,62)
.aPaletteColors(171) = RGB(230,220,78)
.aPaletteColors(172) = RGB(191,238,103)
.aPaletteColors(173) = RGB(83,210,136)
.aPaletteColors(174) = RGB(184,161,43)
.aPaletteColors(175) = RGB(172,69,28)
.aPaletteColors(176) = RGB(79,192,63)
.aPaletteColors(177) = RGB(255,44,122)
.aPaletteColors(178) = RGB(224,0,85)
.aPaletteColors(179) = RGB(163,0,57)
.aPaletteColors(180) = RGB(102,0,81)
.aPaletteColors(181) = RGB(62,0,78)
.aPaletteColors(182) = RGB(0,55,139)
.aPaletteColors(183) = RGB(0,31,108)
.aPaletteColors(184) = RGB(255,105,167)
ENDWITH
ENDPROC
PROCEDURE _newfield
LOCAL loData
m.loData = CREATEOBJECT("Empty")
ADDPROPERTY(m.loData,"ChartType",0)
ADDPROPERTY(m.loData,"FieldValue","")
ADDPROPERTY(m.loData,"Legend","")
ADDPROPERTY(m.loData,"Color",0)
ADDPROPERTY(m.loData,"Shape",0)
ADDPROPERTY(m.loData,"ShowValuesOnShape",.T.)
ADDPROPERTY(m.loData,"AxisIndex",1)
RETURN m.loData
ENDPROC
PROCEDURE _objtoclientex
*********************************************************************
* FUNCTION ObjToClientEx
*********************************************************************
** Method: xfcBitmap.ObjToClientEx
**
** This replaces OBJTOCLIENT that has bugs with pageframes and SP2
**
** History:
** 2007/11/26: CAlloatti/CChalom - Coded Made small adaptation from the original code from Carlos Alloatti in his CTL32SContainer
*********************************************************************
LPARAMETERS toControl, tnType && 1 = Top 2 = Left
*!* TabOrientation parameters
#DEFINE CON_TABOR_TOP 0
#DEFINE CON_TABOR_BOTTOM 1
#DEFINE CON_TABOR_LEFT 2
#DEFINE CON_TABOR_RIGHT 3
LOCAL lnPosition AS INTEGER
m.lnPosition = 0
DO CASE
CASE m.tnType = 1 && Top
DO WHILE NOT UPPER(m.toControl.BASECLASS) == [FORM]
IF PEMSTATUS(m.toControl, [Top],5) THEN && Defined Property
m.lnPosition = m.lnPosition + m.toControl.TOP
ENDIF
IF UPPER(m.toControl.BASECLASS) == [PAGE] THEN
IF m.toControl.PARENT.TABORIENTATION = CON_TABOR_TOP THEN && Top
m.lnPosition = m.lnPosition + ;
m.toControl.PARENT.HEIGHT - ;
m.toControl.PARENT.PAGEHEIGHT - ;
m.toControl.PARENT.BORDERWIDTH * 2
ELSE
m.lnPosition = m.lnPosition + 1
ENDIF
ENDIF
m.toControl = m.toControl.PARENT
ENDDO
CASE m.tnType = 2 && Left
DO WHILE NOT UPPER(m.toControl.BASECLASS) == [FORM]
IF PEMSTATUS(m.toControl, [Left], 5) THEN && Defined Property
m.lnPosition = m.lnPosition + m.toControl.LEFT
ENDIF
IF UPPER(m.toControl.BASECLASS) == [PAGE]
IF m.toControl.PARENT.TABORIENTATION = CON_TABOR_LEFT THEN && Left
m.lnPosition = m.lnPosition + ;
m.toControl.PARENT.WIDTH - ;
m.toControl.PARENT.PAGEWIDTH - ;
m.toControl.PARENT.BORDERWIDTH * 2
ELSE
m.lnPosition = m.lnPosition + 1
ENDIF
ENDIF
m.toControl = m.toControl.PARENT
ENDDO
ENDCASE
RETURN m.lnPosition
ENDPROC
PROCEDURE _preparebackground
WITH _SCREEN.SYSTEM.Drawing
IF This.BrushType = 3 && Monochrome
This.ChartCanvas.Clear(This._oClrWhite)
ELSE
LOCAL lcType
m.lcType = VARTYPE(This.BackColor2)
DO CASE
CASE m.lcType <> "N"
This.ChartCanvas.Clear(.Color.FromARGB(This.BackColorAlpha, This.BackColor))
CASE m.lcType = "N" AND (This.BackColor = This.BackColor2)
This.ChartCanvas.Clear(.Color.FromARGB(This.BackColorAlpha, This.BackColor))
OTHERWISE
LOCAL loGradBrush as xfcLinearGradientBrush
m.loGradBrush = .Drawing2D.LinearGradientBrush.New(This.ChartCanvas.Rectangle, ;
.Color.FromARGB(This.BackColorAlpha, This.BackColor), ;
.Color.FromARGB(This.BackColorAlpha, This.BackColor2), ;
This.BackGradientMode)
This.oGfx.FillRectangle(m.loGradBrush, This.ChartCanvas.Rectangle)
ENDCASE
ENDIF
ENDWITH
ENDPROC
PROCEDURE _preparebrushes
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlRect, tnCount
LOCAL lnShape as Number
IF VARTYPE(m.tnCount) = "L"
m.tnCount = 1
ENDIF
IF PCOUNT() = 0
m.tnX = 0
m.tnY = 0
m.tnWidth = This.ChartCanvas.Width
m.tnHeight = This.ChartCanvas.Height
ENDIF
m.tnWidth = MAX(1,m.tnWidth)
m.tnHeight = MAX(1,m.tnHeight)
LOCAL lnBrushType, lnMainColor
m.lnBrushType = This.BrushType
m.lnMainColor = This.aColors(m.tnCount)
IF VARTYPE(m.lnMainColor) <> "N"
m.lnMainColor = This._GetRandomColor()
ENDIF
This._nColor = m.lnMainColor
WITH _Screen.System.Drawing
IF This.BrushType = 3 && Monochrome
This._oBorderPen = .Pen.New(This._oClrBlack)
ELSE
LOCAL lnColor
m.lnColor = This.ChangeColor(m.lnMainColor, +30)
This._oBorderPen = .Pen.New(.Color.FromRGB(m.lnColor))
* Check if we are drawing on the selected shape
IF NOT This._InLegend AND This.ChangeColoronMouse AND ;
This._GeneralType <> "Point"
LOCAL m.lnShape
m.lnShape = This._nMouseOnShape
IF m.lnShape > 0 AND This._nMouseOnShape = This._nIndex
m.lnMainColor = This.SelectedShapeColor
ENDIF
ENDIF
ENDIF
DO CASE
CASE m.lnBrushType = 1 && Solid Brush
This._oMainBrush = .SolidBrush.New(.COLOR.FromARGB(This.AlphaChannel, m.lnMainColor))
This._o3DBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This.ChangeColor(m.lnMainColor, - 20)))
CASE m.lnBrushType = 2 && Gradient Path Brush
LOCAL loColor1 as xfcColor
m.loColor1 = .Color.FromARGB(This.AlphaChannel, This.ChangeColor(m.lnMainColor, - 10))
LOCAL loColor2 as xfcColor
m.loColor2 = .COLOR.FromARGB(This.AlphaChannel, This.ChangeColor(m.lnMainColor, This.GradientLevel * 10))
IF This.GradientInvertColors
LOCAL loTmpColor as xfcColor
m.loTmpColor = m.loColor2
m.loColor2 = m.loColor1
m.loColor1 = m.loTmpColor
ENDIF
DO CASE
CASE This._GeneralType = "Pie" AND NOT m.tlRect && Pie or Donut Chart and still not at legend
LOCAL loPath as xfcGraphicsPath
m.loPath = .Drawing2D.GraphicsPath.New()
m.loPath.AddEllipse(m.tnX, m.tnY, m.tnWidth, m.tnHeight)
LOCAL loPathGradBrush as xfcPathGradientBrush
m.loPathGradBrush = .Drawing2D.PathGradientBrush.New(m.loPath)
m.loPathGradBrush.CenterColor = m.loColor2
IF This.PieGradCenterDistance > 0
LOCAL loCenterPt as xfcPointF
m.loCenterPt = This._GetCenterPoint(m.tnX, m.tnY, m.tnWidth, m.tnHeight)
* Set the center using direct API call because the original funciorn has bugs
* When fixed, the line below should work instead:
* m.loPathGradBrush.CenterPoint = m.loCenterPt
=xfcGdipSetPathGradientCenterPoint(m.loPathGradBrush.Handle, m.loCenterPt.ToVarBinary())
ENDIF
* Not working on version 1.20 official
* loPathGradBrush.SurroundColors[1] = loColor1
* loPathGradBrush.SurroundColors = loColor1
* Workaround using direct API call to assign the surround colors
LOCAL lqColors
m.lqColors = BINTOC(m.loColor1.ARGB,"4rs")
=xfcGdipSetPathGradientSurroundColorsWithCount(m.loPathGradBrush.Handle, @m.lqColors, 1)
IF This.GradientType = 0 && SigmaBell
m.loPathGradBrush.SetSigmaBellShape(This.GradientPosition, 1.0)
ELSE && BlendTriangularShape
m.loPathGradBrush.SetBlendTriangularShape(This.GradientPosition, 1.0)
ENDIF
This._oMainBrush = m.loPathGradBrush
CASE This._GeneralType = "Bar" OR m.tlRect && Bar Chart
m.tnWidth = MAX(1, m.tnWidth)
m.tnHeight = MAX(1, m.tnHeight)
LOCAL loLinGradBrush as xfcLinearGradientBrush
m.loLinGradBrush = .Drawing2D.LinearGradientBrush.New(;
.Rectangle.New(m.tnX, m.tnY, m.tnWidth, m.tnHeight), ;
m.loColor1, m.loColor2, This.GradientShapeDirection)
IF This.GradientType = 0 && SigmaBell
m.loLinGradBrush.SetSigmaBellShape(This.GradientPosition, 1)
ELSE && BlendTriangularShape
m.loLinGradBrush.SetBlendTriangularShape(This.GradientPosition, 1.0)
ENDIF
This._oMainBrush = m.loLinGradBrush
CASE This._GeneralType = "Point" && Line, Point or Area Chart
m.loColor2 = .COLOR.FromRGB(This.ChangeColor(m.lnMainColor, This.GradientLevel * 8))
LOCAL loLinGradBrush as xfcLinearGradientBrush
m.loLinGradBrush = .Drawing2D.LinearGradientBrush.New(;
.Rectangle.New(m.tnX, m.tnY, m.tnWidth, m.tnHeight), ;
m.loColor1, m.loColor2, This.GradientShapeDirection)
IF This.GradientType = 0 && SigmaBell
m.loLinGradBrush.SetSigmaBellShape(This.GradientPosition, 1)
ELSE && BlendTriangularShape
m.loLinGradBrush.SetBlendTriangularShape(This.GradientPosition, 1.0)
ENDIF
This._oMainBrush = m.loLinGradBrush
ENDCASE
This._o3DBrush = .SolidBrush.New(.Color.FromARGB(This.AlphaChannel, This.ChangeColor(m.lnMainColor, - 15)))
CASE m.lnBrushType = 3 && Monochrome - HatchBrush
LOCAL lnHatchBrushValue
IF This.ChartsCount > 1 AND NOT This.SingleData && Pie, Bar or Donut
m.lnHatchBrushValue = 4 + m.tnCount * 2
ELSE
m.lnHatchBrushValue = m.lnMainColor * 2
ENDIF
This._oMainBrush = .Drawing2D.HatchBrush.New( ;
m.lnHatchBrushValue, ; && HatchStyle
This._oClrBlack, ; && ForeColor
This._oClrWhite ) && BackColor
This._o3DBrush = .Drawing2D.HatchBrush.New( ;
m.lnHatchBrushValue , ; && HatchStyle
.COLOR.Gray, ; && ForeColor
.COLOR.LightGray ) && BackColor
ENDCASE
ENDWITH
RETURN
ENDPROC
PROCEDURE _preparecolors
SELECT(This._DataCursor)
LOCAL lnColorType, n
m.lnColorType = This.ColorType
IF NOT This.SingleData
LOCAL lnColor, lcIndex
DIMENSION This.aColors(This.ChartsCount)
FOR m.n = 1 TO This.ChartsCount
m.lcIndex = This._Str(m.N)
DO CASE
CASE This.BrushType = 3 && Monochrome
m.lnColor = 0
CASE m.lnColorType = 0 && Basic Colors
m.lnColor = This._GetBasicColor(m.n)
CASE m.lnColorType = 1 && Custom
m.lnColor = This.Fields(m.n).Color
IF VARTYPE(m.lnColor) <> "N"
m.lnColor = This._GetRandomColor()
ENDIF
* CASE m.lnColorType = 2 AND This._UpdateRandomColors && Random
CASE m.lnColorType = 2 AND ;
(This._UpdateRandomColors OR VARTYPE(This.aColors(m.n)) = "L") && Random or not initialized
m.lnColor = This._GetRandomColor()
CASE m.lnColorType = 2 AND NOT This._UpdateRandomColors && Random
RETURN && Keep the current color
CASE m.lnColorType = 3 && Gradient
m.lnColor = This._GetGradientColor(m.n)
CASE m.lnColorType >= 4
m.lnColor = This._GetPaletteColor(m.lnColorType - 4, m.n)
ENDCASE
This.aColors(m.n) = m.lnColor
ENDFOR
ELSE
DIMENSION This.aColors(This._nRecords)
SCAN
m.n = RECNO()
DO CASE
CASE This.BrushType = 3 && Monochrome
m.lnColor = m.n
CASE m.lnColorType = 0 && Basic Colors
m.lnColor = This._GetBasicColor(m.n)
* CASE m.lnColorType = 2 AND This._UpdateRandomColors && Random
CASE m.lnColorType = 2 AND ;
(This._UpdateRandomColors OR VARTYPE(This.aColors(m.n)) = "L") && Random or not initialized
m.lnColor = This._GetRandomColor()
CASE m.lnColorType = 2 AND NOT This._UpdateRandomColors && Random
RETURN
CASE m.lnColorType = 3 && Gradient
m.lnColor = This._GetGradientColor(m.n)
CASE m.lnColorType = 1 AND NOT EMPTY(This.FieldColor) && Custom
m.lnColor = nColor && Retrieve color from Field
CASE m.lnColorType = 1 AND EMPTY(This.FieldColor) && Custom
IF This._UpdateRandomColors
m.lnColor = This._GetRandomColor()
ELSE && no need to update, keep using the same prev color
RETURN
ENDIF
CASE m.lnColorType >= 4
m.lnColor = This._GetPaletteColor(m.lnColorType - 4, m.n)
OTHERWISE && Custom color and not Line or Area chart
ENDCASE
This.aColors(m.n) = m.lnColor
ENDSCAN
ENDIF
This._UpdateRandomColors = .F.
ENDPROC
PROCEDURE _preparedata
LOCAL lcAlias, lcLegend, lcDetach, lcColor, lcSliceHidden, lcNumType, lcCast, lcCursor
LOCAL lcAxis2 as String, ;
lcValue1 as String, ;
loExc as Object
IF EMPTY(This._DataCursor) OR NOT USED(This._DataCursor)
m.lcCursor = "FCharts_" + SYS(2015)
This._DataCursor = m.lcCursor
ELSE
m.lcCursor = This._DataCursor
ENDIF
IF This.OldStyleProperties
LOCAL luValue, n, lcN
FOR m.n = 1 TO This.ChartsCount
m.lcN = This._Str(m.n)
m.luValue = EVALUATE("This.ChartType" + m.lcN)
IF NOT EMPTY(m.luValue)
This.Fields(m.n).ChartType = m.luValue
ENDIF
m.luValue = EVALUATE("This.FieldValue" + m.lcN)
IF NOT EMPTY(m.luValue)
This.Fields(m.n).FieldValue = m.luValue
ENDIF
m.luValue = EVALUATE("This.Legend" + m.lcN)
IF NOT EMPTY(m.luValue)
This.Fields(m.n).Legend = m.luValue
ENDIF
m.luValue = EVALUATE("This.Color" + m.lcN)
IF NOT EMPTY(m.luValue)
This.Fields(m.n).Color = m.luValue
ENDIF
m.luValue = EVALUATE("This.Shape" + m.lcN)
IF NOT EMPTY(m.luValue)
This.Fields(m.n).Shape = m.luValue
ENDIF
m.luValue = EVALUATE("This.ShowValuesOnShape" + m.lcN)
IF This.Fields(m.n).ShowValuesOnShape <> .F.
This.Fields(m.n).ShowValuesOnShape = m.luValue
ENDIF
IF NOT EMPTY(This.FieldxAxis)
This.FieldAxis2 = This.FieldxAxis
ENDIF
ENDFOR
ENDIF
WITH This
m.lcAlias = .SourceAlias
m.lcValue1 = .Fields(1).FieldValue
m.lcLegend = IIF(EMPTY(.FieldLegend), "SPACE(0)", .FieldLegend)
m.lcDetach = IIF(EMPTY(.FieldDetachSlice), ".F.", .FieldDetachSlice)
m.lcColor = IIF(EMPTY(.FieldColor), "EVALUATE('00000000')", .FieldColor)
m.lcSliceHidden = IIF(EMPTY(.FieldHideSlice), ".F.", .FieldHideSlice)
m.lcAxis2 = IIF(EMPTY(.FieldAxis2), "SPACE(0)", .FieldAxis2)
ENDWITH
IF EMPTY(m.lcAlias) OR EMPTY(m.lcValue1) OR ("CC" <> (VARTYPE(m.lcAlias) + VARTYPE(m.lcValue1)))
ERROR "Must specify properties SourceAlias and FieldValue"
RETURN .F.
ENDIF
LOCAL lcFieldType, lnDecimals
m.lcFieldType = This._GetFieldType(m.lcAlias, m.lcValue1)
m.lnDecimals = VAL(GETWORDNUM(m.lcFieldType, 2, ","))
This._ValueDecimals = m.lnDecimals
IF VARTYPE(EVALUATE(m.lcAlias + "." + m.lcValue1)) == "Y" && Currency
This._ValueType = This._GetFieldType(m.lcAlias, m.lcValue1)
This._ValueFormat = "Y"
m.lcNumType = " AS " + This._ValueType
m.lcCast = " CAST("
ELSE
This._ValueFormat = "N"
m.lcNumType = ""
m.lcCast = ""
ENDIF
LOCAL n, lcN, lcSQL, lcNameZ, lcValueZ, lcField
m.lcSQL = ""
FOR m.n = 1 TO This.ChartsCount
m.lcN = This._Str(m.N)
m.lcField = This.Fields(m.n).FieldValue
m.lcNameZ = m.lcCast + m.lcField + m.lcNumType + IIF(NOT EMPTY(m.lcCast), ") ", "")
m.lcSQL = m.lcSQL + m.lcNameZ + " AS nValue" + m.lcN + ", "
* The field property cannot be empty.
ASSERT (NOT EMPTY(m.lcField)) MESSAGE "Property: Fields(" + m.lcN + ").FieldValue was NOT assigned"
ENDFOR
SELECT * FROM (This.SourceAlias) INTO CURSOR FCharts_TempData READWRITE
TRY
SELECT &lcSQL ;
&lcLegend AS cLegend, ;
&lcDetach AS lDetach, ;
&lcColor AS nColor, ;
&lcSliceHidden AS lSliceHidden, ;
&lcAxis2 AS cAxis2 ;
FROM FCharts_TempData ;
INTO CURSOR &lcCursor READWRITE
CATCH TO m.loExc
LOCAL lcVersion, lcError, lcCRLF, lcLine
m.lcCRLF = CHR(13) + CHR(10)
m.lcError = "FoxCharts Error in the data source passed" + m.lcCRLF + m.lcCRLF + ;
[Message: ] + m.loExc.MESSAGE + m.lcCRLF + ;
[Details: ] + m.loExc.DETAILS
MESSAGEBOX(m.lcError, 16, "FoxCharts error")
SELECT &lcSQL ;
&lcLegend AS cLegend, ;
&lcDetach AS lDetach, ;
&lcColor AS nColor, ;
&lcSliceHidden AS lSliceHidden, ;
&lcAxis2 AS cAxis2 ;
FROM FCharts_TempData ;
INTO CURSOR &lcCursor READWRITE
ENDTRY
This._nRecords = _Tally
USE IN FCharts_TempData
* Empty cursor stop processing
IF This._nRecords = 0
RETURN .F.
ENDIF
SELECT (m.lcCursor)
* Prepare the array of points
DIMENSION This._aPoints(This._nRecords, 3) && X, Y, Value
* Create a DESCENDING index that can be used in some specific chart types
INDEX ON RECNO() TAG Revert DESCENDING
SET INDEX TO
This._SkipPrepareData = .F.
This._nMouseonShape = 0
ENDPROC
PROCEDURE _preparelegend
* Calculate the height of the X Axis
SELECT(This._DataCursor)
This.XAxis.Reset()
LOCAL lcCaption, lnCurrWidth, lnMaxWidth, lnCurrHeight, lnMaxHeight, lnRotation, lnAxis2Height, lnMaxAxis2Width, lnWidth, lnHeight
STORE 0 TO m.lnMaxWidth, m.lnMaxHeight, m.lnAxis2Height
SCAN
m.lcCaption = ALLTRIM(TRANSFORM(cAxis2))
IF NOT EMPTY(m.lcCaption)
This.AxisLegend2.Caption = m.lcCaption
m.lnCurrWidth = This.AxisLegend2._Width
m.lnMaxWidth = MAX(m.lnMaxWidth, m.lnCurrWidth)
m.lnCurrHeight = This.AxisLegend2._Height
m.lnMaxHeight = MAX(m.lnMaxHeight, m.lnCurrHeight)
ENDIF
ENDSCAN
m.lnMaxAxis2Width = m.lnMaxWidth
m.lnAxis2Height = m.lnMaxHeight
IF This._Orientation = 1 && Vertical
m.lnRotation = This.AxisLegend2.Rotation
IF This.AxisLegend2.Alignment = 1 && Right
m.lnRotation = 360 - m.lnRotation
ENDIF
m.lnHeight = (SIN(DTOR(m.lnRotation)) * m.lnMaxAxis2Width) + This.AxisLegend2._Height
m.lnHeight = MAX(m.lnAxis2Height, m.lnHeight)
ELSE
IF This.ShowScale
This.ScaleLegend._Value = This._ScaleRange
m.lnWidth = This.ScaleLegend._Width
m.lnRotation = This.ScaleLegend.Rotation
m.lnHeight = (SIN(DTOR(m.lnRotation)) * m.lnWidth) + This.ScaleLegend._Height
m.lnAxis2Height = This.ScaleLegend._Height
m.lnHeight = MAX(m.lnAxis2Height, m.lnHeight)
ELSE
m.lnHeight = 0
ENDIF
ENDIF
This._XAxisHeight = IIF(EMPTY(This.XAxis.Caption), 0, This.XAxis._Height) + ;
m.lnHeight + ;
This.Margin + This.MarginBottom + ;
IIF(INLIST(This.LegendPosition, 8, 9, 10), This._LegendHeight, 0) + ; && Bottom Side
6
This._LegendPixHeight = m.lnHeight
RETURN
ENDPROC
PROCEDURE _preparelegendinslice
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnStart, tnSweep, tnValue, tnDistance
IF EMPTY(m.tnDistance)
m.tnDistance = MAX(This.PieLegendDistance, 0.10)
ENDIF
* Calculate the coordinates to draw the Values inside the shapes
This._AdjustStartSweep(@m.tnStart, @m.tnSweep, m.tnWidth, m.tnHeight)
* Calculate positions
LOCAL lnCenterX, lnCenterY
m.lnCenterX = (m.tnWidth / 2)
m.lnCenterY = (m.tnHeight / 2)
* Create a GraphicsPath object.
LOCAL lnAngle, lnDistance, xAdjust, yAdjust
m.lnAngle = m.tnStart + (m.tnSweep / 2)
m.lnDistance = m.tnDistance && This.PieLegendDistance
* lnDistance = IIF(EMPTY(tnDistance), 0.75, tnDistance)
LOCAL loTempPath as xfcGraphicsPath
LOCAL loPoint as xfcPointF
LOCAL loRect as xfcRectangle
m.loTempPath = _Screen.System.Drawing.Drawing2D.GraphicsPath.New()
* Obtaining the needed points
m.xAdjust = (1 - m.lnDistance) / 2
m.yAdjust = (1 - m.lnDistance) / 2
m.loRect = _Screen.System.Drawing.Rectangle.New(m.tnX + m.xAdjust * m.tnWidth, ;
m.tnY + m.yAdjust * m.tnHeight, ;
m.lnDistance * m.tnWidth, ;
m.lnDistance * m.tnHeight)
m.loTempPath.AddArc(m.loRect, m.lnAngle, 0.0001)
m.loPoint = m.loTempPath.GetLastPoint()
* Send back the coordinates
m.tnX = m.loPoint.X
m.tnY = m.loPoint.Y
RETURN
ENDPROC
PROCEDURE _preparesidelegend
*!* Property LegendPosition
*!* Numeric,
*!* Determines the position where the side legend wiil be drawn in the canvas.
*1* 0 - No Legend
*!* 1 - Vertical Top Left
*!* 2 - Vertical Bottom Left
*!* 3 - Vertical Top Right
*!* 4 - Vertical Bottom Right
*!* 5 - Horiz Top Left
*!* 6 - Horiz Top Center
*!* 7 - Horiz Top Right
*!* 8 - Horiz Bottom Left
*!* 9 - Horiz Bottom Center
*!* 10 - Horiz Bottom Right
*!* 11 - Vertical Center Left
LOCAL lnChartsCount
m.lnChartsCount = This.ChartsCount
IF This.ChartType = 17 && Paired Bars
m.lnChartsCount = MIN(2, m.lnChartsCount)
ENDIF
LOCAL lnScale2W
m.lnScale2W = 0
IF This._MaxScale2 > 0
LOCAL lnScale2W, lcCaption
IF NOT EMPTY(This.ScaleLegend._ForceFormat)
m.lcCaption = This._ScaleLegAxis2ForceFormat
ELSE
m.lcCaption = TRANSFORM(This._MaxScale2, This.ScaleLegend.Format)
ENDIF
This.ScaleLegend.Caption = m.lcCaption
m.lnScale2W = This.ScaleLegend._Width
This._Axis2ScaleWidth = m.lnScale2W
ENDIF
IF NOT This.ShowSideLegend OR This.LegendPosition = 0
This._LegendWidth = MAX(5, (This.Margin + This.MarginRight))
This._LegendHeight = 0
This._TopOffSet = This.Margin + This.MarginTop + This._TitleHeight
This._LeftOffset = This.Margin + This.MarginLeft
This._RightOffSet = This.Margin + This.MarginRight + m.lnScale2W
* Leaving some extra space for the X Axis legends
IF NOT EMPTY(This.FieldAxis2) AND This._AllowAxis
* Measure the legend width
This.AxisLegend2._Setup()
* Last legend
GO BOTTOM
LOCAL ln3D
IF This._DeepChart && Point, Line or Area
m.ln3D = This._3D * m.lnChartsCount
ELSE
m.ln3D = This._3D
ENDIF
This.AxisLegend2.Caption = cAxis2 && Field text
IF m.ln3D < (This.AxisLegend2._Width / 2)
This._RightOffSet = This._RightOffSet + (This.AxisLegend2._Width / 2) - m.ln3D
ENDIF
ENDIF
RETURN
ENDIF
SELECT(This._DataCursor)
This.SideLegend.Caption = "12"
This.SideLegend.Reset()
LOCAL lnCurrWidth, lnMaxWidth, lnCurrHeight, lnMaxHeight, lnLegendHeight, lnLegendPosition, n
LOCAL loFont as xfcFont
LOCAL loSize as xfcSize
m.loFont = This.SideLegend._oFont
m.lnMaxWidth = 0
m.lnMaxHeight = 0
m.lnLegendPosition = This.LegendPosition
* Measure the maximum legend width
IF This.SingleData
DIMENSION This._aSideLegends(This._nRecords, 2)
SCAN
m.n = RECNO()
m.lcCaption = TRANSFORM(cLegend)
IF This.LegendHideWhenNull
IF ISNULL(This._GetValue(This.ChartRow, .T.)) && Accept NULLs
m.lcCaption = ""
ENDIF
ENDIF
m.loSize = This.oGfx.MeasureString(m.lcCaption, m.loFont)
m.lnCurrWidth = m.loSize.Width
m.lnMaxWidth = Max(m.lnMaxWidth, m.lnCurrWidth)
m.lnCurrHeight = m.loSize.Height
m.lnMaxHeight = Max(m.lnMaxHeight, m.lnCurrHeight)
This._aSideLegends(m.n, 1) = m.lcCaption
This._aSideLegends(m.n, 2) = m.lnCurrWidth
ENDSCAN
GO TOP
ELSE
DIMENSION This._aSideLegends(m.lnChartsCount, 2)
FOR m.n = 1 To m.lnChartsCount
m.lcCaption = TRANSFORM(This.Fields(m.n).Legend)
m.loSize = This.oGfx.MeasureString(m.lcCaption, m.loFont)
m.lnCurrWidth = m.loSize.Width
m.lnMaxWidth = Max(m.lnMaxWidth, m.lnCurrWidth)
m.lnCurrHeight = m.loSize.Height
m.lnMaxHeight = Max(m.lnMaxHeight, m.lnCurrHeight)
This._aSideLegends(m.n, 1) = m.lcCaption
This._aSideLegends(m.n, 2) = m.lnCurrWidth
NEXT m.n
ENDIF
DO CASE
CASE INLIST(m.lnLegendPosition, 1, 2, 11) && Left Side
This._LegendWidth = m.lnMaxWidth + m.lnMaxHeight + This._LegendExternalMargin * 2
This._LegendHeight = 0
This._LeftOffset = This.Margin + This.MarginLeft + This._LegendWidth
This._RightOffSet = This.Margin + This.MarginRight + m.lnScale2W
This._TopOffSet = This.Margin + This.MarginTop + This._TitleHeight
CASE INLIST(m.lnLegendPosition, 3, 4, 12) && Right Side (Default)
This._LegendWidth = m.lnMaxWidth + m.lnMaxHeight + This._LegendExternalMargin
This._LegendHeight = 0
This._LeftOffset = This.Margin + This.MarginLeft
This._RightOffSet = This.Margin + This.MarginRight + This._LegendWidth + m.lnScale2W
This._TopOffSet = This.Margin + This.MarginTop + This._TitleHeight
CASE INLIST(m.lnLegendPosition, 5, 6, 7) && Top Side
This._LegendWidth = 0
This._LegendHeight = m.lnMaxHeight + (This._LegendExternalMargin * 2)
This._LeftOffset = This.Margin + This.MarginLeft
This._RightOffSet = This.Margin + This.MarginRight + m.lnScale2W
This._TopOffSet = This.Margin + This.MarginTop + This._TitleHeight + This._LegendHeight
CASE INLIST(m.lnLegendPosition, 8, 9, 10) && Bottom Side
This._LegendWidth = 0
This._LegendHeight = m.lnMaxHeight + (This._LegendExternalMargin * 2)
This._LeftOffset = This.Margin + This.MarginLeft
This._RightOffSet = This.Margin + This.MarginRight + m.lnScale2W
This._TopOffSet = This.Margin + This.MarginTop + This._TitleHeight
OTHERWISE
ENDCASE
ENDPROC
PROCEDURE _preparetitle
LOCAL lnTitleHeight, lnSubTitleHeight, lnTitleColor
STORE 0 TO m.lnTitleHeight, m.lnSubTitleHeight
* Check if Title was assigned
IF NOT EMPTY(This.Title.Caption)
This.Title.Reset()
This.Title._DrawString(0, This.Margin + This.MarginTop, This.ChartCanvas.Width, This.ChartCanvas.Height)
m.lnTitleHeight = This.Title._height
ENDIF
* Check if SubTitle was assigned
IF NOT EMPTY(This.SubTitle.Caption)
This.SubTitle.Reset()
This.SubTitle._DrawString(0, This.Margin + This.MarginTop + m.lnTitleHeight, This.ChartCanvas.Width, This.ChartCanvas.Height)
m.lnSubTitleHeight = This.SubTitle._Height
ENDIF
This._TitleHeight = m.lnTitleHeight + m.lnSubTitleHeight
RETURN
ENDPROC
PROCEDURE _preparetooltip
IF NOT This.ShowTips OR NOT This._InsideForm
RETURN
ENDIF
LOCAL loTip as Label
m.loTip = This.ToolTip
* Add the tooltips object to the form
IF NOT PEMSTATUS(Thisform, "FoxChartsToolTip", 5)
Thisform.AddObject("FoxChartsToolTip", "Label")
ENDIF
WITH Thisform.FoxChartsToolTip as Label
.Alignment = m.loTip.Alignment
.Autosize = m.loTip.AutoSize
.BackColor = m.loTip.BackColor
.BackStyle = m.loTip.BackStyle
.BorderStyle = m.loTip.BorderStyle
.FontBold = m.loTip.FontBold
.FontItalic = m.loTip.FontItalic
.FontName = m.loTip.FontName
.FontSize = m.loTip.FontSize
.FontStrikethru = m.loTip.FontStrikethru
.FontUnderline = m.loTip.FontUnderline
.ForeColor = m.loTip.ForeColor
.WordWrap = m.loTip.WordWrap
.ZOrder(0)
ENDWITH
BINDEVENT(Thisform.FoxChartsToolTip, "MouseMove", This.ToolTip, "MouseMove")
ENDPROC
PROCEDURE _preparevariables
LOCAL lnSumValue as Number, ;
loExc as Object
*TRY
SELECT(This._DataCursor)
This._HasNegatives = .F.
LOCAL lnValue
DO CASE
CASE INLIST(This.ChartType, 9, 10, 14) && Stacked Bars or Stacked Area
* Get the maximum value of the chart
Local i, lnTotal, lnMaxValue, lnMinValue
m.lnMaxValue = 0
Scan
m.lnTotal = 0
For m.i = 1 To This.ChartsCount
m.lnValue = This._GetValue(m.i)
IF m.lnValue < 0
This._HasNegatives = .T.
ENDIF
m.lnTotal = m.lnTotal + m.lnValue
Endfor
If Recno() = 1
m.lnMinValue = m.lnTotal
Else
m.lnMinValue = Min(m.lnMinValue, m.lnTotal)
Endif
m.lnMaxValue = Max(m.lnMaxValue, m.lnTotal)
Endscan
Case This.SingleData
Local lnMaxValue, lcField, lnMinValue
m.lcField = (This._DataCursor) + ".nValue" + This._Str(This.ChartRow)
Calculate Max (&lcField.) To m.lnMaxValue for not IsNull (&lcField.)
Calculate Min (&lcField.) To m.lnMinValue for not IsNull (&lcField.)
Calculate Sum (&lcField.) To m.lnSumValue for Nvl(&lcField. , 0) > 0
This.ChartSum = m.lnSumValue
CASE This.ChartType = 18 && Double Axis lines
*!* 2Axis
*!* This.Fields(n).AxisIndex = 2
* Get the maximum value of the chart
* Start with the 2nd axis
Local lnMaxValue, lnMaxValue1, i, lcField, lnRealChartsCount, lnMinValue, lnMinValue1
m.lnMaxValue = 0
m.lnRealChartsCount = This.ChartsCount
LOCAL llHas2Axis && Used to make sure we have data on the 2nd Y axis
m.llHas2Axis = .F.
FOR m.i = 1 To m.lnRealChartsCount
IF This.Fields(m.i).AxisIndex = 1
LOOP
ENDIF
m.llHas2Axis = .T.
m.lcField = (This._DataCursor) + ".nValue" + This._Str(m.i)
Calculate Max (&lcField.) To m.lnMaxValue1 for not IsNull (&lcField.)
Calculate Min (&lcField.) To m.lnMinValue1 for not IsNull (&lcField.)
* CCHALOM 2013-02-21
* Fix in obtaining the Minimum value
IF VARTYPE(m.lnMinValue) <> "N"
m.lnMinValue = m.lnMinValue1
ENDIF
IF m.lnMinValue1 < 0
This._HasNegatives = .T.
ENDIF
If m.i = 1
m.lnMaxValue = m.lnMaxValue1
m.lnMinValue = m.lnMinValue1
Else
m.lnMaxValue = Max(m.lnMaxValue, m.lnMaxValue1)
* CCHALOM 2013-02-21
* Fix in obtaining the Minimum value
m.lnMinValue = Min(m.lnMinValue, m.lnMinValue1)
Endif
Endfor
IF m.llHas2Axis
This._CalculateScale(m.lnMaxValue, m.lnMinValue, 2)
This._ScaleLegend2ForceFormat = This.ScaleLegend._ForceFormat
* CCHALOM 2013-02-21
* Fix in getting a nice Scale legend format for both axes
* New properties inserted: _ScaleLegAxis1ForceFormat , _ScaleLegAxis2ForceFormat
This._ScaleLegAxis2ForceFormat = This.ScaleLegend._ForceFormat
ENDIF
* Do the same for the 1st axis
* Get the maximum value of the chart
m.lnMaxValue = 0
For m.i = 1 To m.lnRealChartsCount
IF This.Fields(m.i).AxisIndex = 2
LOOP
ENDIF
m.lcField = (This._DataCursor) + ".nValue" + This._Str(m.i)
Calculate Max (&lcField.) To m.lnMaxValue1 for not IsNull (&lcField.)
Calculate Min (&lcField.) To m.lnMinValue1 for not IsNull (&lcField.)
IF m.lnMinValue1 < 0
This._HasNegatives = .T.
ENDIF
If m.i = 1
m.lnMaxValue = m.lnMaxValue1
m.lnMinValue = m.lnMinValue1
Else
m.lnMaxValue = Max(m.lnMaxValue, m.lnMaxValue1)
m.lnMinValue = Min(m.lnMinValue, m.lnMinValue1)
Endif
Endfor
OTHERWISE
* Get the maximum value of the chart
Local lnMaxValue, lnMaxValue1, i, lcField, lnRealChartsCount, lnMinValue, lnMinValue1
m.lnMaxValue = 0
m.lnRealChartsCount = Iif(Inlist(This.ChartType, 1,2,7,12),1,This.ChartsCount)
For m.i = 1 To m.lnRealChartsCount
m.lcField = (This._DataCursor) + ".nValue" + This._Str(m.i)
Calculate Max (&lcField.) To m.lnMaxValue1 for not IsNull (&lcField.)
Calculate Min (&lcField.) To m.lnMinValue1 for not IsNull (&lcField.)
IF VARTYPE(m.lnMinValue) <> "N"
m.lnMinValue = m.lnMinValue1
ENDIF
IF m.lnMinValue1 < 0
This._HasNegatives = .T.
ENDIF
If m.i = 1
m.lnMaxValue = m.lnMaxValue1
m.lnMinValue = m.lnMinValue1
Else
m.lnMaxValue = Max(m.lnMaxValue, m.lnMaxValue1)
m.lnMinValue = Min(m.lnMinValue, m.lnMinValue1)
Endif
Endfor
Endcase
This._CalculateScale(m.lnMaxValue, m.lnMinValue)
* CCHALOM 2013-02-21
* Fix in getting a nice Scale legend format for both axes
* New properties inserted: _ScaleLegAxis1ForceFormat , _ScaleLegAxis2ForceFormat
This._ScaleLegAxis1ForceFormat = This.ScaleLegend._ForceFormat
DIMENSION This._aShapes(This.ChartsCount,3)
This._aShapes = ""
IF NOT This._Using3D
This._3D = This.Depth
ENDIF
** CATCH TO m.loExc
** SET STEP ON
** ENDTRY
ENDPROC
PROCEDURE _ps
LPARAMETERS tcPrp, toCtrl, tnType
LOCAL lcExpr as String
DO CASE
CASE m.tnType = 1 && GETCOLOR
LOCAL luOrig,lnClr,lcRet
m.lcExpr = EVAL("toCtrl."+m.tcPrp)
IF VARTY(m.lcExpr)="C"
IF LEFT(m.lcExpr,1) = "="
m.lcExpr=EVALUATE(STRTR(m.lcExpr,"=","",1,1))
ELSE
m.lcExpr = 0
ENDIF
ENDIF
m.luOrig = EVL(m.lcExpr, 0)
m.lnClr = GETCOLOR(m.luOrig)
m.lnClr = IIF(m.lnClr=-1,m.luOrig,m.lnClr)
m.lcRet = TEXTMERGE( ;
"<<MOD(lnClr,256)>>,<<MOD(INT(lnClr/256),256))>>,<<MOD(INT(lnClr/65536),256)))>>")
m.toCtrl.WRITEEXPRESSION(m.tcPrp, "")
STORE m.lcRet TO ("toCtrl." + m.tcPrp)
OTHERWISE
ENDCASE
ENDPROC
PROCEDURE _setfieldscount
LPARAMETERS tnCnt
LOCAL loData
*--MW-->The stock method handled adding fields to the collection but not removing them.
IF This.Fields.Count <> m.tnCnt
LOCAL lnIncr, lnFieldNo
m.lnIncr = m.tnCnt - This.Fields.Count
DO WHILE This.Fields.Count <> m.tnCnt
IF m.lnIncr > 0
*--Adding fields
m.loData = This._NewField()
This.Fields.Add(m.loData)
ELSE
*--Removing fields
m.lnFieldNo = This.Fields.Count
This.Fields.Remove(m.lnFieldNo)
ENDIF
ENDDO
*--Make sure the ChartsCount matches.
This.ChartsCount = m.tnCnt
ENDIF
ENDPROC
PROCEDURE _spellproperty
LPARAMETERS tcProperty
* Returns upper/lower case name of property
LOCAL lcList, lnPos
IF EMPTY(This._SpellingList)
m.lcList = ".AlphaChannel.Area3dTop.AreaDrawBorders.AxisAlpha.AxisColor.AxisLegend2.Alignment.BackColor.BackColorAlpha.FontBold"
m.lcList = m.lcList + ".FontCharSet.FontItalic.FontName.FontSize.FontUnderline.ForeColor.ForeColorAlpha.Format.Rotation.BackColor2.BackGradientMode"
m.lcList = m.lcList + ".BarsPerScale.BarsSpaceBetween.BarType.BrushType.ChangeColorOnMouse.ChartRow.ChartsCount.ChartType"
m.lcList = m.lcList + ".ColorType.Depth.DonutRatio.FieldAxis2.FieldColor.FieldDetachSlice.FieldHideSlice.FieldLegend.Fields.Color"
m.lcList = m.lcList + ".FieldValue.Legend.Shape.Gradientlevel.LegendHideWhenNull.LineCaps.Margin"
m.lcList = m.lcList + ".MarginBottom.MarginLeft.MarginRight.MarginTop.MaxValue.MinNumberScaleLegends.MinValue.MultiChart.OldStyleProperties"
m.lcList = m.lcList + ".PieCompensateAngles.PieDetachAnimationSteps.PieDetachPixels.PieDetachSliceOnClick.PieEnhancedDrawing.PieShowPercent"
m.lcList = m.lcList + ".PointShapeWidth.Scale.ScaleBackAlpha.ScaleBackBarsType.ScaleBackColor.ScaleBackLinesDash.ScaleBackLinesType"
m.lcList = m.lcList + ".ScaleBackLinesWidth.ScaleLegend.ScaleLineColor.ScaleLineZeroColor.ScaleStartValue.SelectedShapeColor.Shape1"
m.lcList = m.lcList + ".ShapeLegend.ShowAxis.ShowLineZero.ShowScale.ShowSideLegend.ShowTips.ShowValuesOnShapes.ShowValueZero.SideLegend"
m.lcList = m.lcList + ".SourceAlias.SubTitle.Title.XAxis.YAxis.YAxis2.Caption"
* Add the new Properties since version 1.00RC
m.lcList = m.lcList + ".GradientInvertColors.GradientPosition.GradientShapeDirection.GradientType.PieGradCenterAngle"
m.lcList = m.lcList + ".PieGradCenterDistance.ScaleDivider.Shadow.ShapeMousePointer.LegendPosition"
m.lcList = m.lcList + ".Debug.ScaleAutoFormat.ShowValuesOnShape.ShowValuesOnShapes.BarLegendDirection"
m.lcList = m.lcList + ".QualityCompositing.QualitySmoothing.QualityTextRenderingHint.BarLegendType"
m.lcList = m.lcList + ".LineCapsShape.PieDetachSliceOnLegendClick.MultiChartMargin.BarLegendDirection"
m.lcList = m.lcList + ".PieForceCircle.RotationCenter"
m.lcList = m.lcList + ".PieLegendDistance.ShapeLegendExpression.ShowAxis2Tics.TicLength"
m.lcList = m.lcList + ".PieDirection.Width.Height.ShowPercentages"
This._spellinglist = m.lcList
ENDIF
m.lnPos = ATCC("." + UPPER(m.tcProperty) + ".", This._spellinglist + ".")
IF m.lnPos # 0
RETURN SUBSTR(This._spellingList, m.lnPos + 1, LEN(m.tcProperty))
ELSE
RETURN m.tcProperty
ENDIF
ENDPROC
PROCEDURE _str
LPARAMETERS tnValue
RETURN ALLTRIM(STR(m.tnValue,2,0))
ENDPROC
PROCEDURE _updatechartinfo
*!* Chart Type Values:
*!* 1 - Pie
*!* 2 - Doughnut
*!* 3 - Full-Stacked Bars
*!* 4 - Points
*!* 5 - Lines
*!* 6 - Area
*!* 7 - Simple Bars
*!* 8 - Multiple Bars
*!* 9 - Stacked Bars
*!* 10 - Stacked Area
*!* 11 - 3D Bars
*!* 12 - Horiz. Simple Bars
*!* 13 - Horiz. Multiple Bars
*!* 14 - Horiz. Stacked Bars
*!* 15 - Horiz. Full-Stacked Bars
*!* 16 - Full-Stacked Area
*!* 17 - Paired Bars
*!* 18 - Double-Axis Lines
LOCAL lnChart, llDeep, llAxis, llSingleData, lnOrientation, llFullStacked, ;
llAbsoluteScale, llChartsCount, llScalePercent
Local lcType as String, ;
llStacked as Boolean, ;
llUseAxis as Boolean
m.lnChart = This.ChartType
DO CASE
CASE m.lnChart = 1 && Pie
m.llDeep = .F.
m.llAxis = .F.
m.llSingleData = .T.
m.lcType = "Pie"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .F.
m.llFullStacked = .T.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 2 && Doughnut
m.llDeep = .F.
m.llAxis = .F.
m.llSingleData = .T.
m.lcType = "Pie"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .F.
m.llFullStacked = .T.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 4 && Point
m.llDeep = .T.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Point"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .F.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE INLIST(m.lnChart, 5, 18) && Line
m.llDeep = .T.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Point"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .F.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 6 && Area
m.llDeep = .T.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Point"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .F.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 7 && Simple Bar
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .T.
m.lcType = "Bar"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .T.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 8 && Multiple Bars
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Bar"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .T.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 9 && Stacked Bars
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Bar"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .F.
m.llStacked = .T.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 10 && Stacked Area
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Point"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .T.
m.llStacked = .T.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 11 && 3d Bars
m.llDeep = .T.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Bar"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .F.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 12 && Horizontal Bars
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .T.
m.lcType = "Bar"
m.lnOrientation = 2 && Horizontal
m.llUseAxis = .T.
m.llFullStacked = .T.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 13 && Horizontal Multiple Bars
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Bar"
m.lnOrientation = 2 && Horizontal
m.llUseAxis = .T.
m.llFullStacked = .T.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 14 && Horizontal Stacked Bars
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Bar"
m.lnOrientation = 2 && Horizontal
m.llUseAxis = .T.
m.llFullStacked = .F.
m.llStacked = .T.
m.llAbsoluteScale = .F.
m.llScalePercent = .F.
CASE m.lnChart = 3 && Full-Stacked Bars
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Bar"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .T.
m.llStacked = .T.
m.llAbsoluteScale = .F.
m.llScalePercent = .T.
CASE m.lnChart = 15 && Horizontal Full-Stacked Bars
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Bar"
m.lnOrientation = 2 && Horizontal
m.llUseAxis = .T.
m.llFullStacked = .T.
m.llStacked = .F.
m.llAbsoluteScale = .F.
m.llScalePercent = .T.
CASE m.lnChart = 16 && Full-Stacked Area
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Point"
m.lnOrientation = 1 && Vertical
m.llUseAxis = .T.
m.llFullStacked = .T.
m.llStacked = .T.
m.llAbsoluteScale = .F.
m.llScalePercent = .T.
CASE m.lnChart = 17 && Paired Bars
m.llDeep = .F.
m.llAxis = .T.
m.llSingleData = .F.
m.lcType = "Bar"
m.lnOrientation = 2 && Horizontal
m.llUseAxis = .T.
m.llFullStacked = .T. && F
m.llStacked = .F.
m.llAbsoluteScale = .T.
m.llScalePercent = .F.
OTHERWISE
* ERROR "Chart type " + TRANSFORM(lnChart) + " does not exist"
ENDCASE
This._DeepChart = m.llDeep
This._AllowAxis = m.llAxis
This.SingleData = m.llSingleData
This._GeneralType = m.lcType
This._Orientation = m.lnOrientation
This._UseAxis = m.llUseAxis
This._SumRow = m.llFullStacked
This._STACKED = m.llStacked
This._AbsoluteScaleValues = m.llAbsoluteScale
This._ScaleInPercent = m.llScalePercent
* Clear the chart coodinates
IF NOT This._InReport
This.aCoord = .F.
ENDIF
This._nIndex = 0
This.ShapeLegend._ForceFormat = ""
ENDPROC
PROCEDURE _updatecoordinates
LPARAMETERS tcObjType, tnX, tnY, tnWidth, tnHeight, tnValue, tnStart, tnSweep
*** SumofTheRow
SELECT (This._DataCursor)
* During DrawReport(), there's no need to update the coordinates
*!* IF This._InReport
*!* RETURN
*!* ENDIF
*!* IF NOT This.ShowTips
*!* RETURN
*!* ENDIF
LOCAL n
m.n = This._nIndex + 1
This._nIndex = m.n
DIMENSION This.aCoord(m.n,12)
This.aCoord(m.n,1) = m.tnX
This.aCoord(m.n,2) = m.tnY
This.aCoord(m.n,3) = m.tnWidth
This.aCoord(m.n,4) = m.tnHeight
This.aCoord(m.n,5) = m.tnValue
* This.aCoord(n,6) = Legend
This.aCoord(m.n,7) = m.tnStart
This.aCoord(m.n,8) = m.tnSweep
This.aCoord(m.n,9) = This._ChartIndex && ChartRow
IF m.tcObjType = "Legend"
&& on "Legend" mode, tnValue passes the index
This.aCoord(m.n,10) = IIF(NOT EMPTY(This._Currentrow), This._CurrentRow, m.tnValue)
This.aCoord(m.n,6) = IIF(VARTYPE(m.tnStart) = "C", m.tnStart, "")
ELSE
This.aCoord(m.n,10) = IIF(NOT EMPTY(This._Currentrow), This._CurrentRow, RECNO())
LOCAL lcLegend
IF This.SingleData && Pie, Donut or Single Bar
m.lcLegend = cLegend
ELSE
m.lcLegend = This.Fields(This._ChartIndex).Legend
ENDIF
This.aCoord(m.n,6) = ALLTRIM(TRANSFORM(m.lcLegend))
ENDIF
This.aCoord(m.n,11) = m.tcObjType
This.aCoord(m.n,12) = IIF(m.tcObjType = "Rect" and not EMPTY(m.tnStart), m.tnStart, 0) && Sum of the current row
ENDPROC
PROCEDURE _updatequality
LOCAL loCanvas as xfcImgCanvas OF "GdiPlusX.vcx"
m.loCanvas = This.ChartCanvas
m.loCanvas.SmoothingMode = This.QualitySmoothing
m.loCanvas.TextRenderingHint = This.QualityTextRenderingHint
m.loCanvas.oGfx.CompositingQuality = This.QualityCompositing
ENDPROC
PROCEDURE ChartCanvas.activate
DODEFAULT()
This.Parent._GetRelativePositions()
ENDPROC
PROCEDURE ChartCanvas.beforedraw
This.Parent._BeforeDraw()
ENDPROC
PROCEDURE ChartCanvas.Click
LOCAL lnValue, lcLegend, lcObjType, lnCoordIndex
lnCoordIndex = 0
LOCAL lnX, lnY
lnX = MCOL(0,3)
lnY = MROW(0,3)
This.Parent._CheckMousePosition(0, 0, lnX, lnY, @lnValue, @lcLegend, @lnCoordIndex, @lcObjType)
This.Parent.CurrValue = lnValue
This.Parent.CurrLegend = lcLegend
This.Parent.CurrIndex = lnCoordIndex
This.Parent.CurrObjType = lcObjType
This.Parent.Click()
RETURN
ENDPROC
PROCEDURE ChartCanvas.DblClick
LOCAL lnValue, lcLegend, lcObjType, lnCoordIndex, lnX, lnY
lnCoordIndex = 0
lnX = MCOL(0,3)
lnY = MROW(0,3)
**12.4.2013 KP: changed parameters - set tcLegend
*!*Lparameters tnButton, tnShift, tnXCoord, tnYCoord, tlnValue, tcLegend, tlnCoordIndex, tlcObjType
This.Parent._CheckMousePosition(0, 0, lnX, lnY, @lnValue, '', @lnCoordIndex, @lcObjType)
This.Parent.CurrIndex = lnCoordIndex
This.Parent.DblClick()
RETURN
ENDPROC
PROCEDURE ChartCanvas.Destroy
IF NOT EMPTY(This.Parent._DataCursor) AND USED(This.Parent._DataCursor)
USE IN (This.Parent._DataCursor)
ENDIF
DODEFAULT()
ENDPROC
PROCEDURE ChartCanvas.Init
This.Width = This.Parent.Width
This.Height = This.Parent.Height
DODEFAULT()
ENDPROC
PROCEDURE ChartCanvas.MouseLeave
LPARAMETERS nButton, nShift, nXCoord, nYCoord
Thisform.FoxChartsToolTip.Visible = .F.
WITH This.Parent
IF .ChangeColoronMouse AND ;
(NOT BETWEEN(.Left, nXCoord - .Left, .Width - .Left) AND ;
NOT BETWEEN(.Top , nXCoord - .Top , .Height - .Top ))
._nMouseOnShape = 0
._SkipPrepareData = .T.
IF ._Drawing = .F.
.DrawChart()
ELSE
._Redraw = .T.
ENDIF
ENDIF
ENDWITH
ENDPROC
PROCEDURE ChartCanvas.MouseMove
LPARAMETERS nButton, nShift, nXCoord, nYCoord
LOCAL lnValue, lcLegend, lcObjType, lnCoordIndex
m.lnCoordIndex = 0
WITH This.Parent
._CheckMousePosition(nButton, nShift, nXCoord, nYCoord, @lnValue, @lcLegend, @lnCoordIndex, @lcObjType)
* Update the index property, that will allow all the other "curr"properties to be up to date
This.Parent.Currindex = lnCoordIndex
* Prepare the ToolTips
LOCAL lcType
m.lcType = VARTYPE(m.lnValue) + VARTYPE(m.lcLegend)
LOCAL loTip as Label
m.loTip = Thisform.FoxChartsToolTip
IF m.lcType <> "NC"
m.loTip.Visible = .F.
This.MousePointer = ._OrigMousePointer && = 0 && Default
ELSE
IF .ShowTips
.ShapeToolTip(nButton, nShift, nXCoord, nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex, m.lcObjType)
* Fix by Christof Wollenhaupt
* WorkItem #20978
* http://www.codeplex.com/VFPX/WorkItem/View.aspx?WorkItemId=20978
*
* IF TYPE("_Screen.ActiveForm") == "O" AND ;
(_Screen.ActiveForm = Thisform) AND ;
NOT EMPTY(m.loTip.Caption)
IF TYPE("_Screen.ActiveForm") == "O" AND ;
NOT EMPTY(m.loTip.Caption)
LOCAL lnLeft, lnTop, lnWidth, lnHeight, lnX, lnY
lnX = m.nXCoord
lnY = m.nYCoord
m.lnWidth = m.loTip.Width
m.lnHeight = m.loTip.Height
m.lnLeft = lnX + 1
IF m.lnLeft + m.lnWidth > Thisform.Width
m.lnLeft = Thisform.Width - m.lnWidth
ENDIF
m.lnTop = lnY - m.lnHeight - 1
IF m.lnTop < 0
m.lnTop = 0
ENDIF
m.loTip.Left = m.lnLeft
m.loTip.Top = m.lnTop
IF m.loTip.Visible = .F.
m.loTip.Visible = .T.
ENDIF
ELSE
m.loTip.Visible = .F.
ENDIF
ENDIF
ENDIF
m.lcObjType = IIF(EMPTY(m.lcObjType),"", m.lcObjType)
m.lcLegend = IIF(EMPTY(m.lcLegend),"", m.lcLegend)
.MouseMove(nButton, nShift, nXCoord, nYCoord, m.lnValue, m.lcLegend, m.lnCoordIndex, m.lcObjType)
ENDWITH
RETURN
ENDPROC
PROCEDURE ChartCanvas.MouseUp
LPARAMETERS nButton, nShift, nXCoord, nYCoord
LOCAL lnValue, lcLegend, lcObjType, lnCoordIndex
lnCoordIndex = 0
This.Parent._CheckMousePosition(nButton, nShift, nXCoord, nYCoord, @lnValue, @lcLegend, @lnCoordIndex, @lcObjType)
* Update the index property, that will allow all the other "curr"properties to be up to date
This.Parent.Currindex = lnCoordIndex
This.Parent.MouseUp(nButton, nShift, nXCoord, nYCoord, lnValue, lcLegend, lnCoordIndex, lcObjType)
IF This.Parent._GeneralType = "Pie"
IF lcObjType = "Pie" AND This.Parent.PieDetachSliceonClick
This.Parent._DetachClickedSlice(lnCoordIndex)
ENDIF
IF lcObjType = "Legend" AND This.Parent.PieDetachSliceonLegendClick
This.Parent._DetachClickedSlice(lnCoordIndex)
ENDIF
ENDIF
RETURN
ENDPROC
PROCEDURE ScaleLegend._updatemeasures
LPARAMETERS tlNumeric
IF VARTYPE(This.Parent.oGfx) <> "O"
RETURN
ENDIF
* Measure the Legend height
IF VARTYPE(This._oBrush) + VARTYPE(This._oFont) <> "OO" OR (This._initialized = .F.)
This._Setup()
ENDIF
LOCAL lcCaption, lcFormat
* _ForceFormat is a forced formatting managed directly from FoxCharts
lcFormat = IIF(EMPTY(ALLTRIM(This._ForceFormat)), This.Format, ALLTRIM(This._ForceFormat))
IF tlNumeric
lcCaption = ALLTRIM(TRANSFORM(This._Value, lcFormat))
ELSE
lcCaption = This.Caption
ENDIF
LOCAL loSize as xfcSize
IF NOT EMPTY(lcCaption) && Modified by Paul Newton 12 Jul 2010
loSize = This.Parent.oGfx.MeasureString(lcCaption, This._oFont) &&, This._oStringFormat)
This._Height = loSize.Height
This._Width = loSize.Width
ELSE
This._Height = 0
This._Width = 0
ENDIF
This._TransfCaption = lcCaption
ENDPROC
PROCEDURE ShapeLegend.caption_assign
lparameters tcText
This.Caption = tcText
This._UpdateMeasures()
ENDPROC
PROCEDURE ShapeLegend._drawstring
LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical
LOCAL x1, y1, lnAlign, lnMode, xBack, llBar
llBar = IIF(This.Parent.Name = "ShapeLegend",.T., .F.)
lnMode = 0 && 0 = x,y Coordinates ; 1 = xfcRectangle coordinates
lnAlign = This.Alignment
* 0 = Left 1 = Right 2 = Center
LOCAL loGfx as xfcGraphics
loGfx = This.Parent.oGfx
WITH _Screen.System.Drawing
DO CASE
CASE VARTYPE(tnWidth) + VARTYPE(tnHeight) = "NN"
lnMode = 1
* Create a STRINGFORMAT object in order to draw the string centered in the image
LOCAL loStringFmt as xfcStringFormat
LOCAL lnGdipAlign
loStringFmt = .StringFormat.New()
DO CASE
CASE lnAlign = 2 && Center
lnGdipAlign = .StringAlignment.Center
CASE lnAlign = 1
lnGdipAlign = .StringAlignment.Far
OTHERWISE
lnGdipAlign = .StringAlignment.Near
ENDCASE
loStringFmt.Alignment = lnGdipAlign
IF tlVertical
loStringFmt.FormatFlags = .StringFormatFlags.DirectionVertical
loStringFmt.LineAlignment = .StringAlignment.Center
ENDIF
LOCAL loSize as xfcSize
IF tlVertical
loSize = .Size.New(This.Parent.Width, This.Parent.Height)
ELSE
loSize = .Size.New(tnWidth, tnHeight)
ENDIF
loSize = loGfx.MeasureString(;
This._TransfCaption, This._oFont, loSize, loStringFmt)
This._Height = CEILING(loSize.Height)
This._Width = CEILING(loSize.Width)
LOCAL loRect as xfcRectangle
loRect = .Rectangle.New(tnX, tnY, tnWidth, This._Height)
x1 = tnX
y1 = tnY
IF tlVertical
xBack = tnX + tnWidth / 2 - (This._Width / 2)
DO CASE
CASE lnAlign = 0 && Left
y1 = tnY
CASE lnAlign = 1 && Right
y1 = tnY + tnHeight - This._Height
CASE lnAlign = 2 && Center
y1 = tnY + (tnHeight / 2) - (This._Height / 2)
ENDCASE
ELSE
DO CASE
CASE lnAlign = 0 && Left
xBack = tnX
CASE lnAlign = 1 && Right
xBack = tnX + tnWidth - This._Width
CASE lnAlign = 2 && Center
xBack = tnX + (tnWidth - This._Width) / 2
ENDCASE
ENDIF
CASE lnAlign = 0 && Left
STORE tnX TO x1, xBack
y1 = tnY
CASE lnAlign = 1 && Right
x1 = tnX - This._Width
xBack = x1
y1 = tnY
CASE lnAlign = 2 && Center
x1 = tnX - (This._Width / 2)
xBack = x1
y1 = tnY
ENDCASE
LOCAL lnRotation
lnRotation = This.Rotation
IF lnRotation <> 0
WITH _SCREEN.System.Drawing
LOCAL loPointF as xfcPointF
LOCAL loMatrix as xfcMatrix
loMatrix = .Drawing2D.Matrix.New()
IF lnMode = 1
loPointF = .PointF.New(tnX, tnY) && this is the point of rotation
ELSE
DO CASE
CASE lnAlign = 0 && Left
loPointF = .PointF.New(x1 + 5, y1 + This._Height / 2) && this is the point of rotation
CASE lnAlign = 1 && Right
loPointF = .PointF.New(x1 + This._Width - 5, y1 + This._Height / 2) && this is the point of rotation
CASE lnAlign = 2 && Center
loPointF = .PointF.New(x1 + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation
ENDCASE
ENDIF
loMatrix.RotateAt(lnRotation, loPointF)
loGfx.MultiplyTransform(loMatrix)
ENDWITH
ENDIF
lnRotationCenter = This.RotationCenter
* Center Rotation
IF lnRotationCenter <> 0
WITH _SCREEN.System.Drawing
LOCAL loPointFC as xfcPointF
LOCAL loMatrixC as xfcMatrix
loMatrixC = .Drawing2D.Matrix.New()
* loPointFC = .PointF.New(x1 + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation
loPointFC = .PointF.New(xBack + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation
loMatrixC.RotateAt(lnRotationCenter, loPointFC)
loGfx.MultiplyTransform(loMatrixC)
ENDWITH
ENDIF
IF This.BackColorAlpha > 0
* Draw the BackGround Rectangle
WITH _Screen.System.Drawing
IF lnMode = 0 && default
loGfx.FillRectangle( ;
.SolidBrush.New(.Color.FromARGB(This.BackColorAlpha, This.BackColor)), ;
x1, y1, This._Width, This._Height)
ELSE
loGfx.FillRectangle( ;
.SolidBrush.New(.Color.FromARGB(This.BackColorAlpha, This.BackColor)), ;
xBack, y1, This._Width, This._Height)
ENDIF
ENDWITH
ENDIF
* Draw the Text
IF lnMode = 0
LOCAL loStringFmt as xfcStringFormat
LOCAL lnGdipAlign
loStringFmt = .StringFormat.New()
DO CASE
CASE lnAlign = 2 && Center
lnGdipAlign = .StringAlignment.Center
CASE lnAlign = 1
lnGdipAlign = .StringAlignment.Far
OTHERWISE
lnGdipAlign = .StringAlignment.Near
ENDCASE
loStringFmt.Alignment = lnGdipAlign
loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, ;
.Rectangle.New(x1, y1, CEILING(This._Width), This._Height + 2), ;
loStringFmt)
ELSE
IF tlVertical
loRect = .Rectangle.New(xBack, y1, This._Width, This._Height)
loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, loRect, loStringFmt)
ELSE
loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, loRect, loStringFmt)
ENDIF
ENDIF
IF lnRotation <> 0 OR lnRotationCenter <> 0
loGfx.ResetTransform()
ENDIF
ENDWITH
RETURN
ENDPROC
PROCEDURE ShapeLegend._updatemeasures
LPARAMETERS tlNumeric
IF VARTYPE(THIS.oGfx)#'O' AND THIS.IsParent
THIS.oGfx = THIS.PARENT.oGfx
ENDIF
IF VARTYPE(THIS.oGfx) <> "O"
RETURN
ENDIF
* Measure the Legend height
IF VARTYPE(THIS._oBrush) + VARTYPE(THIS._oFont) <> "OO" OR NOT THIS._initialized
THIS._Setup()
ENDIF
LOCAL lcCaption, lcFormat
* _ForceFormat is a forced formatting managed directly from FoxCharts
lcFormat = IIF(EMPTY(ALLTRIM(THIS._ForceFormat)), THIS.FORMAT, ALLTRIM(THIS._ForceFormat))
IF tlNumeric
IF VARTYPE(THIS._Value) = "C"
lcCaption = THIS._Value
ELSE
IF this.IsParent and EMPTY(lcFormat)
lcFormat = "999,999,999,999" + ;
IIF(THIS.PARENT._ValueDecimals > 0, ;
"." + REPLICATE("9", THIS.PARENT._ValueDecimals), "")
ENDIF
lcCaption = ALLTRIM(TRANSFORM(THIS._Value, lcFormat))
IF this.IsParent and THIS.PARENT._ValueDecimals>0
lcCaption=RTRIM(RTRIM(lcCaption,'0'),'.')
ENDIF
ENDIF
ELSE
lcCaption = STRTRAN(THIS.CAPTION,[CHR(13)+CHR(10)], CHR(13)+CHR(10),-1,-1,1)
lcCaption = ALLTRIM(textmerge(lcCaption))
ENDIF
LOCAL loSize AS xfcSize
loSize = THIS.oGfx.MeasureString(lcCaption, THIS._oFont) &&, This._oStringFormat)
THIS._Height = loSize.HEIGHT
THIS._Width = CEILING(loSize.WIDTH)
THIS._TransfCaption = lcCaption
ENDPROC
PROCEDURE SideLegend.caption_assign
lparameters tcText
This.Caption = tcText
This._UpdateMeasures()
ENDPROC
PROCEDURE ToolTip.caption_assign
LPARAMETERS tcCaption
This.Caption = tcCaption
LOCAL llWordWrap
llWordWrap = This.WordWrap
WITH Thisform.FoxChartsToolTip
* .Autosize = This.AutoSize
.Alignment = This.Alignment
.BackColor = This.BackColor
.BackStyle = This.BackStyle
.BorderStyle = This.BorderStyle
.FontBold = This.FontBold
.FontItalic = This.FontItalic
.FontName = This.FontName
.FontSize = This.FontSize
.FontStrikethru = This.FontStrikethru
.FontUnderline = This.FontUnderline
.ForeColor = This.ForeColor
.Zorder(0)
IF llWordWrap
.WordWrap = .F.
.Caption = tcCaption
.WordWrap = .T.
.Autosize = .T.
ELSE
.Caption = tcCaption
ENDIF
ENDWITH
ENDPROC
PROCEDURE ToolTip.MouseMove
LPARAMETERS nButton, nShift, nXCoord, nYCoord
This.Parent.ChartCanvas.MouseMove(nButton, nShift, nXCoord, nYCoord)
ENDPROC
PROCEDURE YAxis._updatemeasures
Lparameters tlNumeric
If Vartype(This.Parent.oGfx) <> "O"
Return
Endif
* Measure the Legend height
If Vartype(This._oBrush) + Vartype(This._oFont) <> "OO"
This._Setup()
Endif
Local lcCaption, lcFormat
lcFormat = This._ForceFormat
If Empty(lcFormat)
lcFormat = This.Format
Endif
****************************************************************
* Jim Nelson 10/13/2008
*
* modified to accept text data even when expecting numeric (specifically for case GetScaleLegend(-1)
**** old way
*!* If tlNumeric
*!* lcCaption = Alltrim(Transform(This._Value, lcFormat))
*!* Else
*!* lcCaption = Alltrim(Transform(This.Caption, lcFormat))
*!* * lcCaption = ALLTRIM(TRANSFORM(This.Caption, IIF("%" $ lcFormat, "", lcFormat)))
*!* Endif
**** new way
Do Case
Case tlNumeric And "N" = Vartype (This._Value)
lcCaption = Alltrim(Transform(This._Value, lcFormat))
Case tlNumeric And "N" # Vartype (This._Value)
lcCaption = This._Value
Otherwise
lcCaption = Alltrim(Transform(This.Caption, lcFormat))
Endcase
Local loSize As xfcSize
loSize = This.Parent.oGfx.MeasureString(lcCaption, This._oFont) &&, This._oStringFormat)
This._Height = loSize.Height
This._Width = loSize.Width
This._TransfCaption = lcCaption
ENDPROC
PROCEDURE YAxis2._updatemeasures
Lparameters tlNumeric
If Vartype(This.Parent.oGfx) <> "O"
Return
Endif
* Measure the Legend height
If Vartype(This._oBrush) + Vartype(This._oFont) <> "OO"
This._Setup()
Endif
Local lcCaption, lcFormat
lcFormat = This._ForceFormat
If Empty(lcFormat)
lcFormat = This.Format
Endif
****************************************************************
* Jim Nelson 10/13/2008
*
* modified to accept text data even when expecting numeric (specifically for case GetScaleLegend(-1)
**** old way
*!* If tlNumeric
*!* lcCaption = Alltrim(Transform(This._Value, lcFormat))
*!* Else
*!* lcCaption = Alltrim(Transform(This.Caption, lcFormat))
*!* * lcCaption = ALLTRIM(TRANSFORM(This.Caption, IIF("%" $ lcFormat, "", lcFormat)))
*!* Endif
**** new way
Do Case
Case tlNumeric And "N" = Vartype (This._Value)
lcCaption = Alltrim(Transform(This._Value, lcFormat))
Case tlNumeric And "N" # Vartype (This._Value)
lcCaption = This._Value
Otherwise
lcCaption = Alltrim(Transform(This.Caption, lcFormat))
Endcase
Local loSize As xfcSize
loSize = This.Parent.oGfx.MeasureString(lcCaption, This._oFont) &&, This._oStringFormat)
This._Height = loSize.Height
This._Width = loSize.Width
This._TransfCaption = lcCaption
ENDPROC
ENDDEFINE