*--------------------------------------------------------------------------------------------------------------------------------------------------------
* (ES) AUTOGENERADO - ˇˇATENCIÓN!! - ˇˇNO PENSADO PARA EJECUTAR!! USAR SOLAMENTE PARA INTEGRAR CAMBIOS Y ALMACENAR CON HERRAMIENTAS SCM!!
* (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!!
*--------------------------------------------------------------------------------------------------------------------------------------------------------
*< FOXBIN2PRG: Version="1.19" SourceFile="foxcharts.vcx" /> (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="" />

	Name = "_chartcanvas"
	
	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: 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
	AutoSize = .T.
	backcoloralpha = 0
	Caption = "Legend"
	DragIcon = ..\
	forecoloralpha = 255
	format = 		&& Specifies the input and output formatting of a control's Value property.
	format2 = 
	Height = 17
	Name = "_legend"
	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="oledragmode" type="property" display="OLEDragMode"/>
		<memberdata name="oledropeffects" type="property" display="OLEDropEffects"/>
		<memberdata name="oledrophasdata" type="property" display="OLEDropHasData"/>
		<memberdata name="oledropmode" type="property" display="OLEDropMode"/>
		<memberdata name="anchor" type="property" favorites="True" display="Anchor"/>
		<memberdata name="baseclass" type="property" display="BaseClass"/>
		<memberdata name="class" type="property" display="Class"/>
		<memberdata name="classlibrary" type="property" display="ClassLibrary"/>
		<memberdata name="colorscheme" type="property" display="ColorScheme"/>
		<memberdata name="colorsource" type="property" display="ColorSource"/>
		<memberdata name="disabledbackcolor" type="property" display="DisabledBackColor"/>
		<memberdata name="disabledforecolor" type="property" display="DisabledForeColor"/>
		<memberdata name="dragicon" type="property" display="DragIcon"/>
		<memberdata name="dragmode" type="property" display="DragMode"/>
		<memberdata name="alignment" type="property" display="Alignment"/>
		<memberdata name="_width" type="property" display="_Width"/>
		<memberdata name="_updatemeasures" type="method" display="_UpdateMeasures"/>
		<memberdata name="name" type="property" display="Name"/>
		<memberdata name="caption" type="property" favorites="True" display="Caption"/>
		<memberdata name="caption_assign" type="method" display="Caption_Assign"/>
		<memberdata name="backstyle" type="property" display="BackStyle"/>
		<memberdata name="borderstyle" type="property" display="BorderStyle"/>
		<memberdata name="height" type="property" display="Height"/>
		<memberdata name="_memberdata" type="property" display="_MemberData"/>
		<memberdata name="wordwrap" type="property" display="WordWrap"/>
		<memberdata name="_height" type="property" display="_Height"/>
		<memberdata name="_drawstring" type="method" display="_DrawString"/>
		<memberdata name="_obrush" type="property" display="_oBrush"/>
		<memberdata name="_ofont" type="property" display="_oFont"/>
		<memberdata name="reset" type="method" display="Reset"/>
		<memberdata name="format" type="property" display="Format"/>
		<memberdata name="_transfcaption" type="property" display="_TransfCaption"/>
		<memberdata name="_vartype" type="property" display="_Vartype"/>
		<memberdata name="_value" type="property" display="_Value"/>
		<memberdata name="_value_assign" type="method" display="_Value_Assign"/>
		<memberdata name="_forceformat" type="property" display="_ForceFormat"/>
		<memberdata name="visible" type="property" display="Visible"/>
		<memberdata name="rotationcenter" type="property" display="RotationCenter"/>
		<memberdata name="format2" display="Format2"/>
		</VFPData>		&& XML Metadata for customizable properties
	_obrush = 
	_ofont = 
	_orectangle = 
	_ostringformat = 
	_transfcaption = 
	_value = 
	_vartype = 
	_width = 0
	
	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

	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.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
			IF VARTYPE(This._Value) = "C"
				lcCaption = This._Value
			ELSE 
		
				IF EMPTY(lcFormat)
					lcFormat = "999,999,999,999" + ;
						IIF(This.Parent._ValueDecimals > 0, ;
							"." + REPLICATE("9", This.Parent._ValueDecimals), "")
				ENDIF 
				lcCaption = ALLTRIM(TRANSFORM(This._Value, lcFormat))
			ENDIF
			
		ELSE
			lcCaption = ALLTRIM(TRANSFORM(This.Caption, lcFormat))
		ENDIF
		
		LOCAL loSize as xfcSize
		
		IF NOT EMPTY(lcCaption)
			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 _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>

	Caption = "ToolTip"
	Height = 17
	Name = "_tooltip"
	Width = 40
	
	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>

	alphachannel = 255		&& Numeric, 0-255 Determines the level of the transparency level; 255 = Opaque; 0 = Transparent ***Spinner0,255
	Anchor = 0
	area3dtop = .T.		&& Logical, when true, a line will be drawn on the top of the 3D Area chat
	areadrawborders = .T.		&& Logical, draws borders around each Area piece
	axisalpha = 200		&& Numeric, Determines the Alpha (transparency) for the Y and X axis and the background lines. Useful when the background contains colors. ***Spinner0,255
	axiscolor = 15790320		&& Numeric, the RGB value for the Axis main color. ***COLOR
	backcolor2 = .F.		&& 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".
	backcoloralpha = 255		&& Numeric (0-255), the transparency level of the background of the chart. ***Spinner0,255
	backgradientmode = 0		&& Numeric, if gradient background (having BackColor2 specified). *** 0 = Horizontal, 1 = Vertical, 2 = Diagonal 1 , 3 = Diagonal 2
	barlegenddirection = 0		&& 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)
	barlegendtype = 0		&& 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)
	barsperscale = 2		&& Integer, number of horizontal bars per scale legend. ***Spinner0,255
	barsspacebetween = 15		&& Numeric, for bars chart - the distance between bars in pixels. ***Spinner0,500
	bartype = 0		&& Integer (0-2), the bar type ***0 = Rectangular ; 1 = Cylinder ; 2 = Triangle
	brushtype = 1		&& Numeric, Type of brush used to fill the chart: ***1 = Solid Colors; 2 = Gradient Colors; 3 = Monochrome Hatch brush
	changecoloronmouse = .F.		&& Logical, determines if a shape color will be changed when the mouse is passed over it.
	chartrow = 1		&& 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.
	chartscount = 1		&& Numeric, the number of data series.
	chartsum = 0		&& Numeric, ReadOnly, For Pie, Doughnut and SingleBars charts, returns the sum for the current column of data when the readonly SingleData property is true.
	charttype = 1		&& 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
	charttype1 = 0
	color1 = 0		&& Numeric, the RGB value of the color from the first chart. For backwards compatibility - use Fields.Color instead
	colortype = 1		&& Numeric, the type of colors: 0 = Basic Colors   1 = Custom (default)   2 = Random   3 = Scale of Gradients
	currcolumn = 0		&& Numeric, ReadOnly, the column number from the Source alias cursor. To be used when controlling mouse events.
	currindex = 0		&& 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.
	currlegend = 		&& Character, ReadOnly, The current associated legend. To be used when controlling mouse events.
	currobjtype = 		&& Character, ReadOnly, the type of object - "Pie", "Rect" or "Legend". To be used when controlling mouse events.
	currrecno = 0		&& Numeric, ReadOnly, the RECNO(), the row value from the Source alias cursor. To be used when controlling mouse events.
	currvalue = 0		&& ReadOnly, the value of the current shape. To be used when controlling mouse events.
	depth = 20		&& Numeric, the depth in pixels, simulating a 3D effect (0 = plain) ***Spinner0,50
	donutratio = 0.50		&& For Doughnut chart - Numeric, the width of the donut related to its size ( 0.01 = full slice ; 0.99 = thin).
	fieldaxis2 = 		&& Character, the name of the field that contains the text to be drawn in the axis opposite to the scale.
	fieldcolor = 		&& Character, the field name of the cursor that contains the RGB values of the custom colors for the chart
	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
	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
	fieldlegend = 		&& Character, the field name of the cursor that contains the character values that contain the main legends of the Pie or Donut charts
	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
	fieldxaxis = 		&& For backwards compatibility - use FieldAxis2 instead
	fontname = 		&& Character, the name of the font used to display text.
	gradientinvertcolors = .F.		&& Logical, determines if the gradient start and destination colors will be inverted.
	gradientlevel = 5		&& Numeric, for gradient brush mode (-10 = destination black; 0 = solid color; +10 destination white). ***Spinner -10,10
	gradientposition = 0.6		&& 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
	gradientshapedirection = 0		&& Integer, (0-3) determines the gradient direction for gradient brush charts: *** 0 = Horizontal; 1 = Vertical; 2 = Diagonal1 ; 3 = Diagonal 2
	gradienttype = 0		&& 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
	Height = 264
	legend1 = 		&& The legend for the first column of chart. For backwards compatibility - use Fields.Color instead
	legendhidewhennull = .T.		&& Logical, For Pies, Doughnuts and Simple horizontal and vertical bars, will hide the legends associated when the source value s NULL.
	legendposition = 3		&& 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
	linecaps = .T.		&& Logical, for the case of plain line chart, shows rounded caps in each point.
	lineignorenulls = .F.
	margin = 4		&& Numeric, Specifies the margin width created in the text portion of the control.
	marginbottom = 0		&& Numeric, Specifies the bottom margin left without any drawing in the FoxCharts control.
	marginleft = 0		&& Numeric, Specifies the left margin left without any drawing in the FoxCharts control.
	marginright = 0		&& Numeric, Specifies the right margin left without any drawing in the FoxCharts control.
	margintop = 0		&& Numeric, Specifies the top margin left without any drawing in the FoxCharts control.
	maxvalue = .F.		&& If numeric, maximum value plotted along Y-Axis.  Otherwise ignored (maximum value will be calculated).
	minnumberscalelegends = 5		&& Numeric, Determines the minimum number of scales legends along the Y-Axis
	minvalue = .F.		&& If numeric, minimum value plotted along Y-Axis.  Otherwise ignored (minimum value will be calculated).
	MouseIcon = ..\..\..\gradobjects\gradobjects_foxite\gradobjects\
	multichart = .F.		&& Logical, determines if more than one kind of chart will run at the same time
	multichartmargin = .T.		&& 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
	Name = "foxcharts"
	obmp = NULL		&& Object, ReadOnly, The GDI+ Bitmap object for the Chart Canvas. For GdiPlusX users, allow direct manipulation of the charts canvas.
	ogfx = NULL		&& Object, ReadOnly, The GDI+ Graphics object for the Chart Canvas. For GdiPlusX users, allow direct manipulation of the charts canvas.
	oldstyleproperties = .F.		&& Logical, determines if the legacy style using enumerated properties will be used. Disrecommended use !
	piecompensateangles = .T.		&& 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.
	piedetachanimationsteps = 3		&& Numeric, the quantity of steps that a slice of a pie or doughnut will take till full detachment
	piedetachpixels = 30		&& Numeric, for Pie and Doughnut charts, the quantity of pixels to detach from center
	piedetachsliceonclick = .T.		&& Logical, allows detachment of pie or doughnut slices on mouse click.
	piedetachsliceonlegendclick = .F.		&& Logical, allows detachment of pie or doughnut slices on mouse click over the associated side legend
	piedirection = 0		&& Integer (0-1), determines the direction that the slices will be drawn in Pie or Doughnut charts *** 0 = Clockwise, 1 = Anticlockwise
	pieenhanceddrawing = .T.		&& Logical, For Pie and Doughnut charts. Enables the enhancing drawing mode, with all edges separately, providing a better effect.
	pieforcecircle = .F.		&& logical, for Pie and Doughnut charts, determines if the shape will be a circle with the same width and height.
	piegradcenterangle = 0		&& Numeric, the angle that the desired Center Point for the gradient brush will be applied (0-360). Use together with "PieGradCenterDistance"
	piegradcenterdistance = 0		&& Numeric, the distance from the center that the desired Center Point for the gradient brush will be applied (-2, +2). Use together with "PieGradCenterAngle"
	pielegenddistance = 0.75		&& 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
	pieshowpercent = .T.		&& Logical, shows the percentage of the slice in the tooltip.
	pointshapewidth = 2		&& Numeric, for Point chart, determines the width of the pen that will draw the shapes. ***Spinner1,10,1
	qualitycompositing = 2		&& Specifies the quality level to use during compositing. *** 0 = Default; 1 = HighSpeed; 2 = HighQuality; 3 = GammaCorrected; 4 = AssumeLinear
	qualitysmoothing = 4		&& 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
	qualitytextrenderinghint = 4		&& Specifies the quality of text rendering. *** 0 = SystemDefault; 1 = SingleBitPerPixelGridFit; 2 = SingleBitPerPixel; 3 = AntiAliasGridFit; 4 = AntiAlias; 5 = ClearTypeGridFit
	scale = 0		&& Numeric, determines the scale value for the Y axys; 0 = Automatic scale
	scaleautoformat = .T.		&& Logical, determines if the Scales formatting from "ScaleLegend.Format" will be automatically configured.
	scalebackalpha = 128		&& Numeric (0-255), Determines the level of the transparency level; 255 = Opaque; 0 = Transparent. ***Spinner0,255
	scalebackbarstype = 1		&& Integer (0-3), the background scale type; *** 0 = None; 1 = Horizontal lines; 2 = Vertical lines; 3 = Both
	scalebackcolor = 16118000		&& Numeric, the RGB value for the bar background scale color. ***Color
	scalebacklinesdash = 0		&& 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)
	scalebacklinestype = 1		&& Integer (0-3), the background scale type; *** 0 = None; 1 = Horizontal lines; 2 = Vertical lines; 3 = Both
	scalebacklineswidth = 1		&& Numeric, Width in pixels of the GDI+ pen used to draw the background scale
	scaledivider = 1		&& Numeric, the value that the scales must be divided. Useful when the scale values are very big.
	scalelinecolor = 0		&& Numeric, RGB value for the line Background color. ***Color
	scalelinezerocolor = 255		&& Numeric, the RGB value for the color of the line of the zero scale. ***COLOR
	selectedshapecolor = 8421504		&& Numeric, the RGB values for the selected shape color when property 'ChangeColoronMouse' is true ***COLOR
	shadow = .F.		&& Logical, determines if shadows will be drawn under the shapes. The deepness is defined by the "depth" property.
	shape1 = 0
	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.
	shapemousepointer = 15		&& Numeric, Specifies the shape of the mouse pointer when the mouse is over a shape of the chart at run time
	showaxis = .T.		&& Logical, for Line, Area or Point charts - defines if the X and Y axys will be drawn
	showaxis2tics = .T.		&& Logical, determines if the legend axis (axis2) will show tic marks on each legend.
	showlinezero = .T.		&& Logical, determines if the background line for the zero scale will be shown or not.
	showpercentages = .F.		&& 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
	showscale = .T.		&& Logical, determines if the scale in the Y axys will be shown
	showsidelegend = .T.		&& Logical, Shows the side legends
	showtips = .T.		&& Logical, specifies if ToolTips are shown for the controls on the specified Form object or the specified ToolBar object.
	showvaluesonshape1 = .T.
	showvaluesonshapes = .F.		&& Logical, determines if the values will be drawn inside the shapes of the chart
	showvaluezero = .T.		&& 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.
	singledata = .F.		&& Logical, ReadOnly, tells if the current chart is based on single data, eg. Pie, Doughnut, Single Bars
	sourcealias = 		&& Character, The name of the alias that contains the needed fields that will create the chart
	StatusBarText = ""
	ticlength = 5		&& Integer, the length in pixels of the tic marks used in the scales and in the legend axis. ***Spinner0,30
	version = 1.37		&& Numeric, the current version number of FoxCharts class.
	versiona = FoxCharts v1.37b ALPHA		&& Character, the detailed version of FoxCharts class, in alphanumeric format.
	Width = 360
	_3d = .F.		&& Numeric, the quantity of pixels that create the 3D effect. For backwards compatibility - use the property "Depth" instead.
	_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		&& Internal Use
	_legendpixheight = 0
	_legendwidth = 0		&& Internal use
	_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" display="SaveChartProperties"/>
		<memberdata name="debug" display="Debug"/>
		<memberdata name="acoord" display="aCoord"/>
		<memberdata name="shapetooltip" display="ShapeToolTip"/>
		<memberdata name="linecapsshape" display="LineCapsShape"/>
		<memberdata name="apalettecolors" display="aPaletteColors"/>
		<memberdata name="ogfx" display="oGfx"/>
		<memberdata name="obmp" display="oBmp"/>
		<memberdata name="drawchart" display="DrawChart"/>
		<memberdata name="changecolor" display="ChangeColor"/>
		<memberdata name="backcolor2" display="BackColor2"/>
		<memberdata name="gradientlevel" display="GradientLevel"/>
		<memberdata name="alphachannel" display="AlphaChannel"/>
		<memberdata name="area3dtop" display="Area3dTop"/>
		<memberdata name="axisalpha" display="AxisAlpha"/>
		<memberdata name="axiscolor" display="AxisColor"/>
		<memberdata name="backgradientmode" display="BackGradientMode"/>
		<memberdata name="barsspacebetween" display="BarsSpaceBetween"/>
		<memberdata name="brushtype" display="BrushType"/>
		<memberdata name="chartscount" display="ChartsCount"/>
		<memberdata name="charttype" display="ChartType"/>
		<memberdata name="colortype" display="ColorType"/>
		<memberdata name="donutratio" display="DonutRatio"/>
		<memberdata name="fieldcolor" display="FieldColor"/>
		<memberdata name="fielddetachslice" display="FieldDetachSlice"/>
		<memberdata name="fieldlegend" display="FieldLegend"/>
		<memberdata name="fontname" display="FontName"/>
		<memberdata name="linecaps" display="LineCaps"/>
		<memberdata name="multichart" display="Multichart"/>
		<memberdata name="showaxis" display="ShowAxis"/>
		<memberdata name="showscale" display="ShowScale"/>
		<memberdata name="sourcealias" display="SourceAlias"/>
		<memberdata name="piedetachpixels" display="PieDetachPixels"/>
		<memberdata name="pointshapewidth" display="PointShapeWidth"/>
		<memberdata name="showsidelegend" display="ShowSideLegend"/>
		<memberdata name="showvaluesonshapes" display="ShowValuesOnShapes"/>
		<memberdata name="scalebackcolor" display="ScaleBackColor"/>
		<memberdata name="fieldhideslice" display="FieldHideSlice"/>
		<memberdata name="scale" display="Scale"/>
		<memberdata name="scalebackalpha" display="ScaleBackAlpha"/>
		<memberdata name="scalelinecolor" display="ScaleLineColor"/>
		<memberdata name="scalebacklinestype" display="ScaleBackLinesType"/>
		<memberdata name="scalebackbarstype" display="ScaleBackBarsType"/>
		<memberdata name="scalebacklineswidth" display="ScaleBackLinesWidth"/>
		<memberdata name="scalebacklinesdash" display="ScaleBackLinesDash"/>
		<memberdata name="fieldaxis2" display="FieldAxis2"/>
		<memberdata name="afterchart" display="AfterChart"/>
		<memberdata name="areadrawborders" display="AreaDrawBorders"/>
		<memberdata name="chartrow" display="ChartRow"/>
		<memberdata name="drawreport" display="DrawReport"/>
		<memberdata name="piedetachanimationsteps" display="PieDetachAnimationSteps"/>
		<memberdata name="piecompensateangles" display="PieCompensateAngles"/>
		<memberdata name="piedetachsliceonclick" display="PieDetachSliceonClick"/>
		<memberdata name="pieenhanceddrawing" display="PieEnhancedDrawing"/>
		<memberdata name="pieshowpercent" display="PieShowPercent"/>
		<memberdata name="oldstyleproperties" display="OldStyleProperties"/>
		<memberdata name="backcoloralpha" display="BackColorAlpha"/>
		<memberdata name="scaledivider" display="ScaleDivider"/>
		<memberdata name="gradientposition" display="GradientPosition"/>
		<memberdata name="gradienttype" display="GradientType"/>
		<memberdata name="gradientinvertcolors" display="GradientInvertColors"/>
		<memberdata name="shadow" display="Shadow"/>
		<memberdata name="piegradcenterdistance" display="PieGradCenterDistance"/>
		<memberdata name="piegradcenterangle" display="PieGradCenterAngle"/>
		<memberdata name="shapemousepointer" display="ShapeMousePointer"/>
		<memberdata name="gradientshapedirection" display="GradientShapeDirection"/>
		<memberdata name="singledata" display="SingleData"/>
		<memberdata name="acolors" display="aColors"/>
		<memberdata name="savetofile" display="SaveToFile"/>
		<memberdata name="legendposition" display="LegendPosition"/>
		<memberdata name="scaleautoformat" display="ScaleAutoFormat"/>
		<memberdata name="qualitycompositing" display="QualityCompositing"/>
		<memberdata name="qualitysmoothing" display="QualitySmoothing"/>
		<memberdata name="qualitytextrenderinghint" display="QualityTextRenderingHint"/>
		<memberdata name="barlegenddirection" display="BarLegendDirection"/>
		<memberdata name="barsperscale" display="BarsPerScale"/>
		<memberdata name="bartype" display="BarType"/>
		<memberdata name="changecoloronmouse" display="ChangeColoronMouse"/>
		<memberdata name="chartsum" display="ChartSum"/>
		<memberdata name="depth" display="Depth"/>
		<memberdata name="legendhidewhennull" display="LegendHideWhenNull"/>
		<memberdata name="maxvalue" display="MaxValue"/>
		<memberdata name="minvalue" display="MinValue"/>
		<memberdata name="minnumberscalelegends" display="MinNumberScaleLegends"/>
		<memberdata name="pielegenddistance" display="PieLegendDistance"/>
		<memberdata name="piedetachsliceonlegendclick" display="PieDetachSliceOnLegendClick"/>
		<memberdata name="margin" display="Margin"/>
		<memberdata name="margintop" display="MarginTop"/>
		<memberdata name="marginleft" display="MarginLeft"/>
		<memberdata name="marginbottom" display="MarginBottom"/>
		<memberdata name="marginright" display="MarginRight"/>
		<memberdata name="scalelinezerocolor" display="ScaleLineZeroColor"/>
		<memberdata name="showaxis2tics" display="ShowAxis2Tics"/>
		<memberdata name="shapelegendexpression" display="ShapeLegendExpression"/>
		<memberdata name="pieforcecircle" display="PieForceCircle"/>
		<memberdata name="showlinezero" display="ShowLineZero"/>
		<memberdata name="showtips" display="ShowTips"/>
		<memberdata name="showvaluezero" display="ShowValueZero"/>
		<memberdata name="ticlength" display="TicLength"/>
		<memberdata name="barlegendtype" display="BarLegendType"/>
		<memberdata name="currcolumn" display="CurrColumn"/>
		<memberdata name="currvalue" display="CurrValue"/>
		<memberdata name="currindex" display="CurrIndex"/>
		<memberdata name="currlegend" display="CurrLegend"/>
		<memberdata name="currrecno" display="CurrRecno"/>
		<memberdata name="currobjtype" display="CurrObjType"/>
		<memberdata name="multichartmargin" display="MultiChartMargin"/>
		<memberdata name="selectedshapecolor" display="SelectedShapeColor"/>
		<memberdata name="anchor" display="Anchor"/>
		<memberdata name="piedirection" display="PieDirection"/>
		<memberdata name="charttype_assign" display="ChartType_Assign"/>
		<memberdata name="showpercentages" display="ShowPercentages"/>
		<memberdata name="_scalelegend2forceformat" display="_ScaleLegend2ForceFormat"/>
		<memberdata name="_axis2scalewidth" display="_Axis2ScaleWidth"/>
		<memberdata name="lineignorenulls" display="LineIgnoreNULLs"/>
		<memberdata name="_yaxiswidth2" display="_yAxisWidth2"/>
		</VFPData>		&& XML Metadata for customizable properties
	_minscale = 0
	_minscale2 = 0
	_minvalue = 0
	_ncolor = 0		&& Internal Use
	_nindex = 0
	_nmouseonshape = 0
	_nmouseover = 0
	_nrecords = 0		&& Internal use, the total  of records in the main cursor
	_o3dbrush = 		&& Internal Use, GDI+ Brush object for drawing the 3D effects
	_oborderpen = 		&& Internal Use, Gdi+ Pen for drawing borders
	_oclrblack = 
	_oclrmatrix = 		&& Internal Use, GDI+ ColorMatrix object for drawing the transparent shapes
	_oclrwhite = 
	_omainbrush = 		&& Internal Use, GDI+ Brush object for drawing the main shapes
	_orientation = 1
	_origmousepointer = 0
	_otempbmp = 		&& Internal Use, GDI+ Bitmap object for drawing the transparent shapes
	_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		&& Internal use
	_topoffset = 0
	_updaterandomcolors = .T.
	_useaxis = .T.
	_using3d = .F.
	_valuedecimals = 0
	_valueformat = 
	_valuetype = 
	_xaxisheight = 0
	_xrelative = 0
	_yaxiswidth = 0
	_yaxiswidth2 = 0
	_yrelative = 0

	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°]
				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°]
				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ó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ó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 
		
		RETURN  
	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
		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.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 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
