*--------------------------------------------------------------------------------------------------------------------------------------------------------
* (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!!
*--------------------------------------------------------------------------------------------------------------------------------------------------------
*< FOXBIN2PRG: Version="1.21" SourceFile="foxchartsbeta.vcx" CPID="1251" /> (Solo para binarios VFP 9 / Only for VFP 9 binaries)
*
*
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: isparent
		*p: ogfx
		*p: rotationcenter
		*p: _forceformat
		*p: _height
		*p: _initialized
		*p: _memberdata		&& XML Metadata for customizable properties
		*p: _obrush
		*p: _ofont
		*p: _orectangle
		*p: _ostringformat
		*p: _transfcaption
		*p: _value
		*p: _vartype
		*p: _width
	*</DefinedPropArrayMethod>

	HIDDEN AddProperty,Anchor,AutoSize,BackStyle,BorderStyle,Click,CloneObject,ColorScheme,ColorSource,Comment,DblClick,Destroy,DisabledBackColor,DisabledForeColor,DragDrop,DragIcon,DragMode,DragOver,Drag,Error,FontCondense,FontExtend,FontOutline,FontShadow,GotFocus,HelpContextID,Init,LostFocus,MiddleClick,MouseDown,MouseEnter,MouseIcon,MouseLeave,MouseMove,MousePointer,MouseUp,MouseWheel,Move,OLECompleteDrag,OLEDragDrop,OLEDragMode,OLEDragOver,OLEDragPicture,OLEDrag,OLEDropEffects,OLEDropHasData,OLEDropMode,OLEGiveFeedback,OLESetData,OLEStartDrag,ParentClass,Parent,ReadExpression,ReadMethod,Refresh,ResetToDefault,RightClick,RightToLeft,SaveAsClass,ShowWhatsThis,StatusBarText,Style,TabIndex,TabStop,Tag,UIEnable,WhatsThisHelpID,WordWrap,WriteExpression,WriteMethod,ZOrder
	*<PropValue>
		AutoSize = .T.
		backcoloralpha = 0
		Caption = "Legend"
		DragIcon = ..\..\foxcharts\
		forecoloralpha = 255
		format = 
		Height = 17
		isparent = .F.
		Name = "_legend"
		ogfx = .F.
		OLEDragPicture = ..\..\foxcharts\
		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"/>
		</VFPData>
		_obrush = 
		_ofont = 
		_orectangle = 
		_ostringformat = 
		_transfcaption = 
		_value = 
		_vartype = 
		_width = 0
	*</PropValue>
	
	HIDDEN PROCEDURE caption_assign
		LPARAMETERS tuCaption
		
		LOCAL lcType
		m.lcType = VARTYPE(m.tuCaption)
		
		IF m.lcType $ "DLTN" && Logical, Date, DateTime, Numeric
			m.tuCaption = TRANSFORM(m.tuCaption)
		ENDIF 
		
		This.Caption = m.tuCaption
		This._UpdateMeasures(.F.) && Character passed
		
		*!*	C  Character, Memo, Varchar, Varchar (Binary)
		*!*	D  Date 
		*!*	G  General 
		*!*	L  Logical 
		*!*	N  Numeric, Float, Double, or Integer
		*!*	O  Object
		*!*	Q  Blob, Varbinary
		*!*	T  DateTime 
		*!*	U  Unknown or variable does not exist
		*!*	X  Null
		*!*	Y  Currency 
		
	ENDPROC

	HIDDEN PROCEDURE Init
		THIS.IsParent = TYPE('this.Parent.Name')='C'
		IF THIS.IsParent AND VARTYPE(THIS.PARENT.oGfx)='O'
			THIS.oGfx = THIS.PARENT.oGfx
		ENDIF
		
	ENDPROC

	PROCEDURE reset		&& Resets the legend GDI+ objects
		This._Setup()
		This._UpdateMeasures()
	ENDPROC

	PROCEDURE rotation_assign
		LPARAMETERS tnRotation
		THIS.Rotation = tnRotation + IIF( tnRotation < 0, 360, 0 )
	ENDPROC

	PROCEDURE _drawstring
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, toGfx
		
		LOCAL x1, y1, lnAlign, lnMode, xBack, llBar
		llBar = IIF(THIS.IsParent AND 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 = IIF(VARTYPE(toGfx)='O', toGfx, THIS.oGfx)
		IF VARTYPE(THIS.oGfx)#'O' AND THIS.IsParent
			THIS.oGfx = THIS.PARENT.oGfx
			loGfx = THIS.oGfx
		ENDIF
		
		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, 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 THIS.IsParent AND 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 - 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, 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, 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
		
	ENDPROC

	PROCEDURE _setup
		* Update the FONT object
		
		LOCAL liStyle, lcFont
		liStyle = IIF( THIS.FONTBOLD,1,0) + IIF( THIS.FONTITALIC,2,0) + IIF( THIS.FONTUNDERLINE,4,0) + IIF( THIS.FONTSTRIKETHRU ,8,0)
		
		
		* Prepare the font object
		lcFont = IIF(THIS.IsParent AND EMPTY(THIS.FONTNAME), THIS.PARENT.FONTNAME, THIS.FONTNAME)
		
		* If no font was selected, then take the _Screen one!
		IF EMPTY(lcFont)
			lcFont = EVL(_SCREEN.FONTNAME, "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, lnColor, loBrush AS xfcSolidBrush
		
			lnColor = IIF(THIS.IsParent AND THIS.PARENT.BrushType = 3, 0, THIS.FORECOLOR)
			loColor = .COLOR.FromArgb(THIS.ForeColorAlpha, lnColor)
		
			loBrush = .SolidBrush.New(loColor)
		
			THIS._oBrush = loBrush
		
		ENDWITH
		
		THIS._initialized = .T.
		
	ENDPROC

	PROCEDURE _updatemeasures
		LPARAMETERS tlNumeric
		IF VARTYPE(THIS.oGfx)#'O' AND THIS.IsParent
			THIS.oGfx = THIS.PARENT.oGfx
		ENDIF
		
		IF VARTYPE(THIS.oGfx) <> "O"
			RETURN
		ENDIF
		
		* Measure the Legend height
		IF VARTYPE(THIS._oBrush) + VARTYPE(THIS._oFont) <> "OO" OR NOT THIS._initialized
			THIS._Setup()
		ENDIF
		
		LOCAL lcCaption, lcFormat
		
		* _ForceFormat is a forced formatting managed directly from FoxCharts
		lcFormat = IIF(EMPTY(ALLTRIM(THIS._ForceFormat)), THIS.FORMAT, ALLTRIM(THIS._ForceFormat))
		
		IF tlNumeric
			IF VARTYPE(THIS._Value) = "C"
				lcCaption = THIS._Value
			ELSE
		
				IF this.IsParent and EMPTY(lcFormat)
					lcFormat = "999,999,999,999" + ;
						IIF(THIS.PARENT._ValueDecimals > 0, ;
						"." + REPLICATE("9", THIS.PARENT._ValueDecimals), "")
				ENDIF
				lcCaption = ALLTRIM(TRANSFORM(THIS._Value, lcFormat))
				IF this.IsParent and THIS.PARENT._ValueDecimals>0
					lcCaption=RTRIM(RTRIM(lcCaption,'0'),'.')
				ENDIF
			ENDIF
		
		ELSE
			lcCaption = STRTRAN(THIS.CAPTION,[CHR(13)+CHR(10)], CHR(13)+CHR(10),-1,-1,1)
			lcCaption = ALLTRIM(textmerge(lcCaption))
		ENDIF
		
		LOCAL loSize AS xfcSize
		loSize = THIS.oGfx.MeasureString(lcCaption, THIS._oFont) &&, This._oStringFormat)
		THIS._Height = loSize.HEIGHT
		
		THIS._Width = CEILING(loSize.WIDTH)
		THIS._TransfCaption = lcCaption
		
	ENDPROC

	PROCEDURE _value_assign
		lparameters tuNewValue
		This._Value = tuNewValue
		
		This._UpdateMeasures(.T.) && Value passed
	ENDPROC

ENDDEFINE

DEFINE CLASS fields AS collection 
 	*< CLASSDATA: Baseclass="collection" Timestamp="" Scale="Pixels" Uniqueid="" />

	*<DefinedPropArrayMethod>
		*m: clear		&& Clears the contents of a ComboBox or ListBox control.
		*m: desc_assign
		*m: isempty
		*m: new
		*m: pack
		*m: setcount
		*m: type
		*m: unpack
		*p: desc
		*p: packexpr
		*a: ladesc[1,0]		&& Fields description
	*</DefinedPropArrayMethod>

	*<PropValue>
		desc = 
		Height = 23
		Name = "fields"
		packexpr = .F.
		Width = 23
	*</PropValue>
	
	PROCEDURE clear		&& Clears the contents of a ComboBox or ListBox control.
		LPARAMETERS tnIndex
		LOCAL lcProp
		LOCAL lcName, lnCol, lnLine, loMe
		WITH THIS
			m.loMe = This
			FOR m.lnline = EVL(m.tnIndex,1)TO IIF(EMPTY(m.tnIndex),THIS.COUNT,m.tnIndex)
				FOR m.lnCol=1 TO ALEN(.laDesc,1)
					m.lcName = 'loMe(m.lnLine).'+ .laDesc(m.lnCol,1)
					STORE totype('',.laDesc(m.lnCol,2)) TO (m.lcName)
				NEXT
			NEXT
			m.lcProp = '.Parent.'+.Name+'Pack'
			STORE .pack() TO (m.lcProp)
		
		ENDWITH
		
	ENDPROC

	PROCEDURE desc_assign
		LPARAMETERS vNewVal
		*To do: Modify this routine for the Assign method
		LOCAL lnCount, lnLine, la(1)
		WITH THIS
			.DESC = UPPER(rtrim(m.vNewVal,CHR(13)+CHR(1)))
			lnCount = MAX(1,ALINES(la,.DESC))
			DIMENSION .laDesc (lnCount,3)
			FOR lnLine=1 TO ALINES(la,.DESC)
				.laDesc (lnLine,1) = GETWORDNUM(la(lnLine),1,',')
				.laDesc (lnLine,2) = GETWORDNUM(la(lnLine),2,',')
				.laDesc (lnLine,3) = GETWORDNUM(la(lnLine),3,',')
			NEXT
			.PackExpr  = ''
			FOR lnLine=1 TO ALEN(.laDesc,1)
				.PackExpr = IIF(lnLine=1,'',.PackExpr+'^') + [<<loMe(lnLine).]+.laDesc(lnLine,1)+[>>]
			NEXT
		ENDWITH
		
	ENDPROC

	PROCEDURE isempty
		LPARAMETERS tnIndex
		LOCAL loMe, lnCol, lnLine, luVal
		WITH THIS
			m.loMe=this
			FOR m.lnLine = EVL(m.tnIndex,1)TO IIF(EMPTY(m.tnIndex),THIS.COUNT,m.tnIndex)
				FOR m.lnCol=1 TO ALEN(.laDesc,1)
					m.luVal = totype(EVALUATE('loMe(m.lnLine).'+ .laDesc(m.lnCol,1)),.laDesc(m.lnCol,2))
					IF NOT EMPTY(m.luVal)
						RETURN .F.
					ENDIF
				NEXT
			NEXT
		ENDWITH
		RETURN .T.
		
	ENDPROC

	PROCEDURE new
		LOCAL lnLine, loData
		m.loData = CREATEOBJECT("Empty")
		WITH THIS
			FOR m.lnLine=1 TO ALEN(.laDesc,1)
				ADDPROPERTY(m.loData,.laDesc(m.lnLine,1),Totype(.laDesc(m.lnLine,3),.laDesc(m.lnLine,2)))
			NEXT
		ENDWITH
		RETURN m.loData
		
	ENDPROC

	PROCEDURE pack
		LPARAMETERS tnDeleteIndex
		LOCAL lcExpr, lcPack, lnLine, loMe
		IF THIS.IsEmpty ()
			RETURN ''
		ENDIF
		tnDeleteIndex=EVL(tnDeleteIndex,0)
		loMe=THIS
		lcPack = ''
		WITH THIS
			lcExpr = .PackExpr
			FOR lnLine=1 TO .COUNT
				IF lnLine # tnDeleteIndex
					lcPack = lcPack + TEXTMERGE(lcExpr) + IIF(lnLine=.COUNT,'',CHR(13)+CHR(10))
				ENDIF
			NEXT
		ENDWITH
		RETURN lcPack
		
	ENDPROC

	PROCEDURE setcount
		LPARAMETERS tnCnt
		LOCAL lnLine, lnSelect, loData
		
		*--MW-->The stock method handled adding fields to the collection but not removing them.
		IF THIS.COUNT <> m.tnCnt
			LOCAL lnIncr, lnFieldNo
			lnIncr = m.tnCnt - THIS.COUNT
		
			DO WHILE THIS.COUNT # m.tnCnt
				IF lnIncr > 0
		*--Adding fields
					m.loData = THIS.New()
					THIS.ADD(m.loData)
		
				ELSE
		*--Removing fields
					lnFieldNo = THIS.COUNT
					THIS.REMOVE(lnFieldNo)
				ENDIF
			ENDDO
		ENDIF
		
	ENDPROC

	PROCEDURE type
		LPARAMETERS tcField
		LOCAL lnLine
		tcField= UPPER(tcField)
		FOR lnLine=1 TO ALEN(THIS.laDesc,1)
			IF tcField== UPPER(THIS.laDesc (lnLine,1))
				RETURN THIS.laDesc (lnLine,2)
			ENDIF
		NEXT
		RETURN 'N'
		
	ENDPROC

	PROCEDURE unpack
		LPARAMETERS lcPack
		LOCAL lcName, lnCol, lnLine, lnLines, loMe
		loMe=THIS
		WITH THIS
			lnLines = IIF(EMPTY(lcPack),0,ALINES(laPack,lcPack))
			.SetCount( lnLines )
			FOR lnLine=1 TO lnLines
				FOR lnCol=1 TO MIN(ALEN(.laDesc,1), ALINES(laCols,laPack(lnLine),'^'))
					lcName = 'loMe(lnLine).'+ .laDesc(lnCol,1)
					STORE totype(EVL(laCols(lnCol),.laDesc(lnCol,3)),.laDesc(lnCol,2)) TO (lcName)
				NEXT
			NEXT
			lcName = [.Parent.]+.Name+'Pack'
			STORE .Pack() TO (lcName)
		ENDWITH
		
	ENDPROC

ENDDEFINE

DEFINE CLASS figure AS custom 
 	*< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" />

	*<DefinedPropArrayMethod>
		*m: checkmouseposition
		*m: draw		&& Repaints a Form object.
		*m: drawcontour
		*m: setdimensions
		*p: arrowheight
		*p: bartype
		*p: caption		&& Specifies the text displayed in an object's caption.
		*p: chartindex
		*p: color
		*p: contour
		*p: coordnum
		*p: currentrow
		*p: front
		*p: frontview		&& Передний вид
		*p: legend
		*p: matrix
		*p: parentcoord
		*p: path
		*p: pointfc
		*p: recno
		*p: rotationcenter
		*p: rowsum
		*p: start
		*p: sweep
		*p: tilt
		*p: type
		*p: value		&& Specifies the current state of a control.
	*</DefinedPropArrayMethod>

	*<PropValue>
		arrowheight = 0
		bartype = 0
		caption = 
		chartindex = 0
		color = 0
		contour = .F.
		coordnum = 0
		currentrow = 0
		front = 
		frontview = .F.
		legend = 
		matrix = .F.
		Name = "figure"
		parentcoord = 0
		path = 
		pointfc = .F.
		recno = 0
		rotationcenter = .F.
		rowsum = 0
		start = 0
		sweep = 0
		tilt = .F.
		type = 
		value = .F.
	*</PropValue>
	
	PROCEDURE checkmouseposition
		LPARAMETERS tnX, tnY, tcType
		IF NOT EMPTY(tcType) AND NOT UPPER(tcType) == UPPER(THIS.TYPE)
			RETURN .F.
		ENDIF
		IF EMPTY(THIS.Contour)
			RETURN BETWEEN(tnX, THIS.LEFT, THIS.LEFT + THIS.WIDTH) AND BETWEEN(tnY, THIS.TOP, THIS.TOP + THIS.HEIGHT)
		ELSE
			RETURN _Screen.FoxChartsHelper.InsidePath(EVL(THIS.Contour,THIS.PATH),tnX,tnY)
		ENDIF
		
	ENDPROC

	PROCEDURE draw		&& Repaints a Form object.
		LPARAMETERS toGfx, toPen, toBrush, tnCanvasLeft, tnCanvastTop, tnRotationCenter
		LOCAL lnDiag, lnSinAngle
		tnCanvasLeft = EVL(tnCanvasLeft,This.LEFT)
		tnCanvastTop = EVL(tnCanvastTop,This.TOP)
		WITH THIS
			IF .Tilt OR NOT EMPTY(tnRotationCenter)
				WITH _SCREEN.SYSTEM.Drawing
					This.Matrix = .Drawing2D.Matrix.New()
					This.PointFC = .PointF.New(tnCanvasLeft, tnCanvastTop) && Центр вращения
				ENDWITH
				lnDiag = SQRT(.WIDTH^2 + .ArrowHeight^2)
				lnSinAngle = .ArrowHeight / lnDiag
				.RotationCenter= iif(EMPTY(tnRotationCenter),RTOD(ASIN(lnSinAngle)),tnRotationCenter)
				.Matrix.RotateAt(.RotationCenter, .PointFC)
				toGfx.MultiplyTransform(.Matrix)
			ENDIF
			_SCREEN.FoxChartsHelper.DrawPath( toGfx, m.toPen, m.toBrush, .PATH , 0, 0 )
		ENDWITH
		
	ENDPROC

	PROCEDURE drawcontour
		LPARAMETERS toGfx, toPen, toBrush, tnCanvasLeft, tnCanvastTop
		LOCAL lnDiag, lnSinAngle
		tnCanvasLeft = EVL(tnCanvasLeft,0)
		tnCanvastTop = EVL(tnCanvastTop,0)
		WITH THIS
			IF .Tilt
				WITH _SCREEN.SYSTEM.Drawing
					THIS.Matrix = .Drawing2D.Matrix.New()
					THIS.PointFC = .PointF.New(THIS.LEFT+tnCanvasLeft, THIS.TOP+tnCanvastTop) && Центр вращения
				ENDWITH
				m.lnDiag = SQRT(.WIDTH^2 + .ArrowHeight^2)
				m.lnSinAngle = .ArrowHeight / m.lnDiag
				.RotationCenter=RTOD(ASIN(lnSinAngle))
				.Matrix.RotateAt(.RotationCenter, .PointFC)
				toGfx.MultiplyTransform(.Matrix)
			ENDIF
		
			_Screen.FoxChartsHelper.DrawPath( m.toGfx, m.toPen, m.toBrush, .PATH , m.tnCanvasLeft, m.tnCanvastTop )
		ENDWITH
		
	ENDPROC

	PROCEDURE setdimensions
		LPARAMETERS lnLeft,lnTop,lnWidth,lnHeight
		WITH THIS
			.LEFT=lnLeft
			.TOP=lnTop
			.WIDTH = lnWidth
			.HEIGHT = lnHeight
		ENDWITH
		
	ENDPROC

ENDDEFINE

DEFINE CLASS foxcharts AS foxcharts OF "foxcharts.vcx" 
 	*< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" />

	*-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder 
	*< OBJECTDATA: ObjPath="Shapes" UniqueID="" Timestamp="" />
	*< OBJECTDATA: ObjPath="DeltaLegend" UniqueID="" Timestamp="" />
	*< OBJECTDATA: ObjPath="Tips" UniqueID="" Timestamp="" />
	*< OBJECTDATA: ObjPath="Comments" UniqueID="" Timestamp="" />

	*<DefinedPropArrayMethod>
		*m: chart2report
		*m: drawcontour
		*m: fillpathdim
		*m: getcontourmeasures
		*m: gettexture
		*m: getvalue
		*m: openword
		*m: rotate
		*m: toword
		*m: towriter
		*m: toxls
		*m: _drawcomments
		*m: _drawcone
		*m: _drawconoid
		*m: _drawfrustum
		*m: _drawpyramid
		*p: backimage
		*p: bottomvalue
		*p: column
		*p: commentssetpack
		*p: contourgraphics
		*p: contourpen
		*p: deltagradient
		*p: deltaheight
		*p: deltaposition
		*p: deltatilt
		*p: drawarrowsfromsidelegend
		*p: gradienthorcount
		*p: gradientvertcount
		*p: news
		*p: oldmouseindex
		*p: readonlyprops
		*p: row
		*p: shapelegendtype
		*p: shapelegendvertalignment
		*p: showcolcaption
		*p: showcontour
		*p: showdecimals
		*p: showdelta
		*p: showdeltapercent
		*p: showrowcaption
		*p: showvalue
		*p: sleep
		*p: texturename
		*p: texturetheme
		*p: userightclick
		*p: value		&& Specifies the current state of a control.
		*a: acolors[1,0]
		*a: acoord[1,0]
		*a: apalettecolors[1,0]
		*a: _acolors[1,0]
		*a: _apoints[1,2]
		*a: _ashapes[1,0]
		*a: _asidelegends[1,2]
		*p: _odimbrush
		*p: _orightbrush
	*</DefinedPropArrayMethod>

	*<PropValue>
		backimage = .F.
		bottomvalue = 0
		column = 0
		commentssetpack = .F.
		contourgraphics = .F.
		contourpen = .F.
		deltagradient = 0
		deltaheight = 24
		deltaposition = 1
		deltatilt = .F.
		drawarrowsfromsidelegend = .F.
		gradienthorcount = 1
		gradientvertcount = 1
		Height = 264
		Name = "foxcharts"
		news = .F.
		oldmouseindex = 0
		readonlyprops = .F.
		row = 0
		shapelegendtype = 1
		shapelegendvertalignment = 2
		showcolcaption = .F.
		showcontour = .T.
		showdecimals = 0
		showdelta = 1
		showdeltapercent = .F.
		showrowcaption = .F.
		showvalue = .T.
		sleep = .F.
		texturename = 
		texturetheme = .F.
		userightclick = .F.
		value = 0
		versiona = FoxCharts v1.44 Beta
		Width = 340
		_odimbrush = .F.
		_orightbrush = .F.
		Title.Name = "Title"
		SubTitle.Name = "SubTitle"
		XAxis.Name = "XAxis"
		YAxis.Name = "YAxis"
		ScaleLegend.Name = "ScaleLegend"
		AxisLegend2.Name = "AxisLegend2"
		ShapeLegend.Name = "ShapeLegend"
		SideLegend.Name = "SideLegend"
		ChartCanvas.Name = "ChartCanvas"
		Fields.Name = "Fields"
		ToolTip.Name = "ToolTip"
		YAxis2.Name = "YAxis2"
	*</PropValue>

	ADD OBJECT 'Comments' AS _legend WITH ;
		Alignment = 2, ;
		BackColor = 247,255,255, ;
		Caption = "Comments", ;
		FontSize = 9, ;
		Left = 113, ;
		Name = "Comments", ;
		Top = 236, ;
		Visible = .F.
		*< END OBJECT: ClassLib="foxchartsbeta.vcx" BaseClass="label" />

	ADD OBJECT 'DeltaLegend' AS _legend WITH ;
		Alignment = 2, ;
		BackColor = 247,255,255, ;
		Caption = "DeltaLegend", ;
		FontSize = 9, ;
		Left = 113, ;
		Name = "DeltaLegend", ;
		Top = 162, ;
		Visible = .F.
		*< END OBJECT: ClassLib="foxchartsbeta.vcx" BaseClass="label" />

	ADD OBJECT 'Shapes' AS shapes WITH ;
		Height = 12, ;
		Left = 113, ;
		Name = "Shapes", ;
		Top = 212, ;
		Width = 72
		*< END OBJECT: ClassLib="foxchartsbeta.vcx" BaseClass="container" />

	ADD OBJECT 'Tips' AS tips WITH ;
		AutoSize = .T., ;
		Caption = "Tips", ;
		Height = 17, ;
		Left = 108, ;
		Name = "Tips", ;
		Top = 183, ;
		Width = 24
		*< END OBJECT: ClassLib="foxchartsbeta.vcx" BaseClass="label" />
	
	PROCEDURE afterchart
		WITH THIS
			IF NOT EMPTY(.ShowDelta) AND .ChartType = 7 OR  (INLIST(.ChartType , 3, 8, 9, 11) AND .ChartsCount=1)
				PRIVATE lnHalf, loBrush, loGfx, loPen
		
				lnArrowHeight= .DeltaHeight
				lnHalf = lnArrowHeight/2
				loGfx=_SCREEN.SYSTEM.Drawing
				loPen = loGfx.PEN.New(loGfx.COLOR.Black, 1)	&& Создать карандаш
		
				IF .DeltaGradient = 0
					m.loBrush = loGfx.SolidBrush.New(loGfx.COLOR.FromARGB(128,228,228,228))
				ENDIF
		
				loOldObject=.F.
				FOR EACH loObject IN .Shapes.OBJECTS
		
					IF loObject.TYPE = 'Rect'
						lnValue=0
						IF VARTYPE(loOldObject) = 'O'
							lnX0= INT(loOldObject.LEFT + loOldObject.WIDTH/2)  && Left
							lnY0= ROUND(loOldObject.TOP + loOldObject.HEIGHT - lnArrowHeight,0)
							DO CASE
								CASE .DeltaPosition = 1
									lnY0= ROUND(loOldObject.TOP + loOldObject.HEIGHT - lnArrowHeight,0)  && Bottom
								CASE .DeltaPosition = 2
									lnY0= ROUND(loOldObject.TOP + loOldObject.HEIGHT/2,0)  && Middle
								CASE .DeltaPosition = 3
									lnY0= ROUND(loOldObject.TOP - lnHalf,0)  && Top
								OTHERWISE
									lnY0= ROUND(loOldObject.TOP - lnHalf*4,0)  && Over top
							ENDCASE
		
							lcCaption = ''
							IF .ShowDelta > 0
								IF loOldObject.VALUE # 0 AND .ShowDeltaPercent
									lnValue=(loObject.VALUE - loOldObject.VALUE) / loOldObject.VALUE * 100
									lcCaption = ALLTRIM(STR(lnValue,20,1))+'%'
								ENDIF
								lnValue=loObject.VALUE - loOldObject.VALUE
								lcCaption = IIF(EMPTY(lcCaption),'',lcCaption+', ') + TRANSFORM(lnValue)
							ENDIF
		
							lnWidth = loObject.LEFT - lnX0
							DO CASE
								CASE .DeltaPosition=1
									lnTop2 = lnY0
								CASE .DeltaPosition=2
									lnTop2 = INT(loObject.TOP+loObject.HEIGHT/2)
								CASE .DeltaPosition=3
									lnTop2 = INT(loObject.TOP - lnHalf)
								OTHER
									lnTop2 = INT(loObject.TOP - lnHalf*4)
							ENDCASE
		
							lnHeight = lnTop2-lnY0
							WITH _SCREEN.SYSTEM.Drawing
		*		Gradient brush
								IF THIS.DeltaGradient > 0
									loColor1 =  .COLOR.FromARGB(200, loOldObject.COLOR)
									loColor2 =  .COLOR.FromARGB(200, loObject.COLOR)
									loBrush = .Drawing2D.LinearGradientBrush.New(;
										.Rectangle.New(m.lnX0, m.lnY0, m.lnWidth, m.lnArrowHeight), ;
										loColor1, loColor2, 0)
								ENDIF
		
							ENDWITH
		
							lnEndWidth = 30
							lnTextLeft = lnX0
							lcPolyGon = _Screen.FoxChartsHelper.Arrows(THIS.ShowDelta, @lnTextLeft, lnY0, lnArrowHeight, lnWidth, lnEndWidth, lnValue )
							lcObjectName = 'Shape' + ALLTRIM(STR(.Shapes.OBJECTS.COUNT+1))
							THIS.Shapes.ADDOBJECT(lcObjectName,JUSTSTEM(this.Classlibrary)+[.Figure])
							WITH EVALUATE('.Shapes.'+lcObjectName)
								.CoordNum = this.Shapes.OBJECTS.COUNT
								.SetDimensions( m.lnX0, m.lnY0, m.lnWidth, lnArrowHeight)
								.ArrowHeight = m.lnHeight
								.CAPTION = lcCaption
								.PATH = lcPolyGon
								.Tilt = THIS.DeltaTilt
								.TYPE="Delta"
								.DRAW(THIS.oGfx, m.loPen, m.loBrush, 0,0)
								.Contour = _Screen.FoxChartsHelper.SimplifyPath(lcPolyGon)
								IF THIS.DeltaTilt && AND NOT EMPTY(.RotationCenter)
									.Contour = _Screen.FoxChartsHelper.RotatePath(m.lnX0, m.lnY0, .Contour, .RotationCenter)
								ENDIF
							ENDWITH
							.DeltaLegend._Value = lcCaption
							.DeltaLegend._DrawString(lnTextLeft, lnY0-CEILING(.DeltaLegend._HEIGHT/2)+1,lnWidth-8,.DeltaLegend._HEIGHT)
							.oGfx.ResetTransform()
						ENDIF
						loOldObject = loObject
					ENDIF
				NEXT
			ENDIF
			._DrawComments ()
		ENDWITH
		
	ENDPROC

	PROCEDURE chart2report
		** Chart2Report
		Local lcReportBehaviorOld
		Local oFoxChart
		lcReportBehaviorOld = Set("Reportbehavior")
		Set REPORTBEHAVIOR 90
		Private m.oFoxChart  && needed by report
		oFoxChart = This.ChartCanvas
		Report Form FoxChartsView Preview Nowait
		Set REPORTBEHAVIOR &lcReportBehaviorOld
		
		
	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
				This.AddProperty("Bartype" + m.lcIndex, 0)
			ENDFOR
		ENDIF 
		
		* Prepare the Fields collection
		This._SetFieldsCount(m.tnCount)  
	ENDPROC

	PROCEDURE currlegend_access
		RETURN IIF(This.CurrIndex = 0, "", EVL(EVALUATE('this.Shapes.Shape'+ALLTRIM(Str(This.CurrIndex))+'.Legend'), cLegend))
	ENDPROC

	PROCEDURE currobjtype_access
		LOCAL lnIndex, lcObjType
		lnIndex = This.CurrIndex
		lcObjType = IIF(lnIndex = 0, "", EVALUATE('this.Shapes.Shape'+ALLTRIM(Str(lnIndex))+'.Type'))
		RETURN lcObjType
	ENDPROC

	PROCEDURE currvalue_access
		LOCAL lnIndex, lnValue
		lnIndex = This.CurrIndex
		lnValue = IIF(EMPTY(lnIndex), 0, EVALUATE('this.Shapes.Shape'+ALLTRIM(Str(lnIndex))+'.Value'))
		RETURN lnValue
	ENDPROC

	PROCEDURE drawchart
		LPARAMETERS llForceShow
		LOCAL llSleep
		
		* 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
		m.llSleep=THIS.Sleep
		THIS.Sleep = THIS.Sleep AND NOT m.llForceShow
		THIS.ChartCanvas.DRAW()
		THIS.Sleep = m.llSleep
		
	ENDPROC

	PROCEDURE drawcontour
		LPARAMETERS lcLines, tnIndex
		_Screen.FoxChartsHelper.DrawContour(This, lcLines, tnIndex)
		
	ENDPROC

	PROCEDURE fillpathdim
		LPARAMETERS loBrush, loPath
		WITH THIS
			.oGfx.FillPath(loBrush, loPath)
			IF VARTYPE(._oDimBrush)='O'
				.oGfx.FillPath( ._oDimBrush, loPath )
			ENDIF
		ENDWITH
		
	ENDPROC

	PROCEDURE getchartproperties
		LPARAMETERS tnType, tbWrapper, tlShowDescriptions, tcReadOnlyProps
		**********************************************************************************************
		* 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
		**********************************************************************************************
		LOCAL lcCRLF, lcCollection, lcDescription, lcItem, lcMember, lcObjMem, lcObjects, lcProperty, lcResult, lcTabs, lcTempResult, 	;
			lnI, lnJ, lnRow, lnTabSpaces, lnType, 	;
			loMember, loPropertiesList
		
		*  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
		
		IF NOT EMPTY(tcReadOnlyProps)
			THIS.Readonlyprops = THIS.Readonlyprops + tcReadOnlyProps+','
		ENDIF
		
		m.lcCRLF = CHR(13) + CHR(10)
		m.lnTabSpaces = 4
		m.lcTabs = SPACE(lnTabSpaces)
		
		DO CASE
			CASE EMPTY (tnType)
				lnType = 1
			CASE 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
				lnType = 2
			CASE tnType = 4
				RETURN THIS._GetChartScript()
			OTHERWISE
				lnType = tnType
		ENDCASE
		
		lcResult  = ""
		lcObjects = ""
		lcCollection = ""
		m.loPropertiesList = THIS._GetChartProperties()
		AMEMBERS(laMembers, loPropertiesList, 3)
		
		
		*!*    2009-12-17
		*!*    CChalom: Changed order of appearance of the properties
		
		FOR lnI = 1 TO ALEN (laMembers, 1)
		
			m.lcMember = THIS._spellproperty (m.laMembers(lnI,1))
		
			lcDescription = ''
			lnRow = ASCAN (loPropertiesList._Descriptions, m.lcMember, -1, -1, 1, 9)
			IF lnRow > 0
				lcDescription = loPropertiesList._Descriptions(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, lcDescription, tlShowDescriptions)
		
				CASE "C" = TYPE ("loPropertiesList." + m.lcMember, 1) && collection container
					FOR lnJ = 1 TO EVALUATE ("loPropertiesList." + m.lcMember + ".Count")
						m.lcItem = m.lcMember + ".Item(" + TRANSFORM(lnJ) + ")"
						loMember = EVALUATE ("loPropertiesList." + m.lcItem)
						AMEMBERS (laObjMembers, loMember)
						m.lcTempResult = ''
						FOR EACH m.lcObjMem IN laObjMembers
							m.lcObjMem = THIS._spellproperty (m.lcObjMem)
							lcDescription = ''
							IF tlShowDescriptions AND PEMSTATUS(loMember, "_Descriptions", 5)
								lnRow = ASCAN (loMember._Descriptions, m.lcObjMem, -1, -1, 1, 9)
								IF lnRow > 0
									lcDescription = loMember._Descriptions(lnRow, 4)
								ENDIF
							ENDIF
		
							m.lcProperty = THIS._GetChartProp(;
								m.loPropertiesList, m.lcItem + "." + m.lcObjMem, m.lnType, THIS._savedchartproperties, lcDescription, tlShowDescriptions)
							m.lcTempResult = m.lcTempResult + m.lcProperty
						NEXT
						IF NOT EMPTY (m.lcTempResult)
							m.lcCollection = m.lcCollection + ;
								"WITH ." + m.lcMember + "(" + TRANSFORM(lnJ) + ")" + m.lcCRLF + ;
								STRTRAN(m.lcTempResult, "." + m.lcItem, m.lcTabs)+ "ENDWITH" + m.lcCRLF
						ENDIF
					NEXT
		
				OTHERWISE && Legend objects
					loMember = EVALUATE ("loPropertiesList." + m.lcMember)
					AMEMBERS (laObjMembers, loMember)
		
					m.lcTempResult = ''
					FOR EACH m.lcObjMem IN laObjMembers
						m.lcObjMem = THIS._spellproperty (m.lcObjMem)
						lcDescription = ''
						IF tlShowDescriptions AND PEMSTATUS(loMember, "_Descriptions", 5)
							lnRow = ASCAN (loMember._Descriptions, m.lcObjMem, -1, -1, 1, 9)
							IF lnRow > 0
								lcDescription = loMember._Descriptions(lnRow, 4)
							ENDIF
						ENDIF
						m.lcTempResult = m.lcTempResult + THIS._GetChartProp (;
							m.loPropertiesList, m.lcMember + "." + m.lcObjMem, lnType, THIS._savedchartproperties, lcDescription, tlShowDescriptions)
					NEXT
		
					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
		
		NEXT
		
		* Merge all types
		lcResult = lcResult + lcObjects + lcCollection
		
		*!*    2009-02-21
		*!*    CChalom: Fixed insertion of With/Endwith
		IF m.tbWrapper
			LOCAL lcCommand, laLines(1), N
			m.lcCommand = ""
			FOR N = 1 TO ALINES(laLines, m.lcResult)
				m.lcCommand = m.lcCommand + SPACE(3) + laLines(N) + m.lcCRLF
			NEXT
		
			TEXT TO 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 getcontourmeasures
		LPARAMETERS lcContour, tnLeft, tnTop, tnWidth, tnHeight
		LOCAL lnLine, lnLines, lnVal, laLines(1),la(1),lnCount
		lnLines = ALINES(laLines,lcContour)
		FOR lnLine=1 TO lnLines
			lnCount = ALINES(la,laLines(lnLine),',')
			lnVal=VAL(la(1))
			IF lnLine=1
				STORE lnVal TO tnLeft, tnWidth
			ELSE
				tnLeft = MIN(tnLeft,lnVal)
				tnWidth = MAX(tnWidth,lnVal)
			ENDIF
		
			lnVal=VAL(la(2))
			IF lnLine=1
				STORE lnVal TO tnTop, tnHeight
			ELSE
				tnTop = MIN(tnTop,lnVal)
				tnHeight = MAX(tnHeight,lnVal)
			ENDIF
			IF lnCount>5
				tnWidth  = MAX(tnWidth,VAL(la(1)) +VAL(la(3)))
				tnHeight = MAX(tnHeight,VAL(la(2)) + VAL(la(4)))
			ENDIF
		NEXT
		tnWidth = tnWidth-tnLeft
		tnHeight = tnHeight-tnTop
		
	ENDPROC

	PROCEDURE gettexture
		LPARAMETERS lcTextureTheme,lcPicture
		LOCAL lcExt, lnDir, lnLine
		IF VARTYPE(lcPicture)= 'N'
			lcPicture=TRANSFORM(lcPicture)+'.jpg'
		ENDIF
		lcTextureTheme = EVL(lcTextureTheme,THIS.TextureTheme)
		lcPicture = TRANSFORM(EVL(lcPicture,THIS.TextureName))
		DO CASE
			CASE FILE('Textures\'+ADDBS(lcTextureTheme)+lcPicture)
				RETURN 'Textures\'+ADDBS(lcTextureTheme)+lcPicture
			CASE DIRECTORY('Textures\'+ADDBS(lcTextureTheme))
				FOR lnLine=1 TO ADIR(la,'Textures\'+ADDBS(lcTextureTheme)+'*.*')
					lcExt=LOWER(JUSTEXT(la(lnLine,1)))
					IF lcExt $ [png,jpg,jpeg,gif,bmp]
						THIS.TextureName = la(lnLine,1)
						RETU 'Textures\'+ADDBS(lcTextureTheme)+THIS.TextureName
						EXIT
					ENDIF
				NEXT
		
			OTHERWISE
				FOR lnDir=1 TO ADIR(laDir,'Textures\*',"D")
					IF LEFT(laDir(lnDir,1),1)='.'
						LOOP
					ENDIF
					FOR lnLine=1 TO ADIR(la,'Textures\'+ADDBS(laDir(lnDir,1))+'\*.*')
						lcExt=LOWER(JUSTEXT(la(lnLine,1)))
						IF lcExt $ [png,jpg,jpeg,gif,bmp]
							THIS.TextureName = la(lnLine,1)
							lcTextureTheme = laDir(lnDir,1)
							RETURN 'Textures\'+ADDBS(lcTextureTheme)+THIS.TextureName
						ENDIF
					NEXT
				NEXT
		ENDCASE
		RETURN ''
		
	ENDPROC

	PROCEDURE getvalue
		LPARAMETERS tcField
		LOCAL lcNum
		WITH THIS
				GO .ROW
				IF EMPTY(tcField)
					lcNum = ALLTRIM(STR(.COLUMN))
					.VALUE = NVL(EVALUATE("nValue" +  lcNum),0)
					.BottomValue = IIF(TYPE([Bottom]+lcNum)='N',NVL(EVALUATE("Bottom" +  lcNum),0),0 )
				ELSE
					RETURN EVALUATE(tcField)
				ENDIF
		ENDWITH
		
	ENDPROC

	PROCEDURE Init
		IF NOT 'ALIAS FOXCHARTSBETA' $ SET('Class')
			SET CLASSLIB TO foxchartsBeta.vcx ADDI
		ENDIF
		IF TYPE('_Screen.FoxChartsHelper') = 'U'
			_SCREEN.ADDOBJECT('FoxChartsHelper', 'FoxChartsBeta.FoxChartsHelper')
		ENDIF
		DODEFAULT()
		
	ENDPROC

	PROCEDURE MouseDown
		LPARAMETERS nButton, nShift, nXCoord, nYCoord, toShape
			
		LOCAL llGradientInvertColors, llSingle, 	;
			lnAngle, lnDeltaLeft, lnDeltaTop, lnGradientLevel, lnHeight, lnLeft, lnMyLeft, lnMyTop, lnOldBrushType, lnRatio, lnSeconds, lnTop, lnWidth, lnX, lnX1, lnX2, lnY, lnY1, lnY2, 	;
			loGfx, loObject , loPen
		IF TYPE('thisform.Rect1.Visible')='L' AND THISFORM.Rect1.VISIBLE
			THISFORM.Rect1.VISIBLE=.F.
		ENDIF
		IF TYPE('toShape.Type') # 'C'
			RETURN
		ENDIF
		IF m.nButton=1 AND  m.toShape.TYPE='Comments'
		
			IF TYPE([thisform.Canvas2])='U'
				THISFORM.ADDOBJECT ('Canvas2','FoxChartsBeta.Pattern')
				WITH THISFORM.Canvas2
					.oGfx.SmoothingMode = _SCREEN.SYSTEM.Drawing.Drawing2D.SmoothingMode.AntiAlias
					.PEN = _SCREEN.SYSTEM.Drawing.PEN.New(_SCREEN.SYSTEM.Drawing.COLOR.Black , 2)
					.PEN.DASHSTYLE = 3
				ENDWITH
			ENDIF
			STORE 0 TO m.lnLeft, m.lnTop, m.lnWidth, m.lnHeight
			=THIS.GetContourmeasures (m.toShape.Contour, @m.lnLeft, @m.lnTop, @m.lnWidth, @m.lnHeight)
			WITH THISFORM.Canvas2
		
				.ZORDER(0)
				.BACKSTYLE=0
				.LEFT = THIS.LEFT + m.lnLeft
				.TOP= THIS.TOP + m.lnTop
				.WIDTH= m.lnWidth+1
				.HEIGHT = m.lnHeight+1
				.RenderMode = 4
		*		.CreateOSB()
				.CLEAR(_SCREEN.SYSTEM.Drawing.COLOR.Transparent)
				_Screen.FoxChartsHelper.DrawPath(.oGfx, .PEN,  , m.toShape.Contour, -m.lnLeft, -m.lnTop)
				.MyRenderOSB()
				THISFORM.MOUSEPOINTER = 5
				THISFORM.SETALL('MousePointer', 5)
				.VISIBLE = .T.
				m.lnMyLeft = .LEFT
				m.lnMyTop = .TOP
				m.lnLeft = m.lnMyLeft
				m.lnTop = m.lnMyTop
		
				DO WHILE MDOWN()
					m.lnLeft = m.lnMyLeft + MCOL(THISFORM.NAME,THISFORM.SCALEMODE) - m.nXCoord
					m.lnLeft = MAX(THIS.LEFT,MIN(THIS.LEFT+THIS.WIDTH -m.lnWidth-1,m.lnLeft))
					m.lnTop  = m.lnMyTop + MROW(THISFORM.NAME,THISFORM.SCALEMODE) - m.nYCoord
					m.lnTop = MAX(THIS.TOP, MIN(THIS.TOP +THIS.HEIGHT-m.lnHeight-1, m.lnTop))
					IF m.lnLeft = .LEFT AND m.lnTop = .TOP
						LOOP
					ENDIF
					.LEFT = m.lnLeft
					.TOP = m.lnTop
				ENDDO
				THISFORM.MOUSEPOINTER = 0
				THISFORM.SETALL('MousePointer', 0)
		
				.VISIBLE=.F.
			ENDWITH
			IF m.lnLeft = m.lnMyLeft AND m.lnTop = m.lnMyTop
				RETURN
			ENDIF
		
			WITH THIS.CommentsSet(m.toShape.ChartIndex)
				.LEFT = (m.toShape.LEFT + m.lnLeft-m.lnMyLeft) / THIS.WIDTH
				.TOP = (m.toShape.TOP + m.lnTop-m.lnMyTop) / THIS.HEIGHT
			ENDWITH
			THIS.CommentsSetPack = THIS.CommentsSet.PACK()
			THIS.Drawchart ()
			RETURN
		ENDIF
		
		IF m.nButton=1 AND m.toShape.TYPE='Legend'
			m.lnSeconds = SECONDS()+1
			m.lnX2=-1
			m.lnX1=m.nXCoord
			m.lnY1=m.nYCoord
			WITH _SCREEN.SYSTEM.Drawing
				m.loGfx = .Graphics.FromHWnd(THISFORM.HWND)	&& Create a Graphics object
				m.loGfx.SmoothingMode=4
				m.loPen = .PEN.New(.COLOR.Blue,IIF(INLIST(THIS.ChartType,1,2,7,12),6,3))	&& Создать карандаш
				m.lnOldBrushType= THIS.BrushType
				m.lnGradientLevel = THIS.GradientLevel
				m.llGradientInvertColors = THIS.GradientInvertColors
				THIS.GradientInvertColors =.T.
				THIS.GradientLevel= 9
		
				IF m.lnOldBrushType=1
					THIS.BrushType=2
				ENDIF
				IF m.lnOldBrushType=2
					THIS.BrushType=1
				ENDIF
		
				THIS._PrepareBrushes(0, 0, THIS.WIDTH, THIS.HEIGHT, .T., m.toShape.ChartIndex, .T.)
		
				IF m.lnOldBrushType # THIS.BrushType
					THIS.BrushType=m.lnOldBrushType
				ENDIF
				THIS.GradientLevel=m.lnGradientLevel
				THIS.GradientInvertColors = m.llGradientInvertColors
		
				m.loPen.Brush= THIS._oMainBrush
				m.loPen.StartCap=18
				m.loPen.EndCap=20
				m.loPen.DASHSTYLE=1
				m.llSingle = THIS.Singledata OR THIS.ChartsCount=1
		
				FOR EACH m.loObject IN THIS.Shapes.OBJECTS
					DO CASE
						CASE THIS.ChartType<3 && Pie and donut
		
							IF m.loObject.TYPE $ 'RectPie' AND m.loObject.Currentrow=m.toShape.VALUE
		
								m.lnWidth  = m.loObject.WIDTH / 2
								m.lnHeight = m.loObject.HEIGHT / 2
								m.lnX = m.loObject.LEFT + m.lnWidth
								m.lnY = m.loObject.TOP + m.lnHeight
								m.lnAngle = m.loObject.START  + m.loObject.Sweep / 2
								m.lnAngle = _Screen.FoxchartsHelper.UnAxonometric(m.lnAngle, m.lnWidth, m.lnHeight)
		
								m.lnRatio = IIF(THIS.ChartType=1,0.5,THIS.DonutRatio)
								m.lnRatio =  m.lnRatio + (1 - m.lnRatio) / 2
								m.lnX2 = m.lnX + COS(DTOR(m.lnAngle)) * m.lnWidth  * m.lnRatio
								m.lnY2 = m.lnY + SIN(DTOR(m.lnAngle)) * m.lnHeight * m.lnRatio
								m.lnX2=m.lnX2 + OBJTOCLIENT(THIS,2)
								m.lnY2=m.lnY2 + OBJTOCLIENT(THIS,1)
								m.loGfx.Drawline(m.loPen, m.lnX1, m.lnY1, m.lnX2, m.lnY2)
								EXIT
							ENDIF
						CASE m.llSingle
							IF m.loObject.TYPE = 'Rect' AND m.loObject.Currentrow=m.toShape.VALUE
								m.lnX2 = m.loObject.LEFT + m.loObject.WIDTH/2 + OBJTOCLIENT(THIS,2)
								m.lnY2 = m.loObject.TOP + m.loObject.HEIGHT/2 + OBJTOCLIENT(THIS,1)
								m.loGfx.Drawline(m.loPen, m.lnX1, m.lnY1, m.lnX2, m.lnY2)
								EXIT
							ENDIF
						OTHERWISE
							IF m.loObject.TYPE = 'Rect' AND m.loObject.ChartIndex = m.toShape.ChartIndex
								IF m.loObject.LEFT=0 AND m.loObject.TOP=0
									LOOP
								ENDIF
								m.lnX2=m.loObject.LEFT + m.loObject.WIDTH/2 + OBJTOCLIENT(THIS,2)
								m.lnY2=m.loObject.TOP + m.loObject.HEIGHT/2 + OBJTOCLIENT(THIS,1)
								m.loGfx.Drawline(m.loPen, m.lnX1, m.lnY1, m.lnX2, m.lnY2)
							ENDIF
		
					ENDCASE
				NEXT
			ENDWITH
		
			DO WHILE MDOWN()
			ENDDO
		ENDIF
		DO WHILE MDOWN()
		ENDDO
		THISFORM.CLS()
		
	ENDPROC

	PROCEDURE MouseUp
		LPARAMETERS nButton, nShift, nXCoord, nYCoord, toShape
		
	ENDPROC

	PROCEDURE openword
		* Code from Alex Yudin
		* 23.11.2013: Koen added code to avoid "Application is Busy" 
		* Parameters from ToWord
		 
		Lparameters tcDoc, tlInvisible, tcPassWord
		Local loWord, lnWindow, lcPath, lcPassWord
		Local loErr As Object
		
		#Define wdFormatDocument 0
		#Define wdFormatDocument97 0
		
		*!* lcPassWord = IIF(VARTYPE(m.tcPassWord) == 'C', m.tcPassWord, SPACE(0))
		
		Declare Integer SetForegroundWindow In Win32API Long HWnd
		Declare Long FindWindow In Win32API String lpClassName,String lpWindowName
		Try
			loWord=Getobject(,"WORD.APPLICATION")
		Catch To m.loErr When m.loErr.ErrorNo=1426
			loWord=Createobject("WORD.APPLICATION")
		Finally
		Endtry
		
		** To avoid "Application is Busy" error messages using OLE Automation. see also - KB240809
		Application.OLERequestPendingTimeout = 0
		
		If Type('loWord.ActiveDocument')='O'
			m.loWord.ActiveDocument.Close
		Endif
		
		lnWindow = FindWindow(.Null., m.loWord.Name)
		
		If !Empty(m.tcDoc)
			tcDoc=Lower(Forceext(Alltrim(m.tcDoc),'DOC'))
			If File(m.tcDoc)
				*tcDoc=Fullpath(m.tcDoc)
				m.loWord.Documents.OpenFullpath(m.tcDoc)
			Else
				m.loWord.Documents.Add ("Normal", .F., 0)
				*lcPath=Justpath(m.tcDoc)
				If Not Directory(Justpath(m.tcDoc))
					Md (Justpath(m.tcDoc))
				Endif
				Try
					m.loWord.ActiveDocument.SaveAs(m.tcDoc,0,.F.,m.lcPassword)
				Catch To m.loErr
				Finally
				Endtry
			Endif
		Endif
		loWord.Visible=! m.tlInvisible
		If m.lnWindow # 0
			SetForegroundWindow(m.lnWindow)
		Endif
		Return m.loWord
	ENDPROC

	PROCEDURE rotate
		LPARAMETERS lnX0,lnY0, lnX, lnY, lnNewAngle
		LOCAL lnAlfa, lnC, lnX1, lnY1
		
		lnX1=lnX-lnX0
		lnY1=lnY-lnY0
		
		lnNewAngle = DTOR(lnNewAngle)
		
		* Координаты (lnX1,lnY1) в результате поворота точки (x, y)
		lnX = lnX1*COS(lnNewAngle)-lnY1*SIN(lnNewAngle) +lnX0
		lnY = lnX1*SIN(lnNewAngle)+lnY1*COS(lnNewAngle) +lnY0
		
	ENDPROC

	PROCEDURE savechartproperties
		****************************************************************
		*   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
		IF TYPE('this.CommentsSet.Name')='C'
			THIS.CommentsSetPack = THIS.CommentsSet.PACK()
		ENDIF
		
		THIS._SavedChartProperties = THIS._GetChartProperties()
		
		
		
		
		*!*	****************************************************************
		*!*	*   Jim Nelson   10/20/2008
		*!*	*
		*!*	* Save current settings of Chart Properties so that later comparisons
		*!*	* can determine which properties have changed
		
		*!*	This._SavedChartProperties = This._GetChartProperties()
		
	ENDPROC

	PROCEDURE shapemouseenter
		LPARAMETERS nButton, nShift, nXCoord, nYCoord, loShape
		LOCAL lcLegend, lnChart, lo 
		
		lnChart=loShape.ChartIndex
		lcLegend = EVL(loShape.Legend,'')
		
		FOR EACH lo IN this.Shapes.Objects
			IF lo.Type = 'Legend' AND ALLT(EVL(lo.Legend,''))==lcLegend
				IF TYPE('THISFORM.Rect1')='U'
					THISFORM.ADDOBJECT('Rect1','Shape')
					THISFORM.Rect1.BACKSTYLE=0
					BINDEVENT(THISFORM.rect1,'MouseDown',THIS.ChartCanvas ,'MouseDown')
				ENDIF
				WITH THISFORM.rect1
					.LEFT = lo.Left - 1 + OBJTOCLIENT(THIS,2)
					.WIDTH = lo.Width + 4
					.TOP = lo.Top + OBJTOCLIENT(THIS,1)-1
					.HEIGHT = lo.Height + 1
					.VISIBLE=.T.
					.BORDERCOLOR = RGB(255,0,0)
				ENDWITH
				RETURN
				TRY
					LOCAL lcBell
					lcBell = SET("Bell")
					SET BELL TO (ADDBS(GETENV('windir')))+"MEDIA\Start.WAV"
					?? CHR(7)
					SET BELL TO (lcBell)
				CATCH
				ENDTRY
			ENDIF
		NEXT
		
	ENDPROC

	PROCEDURE shapemouseleave
		LPARAMETERS nButton, nShift, nXCoord, nYCoord, tnValue, tcLegend, tnCoordIndex
		IF TYPE('thisform.Rect1.Visible')='L'
			THISFORM.Rect1.VISIBLE=.F.
		ENDIF
		
	ENDPROC

	PROCEDURE toword
		* Code from Alex Yudin
		* History  : Koen Piller added codes for Clipboard checking in order to
		*            avoid errors when the clipboard is already in use
		*            Koen changed default saving directory and added "FindFirstFile"
		*            to avoid tcDir contains short a shortfilename
		
		Local lcDir, lcFile, lcString, lcTableNum, lcVal, lcWordName, lhClipBMP, lhWndWord, lnChart
		Local lnColumns, lnEnd, lnLine, lnRows, lnStart, lnStartRows, loTable, loWord, luValue, lcBuffer
		** Function FindFirstFile derived from sample code posted by
		** AirCon (IS/IT--Manageme)  on TekTips.com on May 12, 2003
		Declare Long FindFirstFile In Kernel32 As fnFindFirst ;
			String cFileName, String @WIN32_DATA
		Declare FindClose In Kernel32 As fnFindClose Long hFile
		
		lcDir = GETENV("temp")
		lcFile = 'Charts.DOC'
		lcBuffer = Replicate(Chr(0), 318)
		hFile = fnFindFirst(ADDBS(lcDir)+m.lcFile, @m.lcBuffer)
		If (m.hFile > 0)
			lcFile = Substr(m.lcBuffer, 45)
			lcFile = Left(m.lcFile, At(Chr(0), m.lcFile)-1)
			fnFindClose(m.hFile)
		Endif
		Clear Dlls fnFindFirst, fnFindClose
		lcWordName = m.lcDir + m.lcFile
		#Define cf_bitmap  2
		#Define cf_dib     8
		#Define obj_bitmap 7
		
		
		Declare Integer CloseClipboard In user32
		Declare Integer OpenClipboard In user32 Integer HWnd
		Declare Integer GetClipboardData In user32 Integer uFormat
		Declare Integer IsClipboardFormatAvailable In user32 Integer wFormat
		Declare Integer GetObjectType In gdi32 Integer h
		
		***
		Local Array laHeaders(This.ChartsCount+1,2)
		laHeaders(1,1) = This.FieldLegend
		
		For lnChart=1 To This.ChartsCount
			laHeaders(m.lnChart+1,1) = This.Fields(m.lnChart).Fieldvalue
			laHeaders(m.lnChart+1,2) = Evl(This.Fields(m.lnChart).Legend,'-')
		Next
		If This.ChartsCount = 1
			laHeaders(1,2) = Evl(This.Fields(1).Legend,'-')
			laHeaders(2,2) = '-'
		Else
			laHeaders(1,2) = '-'
		Endif
		
		loWord = This.OpenWord(m.lcWordName,)
		lnRows = 1
		lnColumns = Alen(m.laHeaders,1)
		This.oBMP.toClipboard()
		*= OpenClipboard (0)
		*= CloseClipboard ()
		With m.loWord
			lhWndWord = FindWindow("OPUSApp", '')  &&"OPUSApp" is the internal name of the MSWord-Class
			.Selection.WholeStory
		
			lhClipBMP = GetClipboardData (cf_bitmap)
			If m.lhClipBMP = 0 Or GetObjectType(m.lhClipBMP) # obj_bitmap
				lcFile = Addbs(Getenv('temp')) + Sys(2015) + ".PNG"
				This.SaveToFile(m.lcFile)
				.Selection.InlineShapes.AddPicture(m.lcFile,.F.,.T.)
				Erase (m.lcFile)
			Else
				.Selection.paste()
			Endif
			.ActiveDocument.Tables.Add(.Selection.Range(), m.lnRows+1, m.lnColumns, .T., .F.)
			lcTableNum = Evl(m.lcTableNum,1)
			Select (This.SourceAlias)
			loTable = .ActiveDocument.Tables(m.lcTableNum)
			loTable.Select
			lnStartRows = 1 &&loTable.ROWS.COUNT for multiple use
			lcString = ''
			For lnLine = 1 To m.lnColumns
				lcString = m.lcString+Alltrim(m.laHeaders(m.lnLine,2)) + iif(m.lnLine = m.lnColumns,Chr(13),Chr(9))
			Next
			Select (This.SourceAlias)
			lnRows = 0
		
			Scan
				lnRows = m.lnRows + 1
				For lnLine = 1 To m.lnColumns
					lcVal = m.laHeaders(m.lnLine,1)
					luValue = iif(Type(m.lcVal)=='U','-',Nvl(Evaluate(m.laHeaders(m.lnLine,1)),'-'))
					lcString = m.lcString + Transform(m.luValue) + iif(m.lnLine = m.lnColumns,Chr(13),Chr(9))
				Next
			Endscan
			If m.lnRows>1
				.Selection.movedown (5, 1)
				.Selection.insertrows(m.lnRows-1)
			Endif
			_Cliptext = m.lcString
			lnStart = m.loTable.Cell(m.lnStartRows,1).Range.Start
			lnEnd = m.loTable.Cell(m.lnStartRows + m.lnRows,m.lnColumns).Range.End
			.ActiveDocument.Range(m.lnStart,m.lnEnd).Paste()
			.ActiveDocument.Saved = .T.
			.Visible=.T.
		* SetWindowPos moves the window to the top, using the window handle
			Declare SetWindowPos In WIN32API Long HWnd, Long hwndafter, ;
				LONG x, Long Y, Long cx, Long cy, Long Flags
		
			= SetWindowPos(m.lhWndWord, -1, 0,0,0,0, 3) && Moves Word to the topmost
			= SetWindowPos(m.lhWndWord, -2, 0,0,0,0, 3) && Not  topmost
		*    .Selection.TypeParagraph
		Endwith
		
		
	ENDPROC

	PROCEDURE towriter
		* Code from Alex Yudin
		LOCAL lcVal, lnChart, lnColumns, lnLine, lnRowCount, lnRows, 	;
			loChart, loCoreReflection, loDesktop, loDispatcher, loDocument, loFrame, loRange, loTable, 	;
			luValue
		LOCAL loWriter, laArgs(4), loProperty
		TRY
			m.loWriter = CREATEOBJECT("com.sun.star.ServiceManager")
		CATCH
			MESSAGEBOX('Open Office not installed')
		ENDTRY
		IF VARTYPE(m.loWriter) # "O"
			RETURN .F.
		ENDIF
		m.loDesktop = m.loWriter.createInstance("com.sun.star.frame.Desktop")
		m.loDispatcher = m.loWriter.createInstance("com.sun.star.frame.DispatchHelper")
		m.loCoreReflection = m.loWriter.createInstance("com.sun.star.reflection.CoreReflection")
		WITH m.loCoreReflection.forName("com.sun.star.beans.PropertyValue")
			FOR m.lnLine=1 TO ALEN(laArgs,1)
				m.loProperty =CREATEOBJECT( "Empty" )
				.CREATEOBJECT(@m.loProperty)
				laArgs(m.lnLine)=m.loProperty
			NEXT
		ENDWITH
		RELEASE m.loProperty
		COMARRAY(m.loDesktop,10)
		* New document
		laArgs[1].NAME = "ReadOnly"
		laArgs[1].VALUE = .F.
		
		m.loDocument = m.loDesktop.LoadComponentFromUrl( "private:factory/swriter", "_blank", 0, @laArgs )
		m.loFrame = m.loDocument.getCurrentController().getFrame()
		laArgs(1).NAME = "Text"
		laArgs(1).VALUE = " "
		
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:InsertText", "", 0, @laArgs)
		*** Insert table
		SELECT (This.SourceAlias)
		m.lnRows = RECCOUNT()
		
		m.lnColumns = This.ChartsCount+1
		m.lnRowCount = m.lnRows+1
		LOCAL laArray(lnColumns, lnRowCount), laHeaders(lnColumns)
		STORE '-' TO m.laArray
		laHeaders(1) = This.FieldLegend
		FOR m.lnChart=1 TO This.ChartsCount
			laHeaders(m.lnChart+1) = This.FIELDS(m.lnChart).Fieldvalue
			m.laArray(m.lnChart+1,1) = EVL(This.FIELDS(m.lnChart).Legend,'-')
		NEXT
		IF This.ChartsCount = 1
			m.laArray(2,1) = EVL(This.FIELDS(1).Legend,'-')
		ENDIF
		
		m.lnRows = 0
		
		SCAN
			m.lnRows = m.lnRows + 1
			FOR m.lnLine=1 TO m.lnColumns
				m.lcVal = laHeaders( m.lnLine)
				m.luValue = IIF(TYPE(m.lcVal)='U','-',NVL(EVALUATE(m.lcVal),'-'))
				m.laArray(m.lnLine,m.lnRows+1)= TRANSFORM(m.luValue)
			NEXT
		ENDSCAN
		
		laArgs(1).NAME = "TableName"
		laArgs(1).VALUE = "ChartTable"
		laArgs(2).NAME = "Columns"
		laArgs(2).VALUE = m.lnColumns
		laArgs(3).NAME = "Rows"
		laArgs(3).VALUE = m.lnRows+1
		laArgs(4).NAME = "Flags"
		laArgs(4).VALUE = 9
		
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:InsertTable", "", 0, @laArgs)
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:GoToStartOfDoc", "", 0, @laArgs)
		
		m.loTable = m.loDocument.TextTables.getByIndex(0)
		m.loRange = m.loTable.getCellRangeByPosition(0,0, m.lnColumns-1, m.lnRows)
		m.loRange.SetDataArray(@m.laArray)
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:Escape", "", 0, @laArgs)
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:GoToStartOfDoc", "", 0, @laArgs)
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:GoToStartOfDoc", "", 0, @laArgs)
		
		
		THISFORM.ParentForm.Foxcharts1.oBmp.ToClipboard()
		laArgs[1].NAME = ""
		laArgs[1].VALUE = ""
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:Paste", "", 0, @laArgs)
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:Escape", "", 0, @laArgs)
		m.loDispatcher.executeDispatch(m.loFrame, ".uno:GoToStartOfDoc", "", 0, @laArgs)
		
		m.loFrame.getContainerWindow.setVisible(.T.)
		
	ENDPROC

	PROCEDURE toxls
		LOCAL lcClip, lcLegend, lcOldCliptext, lcWorkBook, llOK, 	;
			lnChart, lnCount, lnHeight, lnLine, loBook, loSheet, loXls
		* Trying to attach launched Excel
		m.llOK=.T.
		TRY
			m.loXls=GETOBJECT(,"EXCEL.APPLICATION")
		CATCH TO loErr
			m.llOK=.F.
		ENDTRY
		
		IF ! m.llOK
			m.llOK=.T.
			TRY
				m.loXls=CREATEOBJECT("EXCEL.APPLICATION")
			CATCH TO loErr
				m.llOK=.F.
			ENDTRY
		ENDIF
		m.lcWorkBook=GETENV("TEMP")+'\Foxcharts.xls'
		WITH m.loXls
			.DisplayAlerts=.F.
			m.loBook=.Workbooks.ADD
			m.llOK=.T.
			TRY
				m.loBook.SAVEAS(m.lcWorkBook)
			CATCH
				m.llOK=.F.
			ENDTRY
			IF NOT m.llOK
				.QUIT
				m.loXls=0
				RETURN
			ENDIF
			m.lcOldCliptext=_CLIPTEXT
		
		* Chart image to Clipboard
			THIS.oBmp.ToClipboard()
		* Insert image into Active sheet
			.activesheet.Paste
			m.lnHeight=.activesheet.PICTURES(1).HEIGHT
			m.loSheet=.activesheet
			FOR m.lnLine=1 TO 1000
				IF m.loSheet.cells(m.lnLine,1).TOP>m.lnHeight
					EXIT
				ENDIF
			NEXT
			m.lnCount = THIS.ChartsCount
		
		
			m.loSheet.cells(m.lnLine,1).SELECT
			m.lcClip = '-'
			FOR m.lnChart=1 TO m.lnCount
				TEXT TO m.lcClip addi
			<<EVL(This.FIELDS(m.lnChart).Legend,'-')>>
				ENDTEXT
			NEXT
		
			m.lcClip=m.lcClip+CHR(13)
			SELECT (THIS.sourcealias)
			m.lcLegend=THIS.FieldLegend
			SCAN
				m.lcClip = m.lcClip +ALLT(&lcLegend.)+CHR(9)
				FOR m.lnChart=1 TO m.lnCount
					m.lcClip = m.lcClip +TEXTMERGE([<<EVALUATE(This.FIELDS(m.lnChart).Fieldvalue))>>])+IIF(m.lnChart= THIS.ChartsCount,CHR(13),CHR(9))
				NEXT
			ENDSCAN
			_CLIPTEXT=m.lcClip
		
			m.llOK = .T.
			.activesheet.Paste
		
			_CLIPTEXT=m.lcOldCliptext
			WITH m.loSheet.RANGE(m.loSheet.cells(m.lnLine,1),m.loSheet.cells(m.lnLine,m.lnCount+1))
				.HorizontalAlignment =-4108
				.VerticalAlignment=-4108
				.WrapText = .T.
			ENDWITH
			m.loSheet.COLUMNS("A:A").EntireColumn.AUTOFIT
			m.loSheet.cells(1,1).SELECT
			.VISIBLE=.T.
		* SetWindowPos moves the window to the top, using the window handle
			DECLARE SetWindowPos IN WIN32API LONG HWND, LONG hwndafter, ;
				LONG x, LONG Y, LONG cx, LONG cy, LONG FLAGS
			= SetWindowPos(.HWND, -1, 0,0,0,0, 3) && Moves Excel to the topmost
			= SetWindowPos(.HWND, -2, 0,0,0,0, 3) && Not topmost
		
		ENDWITH
		
	ENDPROC

	PROCEDURE _beforedraw
			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()
				RETURN
			ENDIF
		
		* Check for the minimum dimensions
			IF This.ChartCanvas.Width < 30 OR ;
				This.ChartCanvas.Height < 30
				RETURN
			ENDIF
		
			m.loChart._CheckParams()
			m.loChart._UpdateChartInfo()
			THIS.Shapes.CLEAR
		
			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()
					RETURN
				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()
		
		
		
	ENDPROC

	PROCEDURE _checkmouseposition
		LPARAMETERS nButton, nShift, nXCoord, nYCoord, lnValue, lnCoordIndex, toObject
		* Passed by reference: lnValue
		LOCAL lcObjectName, llFound, lnChartIndex, lnCoords, lnLeft, lnLine, lnNum, lnRecno, lnRecord, lnSelect, lnTop, lnX, lnY, 	;
			loFirstSlice , loFoundShape, loShape
		m.toObject = .F.
		WITH THIS
			IF TYPE('.Shapes.Shape1.name') <> "C" OR nYCoord < 0 OR nXCoord <0
				.MOUSEMOVE(nButton, nShift, nXCoord, nYCoord, toObject)
				.OldMouseIndex = 0
				RETURN
			ENDIF
			m.lnLeft = ._xRelative &&+ .Left
			m.lnTop  = ._yRelative &&+ .Top
			lnX=nXCoord - m.lnLeft
			lnY=nYCoord - m.lnTop
			lnCoords = .Shapes.CONTROLCOUNT
		
			FOR EACH loShape IN .Shapes.OBJECTS
				IF loShape.TYPE $ "Title,Subtitle,YaxisCaption,Yaxis2Caption,XaxisCaption,Legend,ScaleLegend,Comments" AND loShape.CheckMousePosition(lnX, lnY)
					m.toObject = loShape
					lnValue = loShape.VALUE
					lnCoordIndex = loShape.CoordNum
					IF NOT loShape.TYPE = "Legend"
						=IIF(.ShowContour AND .OldMouseIndex # loShape.CoordNum,.DrawContour(loShape.Contour,loShape.CoordNum),.F.)
						.OldMouseIndex = loShape.CoordNum
						RETURN
					ENDIF
				ENDIF
		
		* Проверим "Delta"
				IF .ShowDelta > 0 AND loShape.CheckMousePosition(lnX,lnY,"Delta")
					m.toObject = loShape
					=IIF(.ShowContour AND .OldMouseIndex # loShape.CoordNum, .DrawContour(loShape), .F.)
					.OldMouseIndex = loShape.CoordNum
					RETURN
		
				ENDIF
		
		* Проверим "ShapeLegend"
				IF .ShowValuesOnShapes AND loShape.CheckMousePosition(lnX,lnY,"ShapeLegend")
					m.toObject = loShape
					=IIF(.ShowContour AND .OldMouseIndex # loShape.CoordNum,.DrawContour(loShape.Contour,loShape.CoordNum),.F.)
					.OldMouseIndex = loShape.CoordNum
					RETURN
				ENDIF
			NEXT
		
			DO CASE
		
				CASE ._GeneralType $ "Bar,Point"
					lnRecord = ._nrecords+1
					FOR lnNum=.Shapes.CONTROLCOUNT TO 1 STEP -1  && Reverse in order to catch the first drawing
						lcObjectName='Shape'+ALLTRIM(STR(lnNum))
						loShape=EVALUATE('.Shapes.' + lcObjectName)
						IF loShape.TYPE = 'Delta'
							LOOP
						ENDIF
						IF NOT loShape.TYPE $ 'Title,Subtitle'
							lnRecord = lnRecord -1
						ENDIF
						IF loShape.CheckMousePosition(lnX,lnY,'Rect')
							IF .ShowContour AND .OldMouseIndex # loShape.CoordNum
								=.DrawContour(EVL(loShape.Front,loShape.Contour),loShape.CoordNum),.F.)
							ENDIF
							.OldMouseIndex = loShape.CoordNum
		
						ELSE
							LOOP
						ENDIF
						toObject = loShape
						m.lnValue  = loShape.VALUE
						m.lnCoordIndex = loShape.CoordNum
						IF m.loShape.TYPE $ "Legend"
							._nMouseOnShape = 0
							.OldMouseIndex = loShape.CoordNum
							RETURN
						ENDIF
		
						IF ._nMouseOnShape = 0
							._nMouseOnShape = lnRecord
							.ShapeMouseEnter(nButton, nShift, nXCoord, nYCoord, loShape)
						ELSE
							IF ._nMouseOnShape # loShape.CoordNum
								._nMouseOnShape = loShape.CoordNum
		
								.ShapeMouseEnter(nButton, nShift, nXCoord, nYCoord, loShape)
		
							ELSE && Mouse over the shape
								.ShapeMouseMove(nButton, nShift, nXCoord, nYCoord, m.lnValue, ,m.lnCoordIndex)
							ENDIF
						ENDIF
		
						.OldMouseIndex = loShape.CoordNum
						RETURN
					NEXT
		
					IF ._nMouseOnShape # 0
						._nMouseOnShape = 0
						.ShapeMouseLeave(nButton, nShift, nXCoord, nYCoord, loShape)
					ENDIF
		
		
				CASE ._GeneralType = "Pie"
		
		
		* Adapted code from Luis Maria Guayan - VFP MVP from Argentina
		
					LOCAL lnX1, lnX2, lnX3, lnY1, lnY2, lnY3, lnStart, lnSweep, lnValue, lnAngle
		
					llFound = .F.
					FOR EACH loFirstSlice IN .Shapes.OBJECTS
						IF loFirstSlice.TYPE='Pie'
							.OldMouseIndex = loFirstSlice.CoordNum
							llFound = .T.
							EXIT
						ENDIF
					NEXT
		
					IF NOT llFound
						RETURN
					ENDIF
		
		* Center of Ellipse
					m.lnX1 = loFirstSlice.WIDTH / 2
					m.lnY1 = loFirstSlice.HEIGHT / 2
		
		* Coordinates inside the Shape
					IF ._Pie1stDetached
						m.lnX2 = lnX - m.lnX1 - ._PieX0
						m.lnY2 = - (lnY - m.lnY1 - ._PieY0)
					ELSE
						m.lnX2 = lnX - m.lnX1 - loFirstSlice.LEFT
						m.lnY2 = - (lnY - m.lnY1 - loFirstSlice.TOP)
					ENDIF
		
		* Угол в градусах [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
		
		
					LOCAL lnFoundShape
					m.lnFoundShape = 0
		
		* Now we need to find the shape
					FOR lnLine = loFirstSlice.CoordNum TO lnCoords
						loFoundShape = EVALUATE('.Shapes.Shape' + ALLTRIM(STR(lnLine)))
						m.lnStart  = EVL(loFoundShape.START, 0)
						IF loFoundShape.TYPE # 'Pie' OR VARTYPE(m.lnStart) <> "N"
							LOOP
						ENDIF
		
						m.lnSweep  = EVL(loFoundShape.Sweep, 0)
						IF BETWEEN(m.lnAngle, m.lnStart, m.lnStart + m.lnSweep) OR ;
								BETWEEN(m.lnAngle + 360, m.lnStart, m.lnStart + m.lnSweep)
							m.lnFoundShape = lnLine
							EXIT
						ENDIF
					NEXT
		
					IF m.lnFoundShape = 0
						.OldMouseIndex = 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 = loFoundShape.WIDTH / 2
					m.lnY1 = loFoundShape.HEIGHT / 2
		
		* Coordinates inside the Shape
					m.lnX2 = lnX - m.lnX1 - loFoundShape.LEFT
					m.lnY2 = -(lnY - m.lnY1 - loFoundShape.TOP)
		
		* 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 ._nMouseOnShape <> 0
							._nMouseOnShape = 0
							.ShapeMouseLeave(nButton, nShift, nXCoord, nYCoord, loShape)
						ENDIF
						.OldMouseIndex = 0
						RETURN
					ENDIF
		*** NEW ANGLE
		
		
					LOCAL lnRatio
					m.lnRatio = m.lnY3^2 + m.lnX3^2
		
					IF m.lnRatio > 1	OR ;
							.ChartType = 2 AND m.lnRatio < .DonutRatio / 2  && Doughnut
		
						IF ._nMouseOnShape <> 0
							._nMouseOnShape = 0
		
							.ShapeMouseLeave(nButton, nShift, nXCoord, nYCoord, loShape)
						ENDIF
		
						.OldMouseIndex = 0
						RETURN
					ENDIF
		
					m.lnValue  = loFoundShape.VALUE
					m.lnCoordIndex = loFoundShape.CoordNum
		
					m.toObject = loFoundShape
		
					IF ._nMouseOnShape = 0
						._nMouseOnShape = m.lnFoundShape
						.ShapeMouseEnter(nButton, nShift, nXCoord, nYCoord, loFoundShape)
					ELSE
						IF ._nMouseOnShape <> m.lnFoundShape
							._nMouseOnShape = m.lnFoundShape
							.ShapeMouseEnter(nButton, nShift, nXCoord, nYCoord, loFoundShape)
						ELSE
							.ShapeMouseMove(nButton, nShift, nXCoord, nYCoord, loFoundShape)
						ENDIF
					ENDIF
					RETURN
			ENDCASE
		
			IF .ShowAxis
				FOR EACH loShape IN .Shapes.OBJECTS
					IF loShape.TYPE $ "BottomSide,LeftSide,RightSide,AxisLegend2" AND loShape.CheckMousePosition(lnX,lnY)
						m.toObject = loShape
						=IIF(.ShowContour AND .OldMouseIndex # loShape.CoordNum,.DrawContour(loShape.Contour,loShape.CoordNum),.F.)
						.OldMouseIndex = loShape.CoordNum
						RETURN
					ENDIF
				NEXT
			ENDIF
			IF .OldMouseIndex # 0
				THISFORM.CLS()
				.Tips.VISIBLE=.F.
			ENDIF
			.OldMouseIndex= 0
		ENDWITH
		
	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, 6)            MESSAGE "BarType not available (0-6)"
		ASSERT BETWEEN(This.BrushType, 1, 5)          MESSAGE "BrushType not available (1-5)"
		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 lcCursor, 	;
			llOrigDetach, 	;
			lnDetachPixels, lnRecno, lnStep, 	;
			loObject, N
		IF EMPTY(tnIndex) OR (VARTYPE(tnIndex) <> "N")
			RETURN
		ENDIF
		WITH THIS
		
			loObject = EVALUATE('.Shapes.Shape'+ALLTRIM(STR(tnIndex)))
			._ChartIndex = loObject.ChartIndex
			m.lnRecno = loObject.Currentrow
			m.lcCursor = ._DataCursor
			SELECT (lcCursor)
			GO m.lnRecno
			m.llOrigDetach = lDetach
		
			m.lcCursor = (._DataCursor)
		
			REPLACE lDetach WITH NOT lDetach FOR RECNO() = m.lnRecno IN &lcCursor
		
		
			IF m.llOrigDetach
				._SkipPrepareData = .T.
				.DrawChart()
			ELSE
		
				._PieAnimatedRec  = m.lnRecno
		
				m.lnDetachPixels = .PieDetachPixels
				m.lnStep = m.lnDetachPixels / MAX(1,.PieDetachAnimationSteps)
		
				FOR m.n = m.lnStep TO m.lnDetachPixels STEP m.lnStep
					._PieAnimationPix = m.n
					._SkipPrepareData = .T.
					.DrawChart()
				ENDFOR
			ENDIF
		
			._PieAnimatedRec  = 0
			._PieAnimationPix = 0
			._SkipPrepareData = .F.
		ENDWITH
		
	ENDPROC

	PROCEDURE _drawaxis
		LOCAL ln3D, lnMargin, lnYAxisHeight, x0, x1, y0, y1, lnX, lnY
		
		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
		
		
		STORE 0 TO lnYAxisHeight, lnYaxisRight
		IF THIS.ShowAxis
		* Draw the main Y Axis caption
			LOCAL lcYText
			IF NOT EMPTY(THIS.YAxis.CAPTION)
				THIS.YAxis.RESET()
				lnYAxisHeight = CEILING(THIS.YAxis._Height)
				lnYaxisRight = lnYAxisHeight + THIS.YAxis.Left
			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
			lnLeftCaptionWidth = THIS.AxisLegend2._Width
			lnMinLeft = lnLeftCaptionWidth &&/ 2
		ELSE
			STORE 0 TO lnMinLeft, lnLeftCaptionWidth
		ENDIF
		
		
		LOCAL lnEstimatedX, lnXBetween
		lnEstimatedX = THIS.WIDTH - ;
			(THIS._Rightoffset + THIS._Scalew + lnYAxisHeight + ln3D)
		lnXBetween = lnEstimatedX / THIS._nRecords
		
		
		IF lnXBetween > (lnLeftCaptionWidth / 2)
			lnMinLeft = (lnLeftCaptionWidth / 2) && - lnXBetween
		ENDIF
		lnMinLeft = lnMinLeft + THIS.YAxis.Left + IIF(EMPTY(THIS.YAxis.CAPTION),0, THIS.YAxis.Width)
		
		IF (NOT THIS.ShowAxis) OR NOT THIS._AllowAxis
			IF THIS._Orientation = 1 && Vertical
				THIS._yAxisWidth = 10 + lnMinLeft
			ELSE  && Horizontal
				THIS._yAxisWidth = MAX(lnMinLeft, 0 + THIS._Scalew)
			ENDIF
			THIS._XAxisHeight = THIS._XAxisHeight - THIS.XAxis._Height
			RETURN
		ENDIF
		
		
		LOCAL lnTickWidth, loGfx
		m.lnTickWidth = 4
		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, loAxisBorderColor AS xfcColor, loPen AS xfcPen, loBrush AS xfcSolidBrush
		
		
			loAxisMainColor = .COLOR.FromARGB(THIS.AxisAlpha, m.lnAxisColor)
			loAxisBorderColor = .COLOR.FromARGB(THIS.AxisAlpha, m.lnAxisBorderColor)
			m.loPen = .PEN.New(loAxisBorderColor, 1)
			m.loBrush = .SolidBrush.New(loAxisMainColor)
		
		ENDWITH
		
		****************
		* Рисуем ось Y
		
		THIS._DrawYAxis(ln3D, lnMinLeft, lnYAxisHeight, loBrush, 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
		
		
		* Рисуем ось X
			m.lnMargin = THIS._yAxisWidth + THIS._LeftOffset
		
			LOCAL x0, x1, y0
		
			x0 = m.lnMargin
			x1 = THIS.ChartCanvas.WIDTH - THIS._Rightoffset
			y0 = ROUND(THIS.ChartCanvas.HEIGHT - THIS._XAxisHeight + 1,0)
		
			IF THIS.ShowAxis
		
				IF m.ln3D = 0
					m.loGfx.DrawLine(m.loPen, x0, y0, x1, y0)
				ELSE
					LOCAL laPoints(4)
					laPoints(1) = .POINT.New(x0, y0)
					laPoints(2) = .POINT.New(x0 + m.ln3D, y0 - m.ln3D)
					laPoints(3) = .POINT.New(x1, y0 - m.ln3D)
					laPoints(4) = .POINT.New(x1 - m.ln3D,  y0)
					TEXT to lcPoints
		<<ROUND(x0,0)>>,<<ROUND(y0,0)>>
		<<ROUND(x0 + m.ln3D,0)>>,<<ROUND(y0 - m.ln3D,0)>>
		<<ROUND(x1,0)>>,<<ROUND(y0 - m.ln3D,0)>>
		<<ROUND(x1-m.ln3D,0)>>,<<ROUND(y0,0)>>
		<<ROUND(x0,0)>>,<<ROUND(y0,0)>>
					ENDTEXT
					THIS._updatecoordinates (,'BottomSide', x0, y0, m.ln3D, m.ln3D, '', 0, lcPoints, 0)
		
					m.loGfx.FillPolygon(m.loBrush, @laPoints)
					LOCAL laPointsB(6)
					laPointsB(1) = laPoints(1)
					laPointsB(2) = laPoints(4)
		
					laPointsB(3) = laPoints(3)
					laPointsB(4) = .POINT.New(laPoints(3).x, y0 - m.ln3D + 3)
		
					laPointsB(5) = .POINT.New(laPoints(4).x, y0 + 3)
					laPointsB(6) = .POINT.New(laPoints(1).x, y0 + 3)
		
					m.loGfx.FillPolygon(m.loBrush, @laPointsB)
		
					m.loGfx.DrawLine(m.loPen, x0, y0, x0 + m.ln3D, y0 - m.ln3D)
				ENDIF
			ENDIF
		
		* Draw the main X Axis caption
			IF NOT EMPTY(THIS.XAxis.CAPTION)
				THIS.XAxis.RESET()
				LOCAL lnW, lnH
				m.lnX = m.lnMargin
				m.lnY = y0 + THIS._LegendPixHeight + 4
				m.lnW = x1 - x0
				m.lnH = THIS.XAxis._Height
				THIS.XAxis._DrawString(m.lnX, m.lnY, m.lnW, m.lnH)
		
				DO CASE
					CASE THIS.XAxis.ALIGNMENT = 0
						lnLeft = INT(lnX)
					CASE THIS.XAxis.ALIGNMENT = 1
						lnLeft = INT(lnX + m.lnW - THIS.XAxis._Width)
					OTHER
						lnLeft= INT(lnX + ( m.lnW-THIS.XAxis._Width )/2)
				ENDCASE
				lnTop = INT(lnY)
		
				lnRight = INT(lnLeft + THIS.XAxis._Width)
				lnBottom = INT(lnTop + THIS.XAxis._Height)
				TEXT TO lcPoints
		<<ROUND(lnLeft,0)>>,<<ROUND(lnTop,0)>>
		<<ROUND(lnRight,0)>>,<<ROUND(lnTop,0)>>
		<<ROUND(lnRight,0)>>,<<ROUND(lnbottom,0)>>
		<<ROUND(lnLeft,0)>>,<<ROUND(lnbottom,0)>>
		<<ROUND(lnLeft,0)>>,<<ROUND(lnTop,0)>>
				ENDTEXT
				THIS._updatecoordinates(,"XaxisCaption", lnLeft, lnTop, THIS.XAxis._Width, THIS.XAxis._Height, 0, THIS.XAxis.CAPTION, lcPoints)
			ENDIF
			IF THIS.ShowScale
				THIS._DrawScale(m.loPen)
			ENDIF
		
			IF THIS.ChartType = 18 && DoubleAxis
				IF THIS.ShowScale
					THIS._DrawScale(m.loPen, 2)
				ENDIF
			ENDIF
		
		ENDWITH
		
	ENDPROC

	PROCEDURE _drawbar
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tnMaxBarHeight, tn3D, tnMaxRowBarHeight, tnBarType
		* Yudin Alex 27 May 2013
		LOCAL lcFront, lcPoints, llFrustum, lnBarType, ln3D, loShape, loTopBrush
		
		m.tnHeight = ABS(m.tnHeight)
		m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1)
		m.lnBarType = EVL(m.tnBarType,THIS.BarType)
		DO CASE
			CASE m.lnBarType = 1 && Cylinder
				THIS._DrawCylinder(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
				RETURN
		
			CASE m.lnBarType = 2 && Triangle
				THIS._DrawTriangleBar(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue)
				RETURN
			CASE INLIST(m.lnBarType , 3, 5) && Cone or Conoid
				m.llFrustum = NOT EMPTY(m.tnMaxBarHeight) AND IIF(THIS._Orientation = 1,m.tnHeight,m.tnWidth)+1 < INT(m.tnMaxBarHeight)
				IF m.llFrustum
					RETURN THIS._DrawConoid(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, @m.tn3D, m.tnMaxBarHeight )
				ELSE
					RETURN THIS._DrawCone(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, @m.tn3D )
				ENDIF
			CASE INLIST(m.lnBarType , 4, 6) && Pyramid or Frustum
				m.llFrustum = NOT EMPTY(m.tnMaxBarHeight) AND IIF(THIS._Orientation = 1,m.tnHeight,m.tnWidth)+1 < INT(m.tnMaxBarHeight)
				IF m.llFrustum
					RETURN THIS._DrawFrustum(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, @m.tn3D, m.tnMaxBarHeight)
				ELSE
					RETURN THIS._DrawPyramid(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, @m.tn3D)
				ENDIF
		ENDCASE
		
		THIS._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(THIS.SingleData, RECNO(),THIS._ChartIndex))
		
		LOCAL loPen AS xfcPen, loGfx AS xfcGraphics, loMainBrush AS xfcBrush, lo3dBrush AS xfcBrush
		m.loPen  	= THIS._oBorderPen
		m.loGfx 	= THIS.oGfx
		m.lo3dBrush	= THIS._o3DBrush
		m.loMainBrush = THIS._oMainBrush
		
		WITH _SCREEN.SYSTEM.Drawing
		
		* Draw the 3D Bar using the 3DBrush
			IF m.ln3D > 0 && 3D
		
				IF NOT THIS.SHADOW
		* Prepare Array of points to draw the 3D part of the Bar
					LOCAL laPoints(4)
					m.tnY = m.tnY
					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)
		
					LOCAL loPath AS xfcGraphicsPath
					m.loPath = .Drawing2D.GraphicsPath.New()
					m.loPath.FillMode = .Drawing2D.FillMode.ALTERNATE
		
					m.loPath.StartFigure()
					m.loPath.ADDLINE(m.tnX + m.tnWidth, m.tnY, m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D)
					m.loPath.ADDLINE(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D, m.tnX + m.ln3D, m.tnY - m.ln3D)
					m.loPath.ADDLINE(m.tnX + m.ln3D, m.tnY - m.ln3D, m.tnX, m.tnY)
					m.loPath.ADDLINE(m.tnX, m.tnY, m.tnX + m.tnWidth, m.tnY)
					m.loTopBrush = _SCREEN.FoxChartsHelper.PathGradient( , m.loPath, THIS._nColor,-1, m.tnX+m.tnWidth/2+m.ln3D/2, m.tnY+m.ln3D/2)
		
		
					m.loGfx.FillPolygon(m.loTopBrush, @laPoints)
					IF VARTYPE(THIS._oDimBrush)='O'
						m.loGfx.FillPolygon(THIS._oDimBrush, @laPoints)
					ENDIF
					m.loGfx.DrawPolygon(m.loPen, @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(THIS._oRightbrush , @laPoints)
					IF VARTYPE(THIS._oDimBrush)='O'
						m.loGfx.FillPolygon(THIS._oDimBrush , @laPoints)
					ENDIF
		
					m.loGfx.DrawPolygon(m.loPen, @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)
					IF VARTYPE(THIS._oDimBrush)='O'
						m.loGfx.FillRectangle(THIS._oDimBrush , m.tnX + m.ln3D, m.tnY + m.ln3D, m.tnWidth, m.tnHeight - m.ln3D - m.ln3D)
					ENDIF
					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 , @laPoints)
		
				ENDIF
		
			ENDIF
		
			m.loGfx.FillRectangle(m.loMainBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight)
			IF VARTYPE(THIS._oDimBrush)='O'
				m.loGfx.FillRectangle(THIS._oDimBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight)
			ENDIF
		
			m.loGfx.DrawRectangle(m.loPen, m.tnX, m.tnY, m.tnWidth, m.tnHeight)
			TEXT TO m.lcPoints
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>,<<ROUND(m.tnX + m.tnWidth,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>,<<ROUND(m.tnX + m.tnWidth + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D + m.tnHeight,0)>>,<<ROUND(m.tnX + m.tnWidth + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D,0)>>
		<<ROUND(m.tnX + m.tnWidth + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D,0)>>,<<ROUND(m.tnX + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D,0)>>
		<<ROUND(m.tnX + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D,0)>>,<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY,0)>>,<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
			ENDTEXT
			TEXT TO m.lcFront
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth,0)>>,<<ROUND(m.tnY,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY,0)>>
			ENDTEXT
		
			m.loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,m.lcPoints,,m.lcFront)
			IF THIS._GeneralType = "Bar"
				THIS._DrawLegendinBar(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,m.loShape)
			ENDIF
		
		ENDWITH
		
	ENDPROC

	PROCEDURE _drawbarchart
		* Yudin Alex 2 June 2013
			LOCAL lnBarType, lnBottomValue
		LOCAL lcAlias, lcLastPoint, 	;
			lnBottomHeight, lnBottomWidth, lnColumn, lnCount, lnHorDelta, lnLine, lnLines, lnMaxBarHeight, lnMaxBarWidth, lnMaxRowHeight, lnMaxRowWidth, lnNativeValue, ;
			lnNewHorDelta, lnNewVertDelta, lnOldCone3D, lnStack, lnSumBarHeight, lnSumBarWidth, lnTotalMaxBarHeight, lnTotalMaxBarWidth, lnX1, lnY1, lnYDelta
		LOCAL lnWidth, lnHeight, x1, y1, N, lnValue, lnLeftMargin, ln3D, lnTopMargin
		LOCAL lnPointHeight AS NUMBER, lnYBase AS NUMBER
		WITH THIS
			SELECT(._DataCursor)
		
			m.ln3D     = ._3D
			m.lnWidth  = .ChartCanvas.WIDTH - ._LeftOffset - ._RightOffset - m.ln3D - ._yAxisWidth
			m.lnHeight = .ChartCanvas.HEIGHT - ._XAxisHeight - ._TopOffSet - m.ln3D
		
			IF (m.lnWidth <= 0) OR (m.lnHeight <= 0)
				RETURN
			ENDIF
		
			m.lnLeftMargin = ._yAxisWidth + ._LeftOffset
			m.lnTopMargin  = ._TopOffSet + m.ln3D
		
			LOCAL lnBarWidth, lnBarHeight, lnBetween, lnMaxValue, lnAdjust, lnChartsCount
			m.lnBetween = .BarsSpaceBetween
			m.lnMaxValue = ._ScaleRange
			m.lnChartsCount = .ChartsCount
		
		* Prepare Points
			IF ._Orientation = 1 && Vertical
		
				IF ._DeepChart
					m.lnWidth  = m.lnWidth  - (m.ln3D * (m.lnChartsCount - 1))
				ENDIF
		
				m.lnBetween = MIN(m.lnBetween, ;
					(m.lnWidth - ._nRecords) / ._nRecords)
		
				m.lnBarWidth = (m.lnWidth - (._nRecords - 1) * m.lnBetween) / ._nRecords
		
				SCAN
					m.n = RECNO()
					m.x1 = m.lnLeftMargin + ((m.lnBarWidth + m.lnBetween) * (m.n - 1))
					._aPoints(m.n,1) = m.x1 + (m.lnBarWidth / 2)
				ENDSCAN
		
			ELSE && Horizontal
		
				m.lnBetween = MIN(m.lnBetween, ;
					(m.lnHeight - ._nRecords) / ._nRecords)
		
				m.lnBarHeight = (m.lnHeight - (._nRecords - 1) * m.lnBetween) / ._nRecords
				SCAN
					m.n = RECNO()
					m.y1 = m.lnTopMargin + ((m.lnBarHeight + m.lnBetween) * (m.n - 1))
					._aPoints(m.n,2) = m.y1 + (m.lnBarHeight / 2)
				ENDSCAN
				._DrawYAxisLegend()
			ENDIF
		
		
			._DrawVerticalLineBack()
			m.lnMaxBarHeight=0
		
		
			DO CASE
				CASE .ChartType = 7 && Simple Bar
					SELECT (._DataCursor)
					LOCAL laStack(RECCOUNT(),7)
					m.lnScaleAdjustment = ._ScaleAdjust / m.lnMaxValue * m.lnHeight
		
					m.lnZeroY = ._TopOffSet + m.ln3D + (._MaxScale / m.lnMaxValue * m.lnHeight)
					IF ._MinScale > 0
						m.lnZeroY = m.lnZeroY - (._MinScale / m.lnMaxValue * m.lnHeight)
					ENDIF
		
					._ChartIndex = .ChartRow
					m.lcLastPoint=''
					SCAN
						m.lnLine = RECNO()
						m.lnValue = ._GetValue(.ChartRow, .T.)
						IF ISNULL(m.lnValue) OR m.lnValue < ._MinScale
							LOOP
						ENDIF
		
						IF m.lnValue < 0
							m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight)
							m.lnY1 = m.lnZeroY
						ELSE
							m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight) + ;
								IIF(._ScaleAdjust < 0, m.lnScaleAdjustment, 0)
							m.lnY1 = m.lnZeroY - m.lnBarHeight
						ENDIF
		
						m.lnX1 = m.lnLeftMargin + ((m.lnBarWidth + m.lnBetween) * (RECNO() - 1))
						m.lnMaxBarHeight=MAX(m.lnMaxBarHeight,m.lnBarHeight)
						laStack(m.lnLine,1)=m.lnX1
						laStack(m.lnLine,2)=m.lnY1
						laStack(m.lnLine,3)=m.lnBarWidth
						laStack(m.lnLine,4)=m.lnBarHeight
						laStack(m.lnLine,5)=m.lnValue
						laStack(m.lnLine,6)= RECNO()
						laStack(m.lnLine,7) = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype)
					ENDSCAN
					FOR m.lnLine=1 TO RECCOUNT()
						GO laStack(m.lnLine,6)
						._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(.BarType,3,4),0,m.lnMaxBarHeight),,,laStack(m.lnLine,7))
					NEXT
		
				CASE .ChartType = 8 && Multi Bars
					LOCAL lnChart, lnOneBarWidth, lnZeroY, lnScaleAdjustment, lnTotRow, laValues(m.lnChartsCount), laBottom(m.lnChartsCount)
		
					m.lnOneBarWidth = m.lnBarWidth / m.lnChartsCount
					m.lnZeroY = ._TopOffSet + m.ln3D + (._MaxScale / m.lnMaxValue * m.lnHeight)
					IF ._MinScale > 0
						m.lnZeroY = m.lnZeroY - (._MinScale / m.lnMaxValue * m.lnHeight)
					ENDIF
					m.lnScaleAdjustment = ._ScaleAdjust / m.lnMaxValue * m.lnHeight
					m.lcAlias=ALIAS()
					LOCAL laLastPoint(MAX(1,m.lnChartsCount))
					m.laLastPoint=''
					STORE 0 TO m.lnValue,m.lnBottomValue, m.lnCount
					m.lnLines =RECCOUNT()
		
					SCAN
						m.lnLine = RECNO()
						m.lnTotRow = 0
		* Get the total for the current row
						FOR m.lnColumn = 1 TO m.lnChartsCount
							m.lnValue = ._GetValue(m.lnColumn, .T.)
							laValues(m.lnColumn) = m.lnValue
							m.lnTotRow = m.lnTotRow + NVL(m.lnValue, 0)
						NEXT
						FOR m.lnColumn = 1 TO m.lnChartsCount
							m.lnValue = laValues(m.lnColumn)
							IF ISNULL(m.lnValue) OR m.lnValue < ._MinScale
								LOOP
							ENDIF
							._ChartIndex = m.lnColumn
		
							m.lnX1 = m.lnLeftMargin + ;
								((m.lnBarWidth + m.lnBetween) * (m.lnLine - 1)) + ;
								((m.lnColumn-1 ) * m.lnOneBarWidth)
		
		
							IF m.lnValue < 0
								m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight)
								m.lnY1 = m.lnZeroY
							ELSE
								m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight) + IIF(._ScaleAdjust < 0, m.lnScaleAdjustment, 0)
								m.BottomHeight=(m.lnBottomValue / m.lnMaxValue * m.lnHeight)
								m.lnY1 = m.lnZeroY - m.lnBarHeight - m.BottomHeight
							ENDIF
							.ChartSum = m.lnTotRow
							m.lnMaxBarHeight=MAX(m.lnMaxBarHeight,m.lnBarHeight)
							m.lnCount = m.lnCount+1
							LOCAL laStack(lnCount,8)
							laStack(m.lnCount,1) = m.lnX1
							laStack(m.lnCount,2) = m.lnY1
							laStack(m.lnCount,3) = m.lnOneBarWidth
							laStack(m.lnCount,4) = m.lnBarHeight
							laStack(m.lnCount,5) = m.lnValue
							laStack(m.lnCount,6) = m.lnLine
							laStack(m.lnCount,7) = m.lnColumn
							laStack(m.lnCount,8) = IIF(.Fields(m.lnColumn).Bartype<0, .Bartype, .Fields(m.lnColumn).Bartype)
						NEXT
		
					ENDSCAN
					m.lcLastPoint=''
					FOR m.lnLine=1 TO m.lnCount
						GO laStack(m.lnLine,6)
						._ChartIndex =	laStack(m.lnLine,7)
						lnBartype = laStack(m.lnLine,8)
						._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(.BarType,3,4),0,m.lnMaxBarHeight),,,lnBartype)
					NEXT
					._ChartIndex = 1
		
		
				CASE .ChartType = 9 && Stacked Bars
					m.lnZeroY = ._TopOffSet + m.ln3D + (._MaxScale / m.lnMaxValue * m.lnHeight)
					m.lnYBase = IIF(._HasNegatives, m.lnZeroY, ._TopOffSet + m.ln3D + m.lnHeight)
					m.lnTotalMaxBarHeight = 0
					LOCAL laMaxConeHeight(MAX(1,RECCOUNT()))
					m.laMaxConeHeight = 0
					STORE 0 TO m.lnValue,m.lnBottomValue
					FOR .ROW = 1 TO RECCOUNT()
						STORE m.lnYBase TO m.lnY1, m.yMinus1
						STORE 0 TO m.lnStack, m.lnSumBarHeight
						FOR .COLUMN = 1 TO .ChartsCount
							._ChartIndex = .COLUMN
							m.lnBarType = IIF(.Fields(.Column).Bartype<0, .Bartype, .Fields(.Column).Bartype)
							.GetValue()
		
							m.lnNativeValue = .VALUE
							m.lnValue = ABS(NVL(m.lnNativeValue,0))
		
							m.lnBarHeight = m.lnValue / m.lnMaxValue * m.lnHeight
							IF m.lnBarType # 7
								m.laMaxConeHeight(.ROW) = m.laMaxConeHeight(.ROW) + m.lnBarHeight
								m.lnSumBarHeight = m.lnSumBarHeight + m.lnBarHeight
							ENDIF
							IF m.lnNativeValue	>=0
								LOOP
							ENDIF
		
							m.lnX1 = m.lnLeftMargin + ;
								((m.lnBarWidth + m.lnBetween) * (.ROW - 1))
							m.lnMaxBarHeight=MAX(m.lnMaxBarHeight,m.lnBarHeight)
							m.lnStack = m.lnStack +1
							LOCAL laStack(m.lnStack,8)
							laStack(m.lnStack,1) = m.lnX1
							laStack(m.lnStack,2) = m.yMinus1
							laStack(m.lnStack,3) = m.lnBarWidth
							laStack(m.lnStack,4) = m.lnBarHeight
							laStack(m.lnStack,5) = m.lnNativeValue
							laStack(m.lnStack,6) = ._ChartIndex
							laStack(m.lnStack,7) = m.lnSumBarHeight
							laStack(m.lnStack,8) = m.lnBarType
							m.yMinus1 = m.yMinus1 + m.lnBarHeight
		
						NEXT
						m.lnTotalMaxBarHeight = MAX(m.lnTotalMaxBarHeight, m.lnSumBarHeight)
						FOR m.lnLine=m.lnStack TO 1 STEP -1
							._ChartIndex = laStack(m.lnLine,6)
							._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5),m.lnMaxBarHeight,,,laStack(m.lnLine,8))
						NEXT
		
					NEXT
					LOCAL laLastPoint(MAX(1,m.lnChartsCount))
					m.laLastPoint=''
					FOR .ROW = 1 TO RECCOUNT()
						m.lnY1 = m.lnYBase
						m.lnBottomHeight=0
						m.lnHorDelta = 0
						m.ln3dDelta = 0
						m.lnCone3d = ._3D
						m.lnMaxRowHeight = m.laMaxConeHeight(.ROW)
						FOR .COLUMN = 1 TO .ChartsCount
							._ChartIndex = .COLUMN
							.GetValue()
		
							m.lnNativeValue = .VALUE
							IF m.lnNativeValue	<=0
								LOOP
							ENDIF
							m.lnBarType = IIF(.Fields(.Column).Bartype<0, .Bartype, .Fields(.Column).Bartype)
							m.lnValue = ABS(NVL(m.lnNativeValue,0))
							m.lnBarHeight = m.lnValue / m.lnMaxValue * m.lnHeight
		
							m.lnX1 = m.lnLeftMargin + ((m.lnBarWidth + m.lnBetween) * (.ROW - 1))
		
							m.lnOldCone3D = m.lnCone3d
							DO CASE
								CASE INLIST(m.lnBarType,3,4)
									m.lnY1 = m.lnY1 - m.lnBarHeight
									m.lnNewHorDelta = ._DrawBar(m.lnX1 + m.lnHorDelta + m.ln3dDelta, m.lnY1 - m.ln3dDelta, ;
										m.lnBarWidth-m.lnHorDelta-m.lnHorDelta, m.lnBarHeight, ;
										m.lnValue, m.lnMaxRowHeight-m.lnBottomHeight, @m.lnCone3d,,m.lnBartype)
								OTHER
									m.lnY1 = m.lnY1 - m.lnBarHeight
									m.lnNewHorDelta = ._DrawBar(m.lnX1 + m.lnHorDelta + m.ln3dDelta, m.lnY1 - m.ln3dDelta, ;
										m.lnBarWidth-m.lnHorDelta-m.lnHorDelta, m.lnBarHeight, ;
										m.lnValue, m.lnTotalMaxBarHeight-m.lnBottomHeight, @m.lnCone3d, m.laMaxConeHeight(.ROW)-m.lnBottomHeight, m.lnBartype)
							ENDCASE
							m.lnHorDelta = m.lnHorDelta + IIF(VARTYPE(m.lnNewHorDelta) ='N',m.lnNewHorDelta,0)
							m.lnBottomHeight = m.lnBottomHeight + IIF(m.lnBarType = 7, 0, m.lnBarHeight)
							m.ln3dDelta = m.ln3dDelta + (m.lnOldCone3D - m.lnCone3d) / 2
						NEXT
					NEXT
					._ChartIndex = 1
		
				CASE .ChartType = 11 && 3D Bars
		* Calculate the maximum width of the chart
					m.lnHeight = m.lnHeight - (m.ln3D * (m.lnChartsCount - 1))
					m.lnStack = 0
					FOR ._ChartIndex = 1 TO m.lnChartsCount
						m.lnAdjust = m.ln3D * (m.lnChartsCount - ._ChartIndex )
		
						SCAN
							m.lnValue = ._GetValue(._ChartIndex, .T.)
							m.lnX1 = m.lnLeftMargin + m.lnAdjust + ((m.lnBarWidth + m.lnBetween) * (RECNO() - 1))
							IF ._ChartIndex = m.lnChartsCount
		* Prepare Points
								._aPoints(RECNO(),1) = m.lnX1 + (m.lnBarWidth / 2)
							ENDIF
							IF ISNULL(m.lnValue)
								LOOP
							ENDIF
		
							m.lnPointHeight = (m.lnValue-._MinScale) / m.lnMaxValue * m.lnHeight
		
		
							m.lnY1 = ._TopOffSet + (m.lnHeight - m.lnPointHeight) - m.lnAdjust + (m.ln3D * (m.lnChartsCount))
							m.lnYBase = .ChartCanvas.HEIGHT - ._XAxisHeight - m.lnAdjust
							m.lnBarHeight = m.lnYBase - m.lnY1
							m.lnMaxBarHeight = MAX(m.lnMaxBarHeight , m.lnBarHeight)
							m.lnStack = m.lnStack + 1
							LOCAL laStack(lnStack,8)
							laStack(m.lnStack,1) = m.lnX1
							laStack(m.lnStack,2) = m.lnY1
							laStack(m.lnStack,3) = m.lnBarWidth
							laStack(m.lnStack,4) = m.lnBarHeight
							laStack(m.lnStack,5) = m.lnValue
							laStack(m.lnStack,6) = RECNO()
							laStack(m.lnStack,7) = ._ChartIndex
							laStack(m.lnStack,8) = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype)
		
						ENDSCAN
					NEXT
					LOCAL laLastPoint(RECCOUNT())
					STORE '' TO m.laLastPoint
					FOR m.lnLine=1 TO m.lnStack
						GO laStack(m.lnLine,6)
						._ChartIndex = laStack(m.lnLine,7)
						._ChartIndex = laStack(m.lnLine,7)
						._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(.BarType,3,4),0,m.lnMaxBarHeight),,,laStack(m.lnLine,8))
					NEXT
		
		
				CASE .ChartType = 12 && HORIZONTAL Simple Bar
					IF m.lnBetween >= m.lnHeight / (._nRecords - 1)
						m.lnBarHeight = 1
						m.lnBetween = (m.lnHeight - ._nRecords) / (._nRecords - 1)
					ENDIF
					LOCAL lnZeroX, lnScaleAdjustment, laLastPoint(RECCOUNT())
					m.lnZeroX = m.lnLeftMargin + IIF(._ScaleAdjust < 0 , 0, (._ScaleAdjust / m.lnMaxValue * m.lnWidth))
					m.lnScaleAdjustment = ._ScaleAdjust / m.lnMaxValue * m.lnWidth
		
					._ChartIndex = .ChartRow
		
					SET ORDER TO REVERT
					m.lnStack=0
					m.lnMaxBarWidth = 0
					SCAN
						m.lnValue = ._GetValue(.ChartRow, .T.)
						IF ISNULL(m.lnValue) OR m.lnValue < ._MinScale
							LOOP
						ENDIF
		
						IF m.lnValue < 0
							m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth)
							m.lnX1 = m.lnZeroX - m.lnBarWidth
						ELSE
							m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth) + ;
								IIF(._ScaleAdjust < 0, m.lnScaleAdjustment, 0)
							m.lnX1 = m.lnZeroX
						ENDIF
		
						m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D
						m.lnStack = m.lnStack +1
						LOCAL laStack(m.lnStack,7)
						laStack(m.lnStack,1) =m.lnX1
						laStack(m.lnStack,2) =m.lnY1
						laStack(m.lnStack,3) =m.lnBarWidth
						laStack(m.lnStack,4) =m.lnBarHeight
						laStack(m.lnStack,5) = m.lnValue
						laStack(m.lnStack,6) = RECNO()
						m.lnMaxBarWidth = MAX(m.lnMaxBarWidth,  m.lnBarWidth)
						laStack(m.lnStack,7) = IIF(.Fields(.ChartRow).Bartype<0, .Bartype, .Fields(.ChartRow).Bartype)
					ENDSCAN
					FOR m.lnLine=1 TO m.lnStack
						GO laStack(m.lnLine,6)
						lnBartype = laStack(m.lnLine,7)
						._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(lnBarType,3,4),0,m.lnMaxBarWidth),,,lnBarType)
					NEXT
		
					SET ORDER TO
		
				CASE .ChartType = 13 && HORIZONTAL Multi Bars
					IF m.lnBetween >= m.lnHeight / (._nRecords - 1)
						m.lnBarHeight = 1
						m.lnBetween = (m.lnHeight - ._nRecords) / (._nRecords - 1)
					ENDIF
					m.lnMaxBarWidth = 0
					m.lnBarHeight = (m.lnHeight - (._nRecords - 1) * m.lnBetween) / ._nRecords
					LOCAL i, lnOneBarHeight
					m.lnOneBarHeight = m.lnBarHeight / m.lnChartsCount
		
					LOCAL lnZeroX, lnScaleAdjustment, lnTotRow, laValues(m.lnChartsCount)
					m.lnZeroX = m.lnLeftMargin + IIF(._ScaleAdjust < 0 , 0, (._ScaleAdjust / m.lnMaxValue * m.lnWidth))
					m.lnScaleAdjustment = ._ScaleAdjust / m.lnMaxValue * m.lnWidth
					LOCAL laLastPoint( RECCOUNT())
					m.lnStack = 0
					SET ORDER TO REVERT
					SCAN
						m.lnTotRow = 0
		* Get the total for the current row
						FOR ._ChartIndex = .ChartsCount TO 1 STEP -1
							m.lnValue = ._GetValue(._ChartIndex, .T.)
							laValues(._ChartIndex) = m.lnValue
							m.lnTotRow = m.lnTotRow + NVL(m.lnValue, 0)
						NEXT
		
						FOR ._ChartIndex = .ChartsCount TO 1 STEP -1
							m.lnValue = laValues(._ChartIndex)
							IF ISNULL(m.lnValue) OR m.lnValue < ._MinScale
								LOOP
							ENDIF
		
							IF m.lnValue < 0
								m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth)
								m.lnX1 = m.lnZeroX - m.lnBarWidth
							ELSE
								m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth) + ;
									IIF(._ScaleAdjust < 0, m.lnScaleAdjustment, 0)
								m.lnX1 = m.lnZeroX
							ENDIF
		
							m.lnY1 = ._TopOffSet + m.ln3D + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + ;
								((._ChartIndex-1 ) * m.lnOneBarHeight)
							.ChartSum = m.lnTotRow
							m.lnStack = m.lnStack +1
							LOCAL laStack(m.lnStack,8)
							laStack(m.lnStack,1) = m.lnX1
							laStack(m.lnStack,2) = m.lnY1 + m.lnOneBarHeight/2
							laStack(m.lnStack,3) = m.lnBarWidth
							laStack(m.lnStack,4) = m.lnOneBarHeight
							laStack(m.lnStack,5) = m.lnValue
							laStack(m.lnStack,6) = RECNO()
							laStack(m.lnStack,7) = ._ChartIndex
							laStack(m.lnStack,8) = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype)
							m.lnMaxBarWidth = MAX(m.lnMaxBarWidth,  m.lnBarWidth)
		
						NEXT
					ENDSCAN
					FOR m.lnLine=1 TO m.lnStack
						GO laStack(m.lnLine,6)
						._ChartIndex = laStack(m.lnLine,7)
						._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(.BarType,3,4),0,m.lnMaxBarWidth),,,laStack(m.lnLine,8))
					NEXT
					SET ORDER TO
		
					._ChartIndex = 1
		
				CASE .ChartType = 14 && HORIZONTAL Stacked Bars
					IF m.lnBetween >= m.lnHeight / (._nRecords - 1)
						m.lnBarHeight = 1
						m.lnBetween = (m.lnHeight - ._nRecordss) / (._nRecords - 1)
					ENDIF
		
					SET ORDER TO REVERT
		
					m.lnTotalMaxBarWidth = 0
					LOCAL laMaxConeWidth(MAX(1,RECCOUNT()))
					m.laMaxConeWidth = 0
					SCAN
						m.lnX1 = m.lnLeftMargin
						m.lnStack=0
						m.lnSumBarWidth = 0
						FOR ._ChartIndex = 1 TO m.lnChartsCount
							m.lnValue = ._GetValue(._ChartIndex, .T.)
							IF ISNULL(m.lnValue) OR EMPTY(m.lnValue)
								LOOP
							ENDIF
							m.lnBarWidth = ROUND( m.lnValue / m.lnMaxValue * m.lnWidth, 0)
							m.laMaxConeWidth(RECNO()) = m.laMaxConeWidth(RECNO()) + m.lnBarWidth
							m.lnSumBarWidth = m.lnSumBarWidth + m.lnBarWidth
		
						NEXT
						m.lnTotalMaxBarWidth = MAX(m.lnTotalMaxBarWidth, m.lnSumBarWidth)
		
					ENDSCAN
					LOCAL lnVertDelta, lnCone3d, ln3dDelta, laLastPoint(RECCOUNT())
					SCAN
						m.lnYDelta = 0
						m.lnX1 = m.lnLeftMargin
						STORE 0 TO m.lnVertDelta, m.ln3dDelta, m.lnBottomWidth
						m.lnCone3d = ._3D
						m.lnMaxRowWidth = m.laMaxConeWidth(RECNO())
						m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D
						FOR ._ChartIndex = .ChartsCount TO 1 STEP -1
							m.lnValue = ._GetValue(._ChartIndex, .T.)
							IF ISNULL(m.lnValue) OR EMPTY(m.lnValue)
								LOOP
							ENDIF
							m.lnValue = ABS(NVL(m.lnValue,0))
							m.lnBarWidth = ROUND(m.lnValue / m.lnMaxValue * m.lnWidth,0)
							lnBarType = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype)
		
							m.lnOldCone3D = m.lnCone3d
							IF INLIST(.BarType,3,4)
								m.lnNewVertDelta = ._DrawBar(m.lnX1 + m.ln3dDelta, m.lnY1 + m.lnVertDelta- m.ln3dDelta, ;
									m.lnBarWidth, m.lnBarHeight-m.lnVertDelta*2, ;
									m.lnValue, m.lnMaxRowWidth-m.lnBottomWidth, @m.lnCone3d,,m.lnBarType)
								m.lnX1 = m.lnX1 + m.lnBarWidth
		
							ELSE
								m.lnNewVertDelta = ._DrawBar(m.lnX1 + m.ln3dDelta, m.lnY1  + m.lnVertDelta- m.ln3dDelta  , ;
									m.lnBarWidth, m.lnBarHeight-m.lnVertDelta*2, ;
									m.lnValue, m.lnTotalMaxBarWidth-m.lnBottomWidth, @m.lnCone3d, m.laMaxConeWidth(RECNO()),m.lnBarType)
								m.lnX1 = m.lnX1 + m.lnBarWidth
		
							ENDIF
							m.lnVertDelta = m.lnVertDelta + IIF(VARTYPE(m.lnNewVertDelta) ='N',m.lnNewVertDelta,0)
							m.lnBottomWidth=m.lnBottomWidth+m.lnBarWidth
							m.ln3dDelta = m.ln3dDelta + (m.lnOldCone3D - m.lnCone3d) / 2
						NEXT
		
					ENDSCAN
		
					SET ORDER TO
					._ChartIndex = 1
		
				CASE .ChartType = 15 && HORIZONTAL Full-Stacked Bars
					IF m.lnBetween >= m.lnHeight / (._nRecords - 1)
						m.lnBarHeight = 1
						m.lnBetween = (m.lnHeight - ._nRecords) / (._nRecords - 1)
					ENDIF
		
					SET ORDER TO REVERT
					LOCAL lnTotRow, laValues(m.lnChartsCount)
		
					STORE 0 TO m.lnTotalMaxBarWidth, m.lnStack
					SCAN
						m.lnBottomWidth=0
						m.lnVertDelta = 0
						m.ln3dDelta = 0
						m.lnCone3d = ._3D
						m.lnTotRow = 0
		* Get the total for the current row
						FOR ._ChartIndex = .ChartsCount TO 1 STEP -1
							m.lnValue = ._GetValue(._ChartIndex, .T.)
							laValues(._ChartIndex) = m.lnValue
							m.lnTotRow = m.lnTotRow + m.lnValue
						NEXT
		
						m.lnSumBarWidth = 0
						m.lnX1 = m.lnLeftMargin
						m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D
						FOR ._ChartIndex = .ChartsCount TO 1 STEP -1
							m.lnValue = laValues(._ChartIndex)
							IF EMPTY(m.lnValue)
								LOOP
							ENDIF
							m.lnBarWidth = m.lnValue / m.lnTotRow * m.lnWidth
							m.lnSumBarWidth = m.lnSumBarWidth + m.lnBarWidth
		
							.ChartSum = m.lnTotRow
							m.lnStack = m.lnStack +1
							LOCAL laStack(m.lnStack,8)
							laStack(m.lnStack,1) = m.lnX1
							laStack(m.lnStack,2) = m.lnY1
							laStack(m.lnStack,3) = m.lnBarWidth
							laStack(m.lnStack,4) = m.lnBarHeight
							laStack(m.lnStack,5) = m.lnValue
							laStack(m.lnStack,6) = ._ChartIndex
							laStack(m.lnStack,7) = m.lnSumBarWidth
							m.lnOldCone3D = m.lnCone3d
							m.lnBarType = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype)
							laStack(m.lnStack,8) = m.lnBarType
		
							IF INLIST(.BarType,3,5)
								m.lnNewVertDelta = ._DrawBar(m.lnX1 + m.ln3dDelta, m.lnY1 + m.lnVertDelta - m.ln3dDelta, ;
									m.lnBarWidth, m.lnBarHeight-m.lnVertDelta*2, ;
									m.lnValue, m.lnWidth-m.lnBottomWidth, @m.lnCone3d,,m.lnBarType)
							ELSE
								m.lnNewVertDelta = ._DrawBar(m.lnX1 + m.ln3dDelta, m.lnY1  + m.lnVertDelta- m.ln3dDelta, ;
									m.lnBarWidth, m.lnBarHeight-m.lnVertDelta-m.lnVertDelta, ;
									m.lnValue, m.lnWidth-m.lnBottomWidth, @m.lnCone3d, m.lnWidth-m.lnBottomWidth,m.lnBarType)
							ENDIF
		
							m.lnX1 = m.lnX1 + m.lnBarWidth
							m.lnBottomWidth = m.lnBottomWidth + m.lnBarWidth
							m.lnVertDelta = m.lnVertDelta + IIF(VARTYPE(m.lnNewVertDelta) ='N',m.lnNewVertDelta,0)
							m.ln3dDelta = m.ln3dDelta + (m.lnOldCone3D - m.lnCone3d) / 2
						NEXT
		
					ENDSCAN
					SET ORDER TO
					._ChartIndex = 1
		
				CASE .ChartType = 3 && Full-Stacked Bars
					LOCAL lnTotRow, laValues(m.lnChartsCount)
					m.lnYBase = ._TopOffSet + m.ln3D + m.lnHeight
					FOR .ROW = 1 TO RECCOUNT()
						m.lnY1 = m.lnYBase
						m.lnTotRow = 0
		* Get the total for the current row
						FOR .COLUMN = 1 TO .ChartsCount
							._ChartIndex = .COLUMN
							.GetValue()
							._ChartIndex = .COLUMN
							laValues(.COLUMN) = .VALUE
							m.lnTotRow = m.lnTotRow + .VALUE
						NEXT
		
						m.lnStack=0
						m.lnSumBarHeight = 0
						FOR .COLUMN = 1 TO .ChartsCount
							._ChartIndex = .COLUMN
							m.lnValue = laValues(.COLUMN)
							IF m.lnValue = 0
								LOOP
							ENDIF
							m.lnBarHeight = m.lnValue / m.lnTotRow * m.lnHeight
							m.lnBarType = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype)
		
							m.lnX1 = m.lnLeftMargin + ;
								((m.lnBarWidth + m.lnBetween) * (.ROW - 1))
							m.lnY1 = m.lnY1 - m.lnBarHeight
		
							.ChartSum = m.lnTotRow
							m.lnStack = m.lnStack +1
							LOCAL laStack(m.lnStack,6)
							laStack(m.lnStack,1) = m.lnX1
							laStack(m.lnStack,2) = m.lnY1
							laStack(m.lnStack,3) = m.lnBarWidth
							laStack(m.lnStack,3) = m.lnBarHeight
							laStack(m.lnStack,4) = m.lnValue
							laStack(m.lnStack,5) = .COLUMN
							laStack(m.lnStack,6) = m.lnBarType
						NEXT
						m.lnBottomHeight=0
						m.lnHorDelta = 0
						m.ln3dDelta = 0
						m.lnCone3d = ._3D
						FOR m.lnLine=1 TO m.lnStack
		
							._ChartIndex = laStack(m.lnLine,5)
							.COLUMN = laStack(m.lnLine,5)
							m.lnX1 = laStack(m.lnLine,1)
							m.lnY1 = laStack(m.lnLine,2)
							m.lnBarHeight = laStack(m.lnLine,3)
							m.lnOldCone3D = m.lnCone3d
		
		
							m.lnNewHorDelta = ._DrawBar(m.lnX1 + m.lnHorDelta + m.ln3dDelta, m.lnY1 - m.ln3dDelta, ;
								m.lnBarWidth-m.lnHorDelta-m.lnHorDelta, m.lnBarHeight, ;
								laStack(m.lnLine,4), m.lnHeight-m.lnBottomHeight, @m.lnCone3d , m.lnHeight - m.lnBottomHeight, laStack(m.lnLine,6))
		
							m.lnHorDelta = m.lnHorDelta + IIF(VARTYPE(m.lnNewHorDelta) ='N',m.lnNewHorDelta,0)
							m.lnBottomHeight=m.lnBottomHeight+m.lnBarHeight
							m.ln3dDelta = m.ln3dDelta + (m.lnOldCone3D - m.lnCone3d) / 2
						NEXT
		
					NEXT
					._ChartIndex = 1
		
				CASE .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 = .ShapeLegend.ALIGNMENT
					DO CASE
						CASE m.lnAlign = 0 && Left
							.ShapeLegend.ALIGNMENT = 1 && Right
		
						CASE m.lnAlign = 1 && Right
							.ShapeLegend.ALIGNMENT = 0 && Left
		
						OTHERWISE
					ENDCASE
		
		
					._ChartIndex = 1
					LOCAL laMax( RECCOUNT()), llCalcMax, lnRecno
					m.lnBarType = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype)
					m.llCalcMax = INLIST(lnBarType,5,6) AND m.lnChartsCount > 1
					SCAN
						m.lnRecno = RECNO()
						IF m.llCalcMax
							m.lnValue = ._GetValue(2, .T.)
							laMax(m.lnRecno) = ABS(m.lnValue / m.lnMaxValue * m.lnWidth)
						ENDIF
						m.lnValue = ._GetValue(1, .T.)
						IF ISNULL(m.lnValue) OR (m.lnValue <= 0)
							LOOP
						ENDIF
		
						m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth)
						laMax(m.lnRecno) = ROUND(IIF(m.llCalcMax, MAX(laMax(m.lnRecno),m.lnBarWidth), 0),0)
						m.lnX1 = m.lnZeroX - m.lnBarWidth
		
						m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (m.lnRecno - 1)) + m.ln3D
						._DrawBar(m.lnX1, m.lnY1, m.lnBarWidth, m.lnBarHeight, m.lnValue, laMax(m.lnRecno),,,m.lnBarType)
					ENDSCAN
					.ShapeLegend.ALIGNMENT = m.lnAlign && Restore to the original setting
					IF m.lnChartsCount > 1
		* Draw the right side of the chart
						._ChartIndex = 2
						SCAN
							m.lnRecno = RECNO()
							m.lnValue = ._GetValue(2, .T.)
							IF ISNULL(m.lnValue) OR (m.lnValue < ._MinScale)
								LOOP
							ENDIF
		
							m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth)
							m.lnX1 = m.lnZeroX
							m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (m.lnRecno - 1)) + m.ln3D
		
							._DrawBar(m.lnX1, m.lnY1, m.lnBarWidth, m.lnBarHeight, m.lnValue, IIF(m.llCalcMax,laMax(m.lnRecno),.F.),,m.lnBarType)
						ENDSCAN
					ENDIF
		
					SET ORDER TO
		
				OTHERWISE
		
			ENDCASE
		
		
		* Draw Legends on X Axis for Vertical charts
			IF ._Orientation = 1 && Vertical
		
				IF .BarType > 0
					._DrawXAxisLegend(m.ln3D/2)
				ELSE
					._DrawXAxisLegend()
				ENDIF
		
			ENDIF
		ENDWITH
		
	ENDPROC

	PROCEDURE _drawcomments
		LOCAL lcCaption, lcObjectName, lcPolyGon, 	;
			lnAlignment, lnAlphaChannel, lnBackColor, lnFontSize, lnForeColor, lnGradientLevel, lnLeft, lnLine, lnRotation, lnTextHeight, lnTextWidth, lnTop, 	;
			loBrush, loColor1, loColor2, loShape,lnCenterX, m.lnCenterY
		FOR lnLine=1 TO THIS.CommentsSet.COUNT
		
		*	lcObjectName='Shape'+ALLTRIM(STR(THIS.Shapes.OBJECTS.COUNT+1))
		*	THIS.Shapes.ADDOBJECT(lcObjectName,[Charts.Figure])
		*	loShape = EVALUATE('this.Shapes.' + lcObjectName)
		
			loLegend = THIS.Comments
			WITH THIS.CommentsSet(lnLine)
				lnLeft = IIF(BETWEEN(.LEFT,0,1), THIS.ChartCanvas.WIDTH,1) * .LEFT
				lnTop = IIF(BETWEEN(.TOP,0,1),THIS.ChartCanvas.HEIGHT,1) * .TOP
		
				lnLeft = IIF(BETWEEN(.LEFT,0,1), THIS.WIDTH,1) * .LEFT
				lnTop  = IIF(BETWEEN(.TOP,0,1),THIS.HEIGHT,1) * .TOP
				loLegend.FONTSIZE = EVL(.FONTSIZE,11)
				loLegend.ALIGNMENT = IIF(BETWEEN(.ALIGNMENT,0,2),.ALIGNMENT,2)
		
				loLegend.FORECOLOR = .FORECOLOR
				loLegend.BACKCOLOR = .BACKCOLOR
				loLegend.FONTNAME = .FONTNAME
				loLegend.FONTSIZE = .FONTSIZE
				loLegend.FONTBOLD = .FONTBOLD
				loLegend.FONTITALIC = .FONTITALIC
				loLegend.ForeColorAlpha = .ForeColorAlpha
				loLegend.BackColorAlpha = IIF(.TYPE>0,255,.BackColorAlpha)
				lnGradientLevel = .GradientLevel
				lnRotation = .ROTATION
				loLegend.ROTATION=0
				loLegend._Setup ()
				lcCaption = .CAPTION
				IF 'CHR(13)' $ lcCaption
					lcCaption = STRTRAN(lcCaption,[CHR(13)], CHR(13)+CHR(10))
				ENDIF
		
				loLegend._Value = lcCaption
				lnTextHeight = CEILING(loLegend._Height)
				lnTextWidth = CEILING(loLegend._Width)
		
				m.lnTextLeft = m.lnLeft
				m.lnTextTop = m.lnTop
				lnHeight = lnTextHeight
				lnWidth = lnTextWidth
				lnCenterX = m.lnLeft
				lnCenterY = m.lnTop
		
				lcPolyGon = Labels(.TYPE, @lnTextLeft, @lnTextTop, @lnWidth, @lnHeight, @lnCenterX, @lnCenterY, .PointerSide, .PointerSubSide, .PointerWidth )
				loBrush = _SCREEN.SYSTEM.Drawing.SolidBrush.New(_SCREEN.SYSTEM.Drawing.COLOR.FromARGB(.BackColorAlpha,.BACKCOLOR))
			ENDWITH
			loShape = THIS._UpdateCoordinates(,"Comments", m.lnLeft, m.lnTop, m.lnWidth, m.lnHeight)
		
			WITH loShape
				lnMargin = 4
				.SetDimensions( m.lnLeft, m.lnTop, m.lnTextWidth, m.lnTextHeight)
				IF THIS.CommentsSet(lnLine).TYPE>0
					.PATH = lcPolyGon
				ENDIF
				.Contour = _Screen.FoxchartsHelper.SimplifyPath(lcPolyGon)
				IF NOT EMPTY(lnRotation)
					.Contour = _Screen.FoxchartsHelper.RotatePath(m.lnCenterX, m.lnCenterY, .Contour, lnRotation)
				ENDIF
		
				.Front = []
		
				.Legend = lcCaption
				.COLOR = lnForeColor
				.ChartIndex = lnLine
				.DRAW(THIS.oGfx, THIS._oblackpen, loBrush, m.lnCenterX, m.lnCenterY, lnRotation)
				THIS.Comments._DrawString(lnTextLeft, m.lnTextTop,lnTextWidth,lnTextHeight)
				THIS.oGfx.ResetTransform()
			ENDWITH
		
		NEXT
		
	ENDPROC

	PROCEDURE _drawcone
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D
		* Yudin Alex
		LOCAL lcFile, llConoid,	ln, lnA, lnA2, lnAngle, lnB, lnB2, lnCount, lnDelta, lnDet, ;
			lnLine, lnMX, lnMY, lnRight, lnTop3D, lnTopHeight, lnTopWidth, lnX, lnY, lnY0, loTopBrush
		LOCAL lnBottomY, lnRectY, ln3D, lcPoints, lnAlpha, lnOrigAlpha, lnTopX, lnX0,lnHorDelta,	;
			loBottomBrush AS xfcBrush, loPen AS xfcPen, loGfx AS xfcGraphics,	;
			loPath AS xfcGraphicsPath
		m.loPen   = THIS._oBorderPen
		m.loGfx = THIS.oGfx
		m.lcPoints=''
		m.lnY = tnY
		lnHorDelta=0
		This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex))
		
		lnOrigAlpha = THIS.AlphaChannel
		lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25))
		THIS.AlphaChannel = lnAlpha
		m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1)
		WITH _SCREEN.SYSTEM.Drawing
		
			DO CASE
		
				CASE THIS.BrushType = 1 && SolidColors
					loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20)))
					loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
		
				CASE THIS.BrushType = 2 && Gradient
					loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 50)))
					loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80)))
		
				CASE THIS.BrushType = 4 && TextureBrush
					lcFile = THIS.getTexture()
					IF EMPTY(lcFile)
						loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20)))
						loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
					ELSE
						loTopBrush = THIS._o3dBrush
						loBottomBrush = loTopBrush
					ENDIF
		
				OTHERWISE
					THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex))
					loTopBrush = THIS._oMainBrush
					loBottomBrush = loTopBrush
			ENDCASE
		
			THIS.AlphaChannel = lnOrigAlpha
		
			IF THIS._Orientation = 1 && Vertical
		*****************************
		*					        *
		*	  C o n e	- Vertical	*
		*					        *
		*****************************
				m.lnRectY = tnY - m.ln3D / 2
				m.lnBottomY = tnY + tnHeight - m.ln3D
				m.lnX0 = tnX + m.ln3D / 2
		* Draw ellipse
				m.loGfx.FillEllipse(loBottomBrush, m.lnX0, m.lnBottomY, tnWidth, m.ln3D)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, m.lnX0, m.lnBottomY, tnWidth, m.ln3D)
				ENDIF
		
		* Draw the front shape using a GraphicsPath object
		* Prepare the Main Path
				lnTopX = m.lnX0 + tnWidth/2
		
				loPath = .Drawing2D.GraphicsPath.New()
				loPath.StartFigure()
		
		* Bottom arc
				lnB2 = m.ln3D*m.ln3D/4
				lnA2 = tnWidth * tnWidth/4
				lnMY = lnB2 / tnHeight
				lnDet = (1-lnMY*lnMY/lnB2) * lnA2
				IF lnDet>0
					lnMX = SQRT(lnDet)
					lnAngle = RTOD(ATAN(lnMY/lnMX))
				ELSE
					lnAngle=90
					lnMX = tnWidth/2
					lnMY = 0
				ENDIF
				loPath.ADDLINE(lnTopX, m.lnRectY, lnTopX, m.lnRectY)
				loPath.AddArc(m.lnX0, m.lnBottomY, tnWidth, m.ln3D, -lnAngle, 180+lnAngle+lnAngle)
				loPath.ADDLINE(lnTopX, m.lnRectY, lnTopX, m.lnRectY)
				loPath.Reverse()
		
				loPath.ADDLINE(lnTopX, m.lnRectY, lnTopX, m.lnRectY)
		
		* Draw the path
				THIS.FillPathDim(THIS._oMainBrush, loPath)
				m.loGfx.DrawPath(m.loPen, loPath)
				IF lnMY = 0
					m.loGfx.Drawline(m.loPen,m.lnX0 + tnWidth/2, m.lnRectY, m.lnX0+tnWidth/2-lnMX   , m.lnBottomY - m.lnMY + m.ln3D / 2)
				ENDIF
				TEXT TO lcPoints	&& 	Iпdеделяем точки контуdа для dаспознавания конуса
		<<Round(lnTopX,0)>>,<<Round(m.lnRectY,0)>>,<<Round(m.lnX0+tnWidth/2-lnMx,0)>>,<<Round(tnY + tnHeight - ln3d/2 - lnMY ,0)>>,0
		<<Round(lnX0,0)>>,<<Round(m.lnBottomY,0)>>,<<Round(tnWidth,0)>>,<<Round(m.ln3D,0)>>,<<-lnAngle>>,<<180+lnAngle+lnAngle>>
		<<Round(lnTopX,0)>>,<<Round(m.lnRectY,0)>>,<<Round(m.lnX0+tnWidth/2+m.lnMx,0)>>,<<Round(tnY + tnHeight - ln3d/2 - lnMY,0)>>,0
				ENDTEXT
		
		
			ELSE &&_Orientation = 2
				llLeftRight = THIS.Charttype # 17 AND THIS._ChartIndex>1
				m.lnTopX = m.tnX + m.tnWidth &&- m.ln3D/2 * IIF(llLeftRight,0,1)
				IF THIS.Charttype = 17 AND THIS._ChartIndex=1
					m.lnStore=m.lnTopX
					m.lnTopX = m.tnX
					m.tnX=m.lnStore
				ENDIF
				m.lnX0 = tnX
				m.lnY = tnY  - m.ln3D / 2
		* Draw the front shape using a GraphicsPath object
		* Prepare the Main Path
				loPath = .Drawing2D.GraphicsPath.New()
		* Ellipse
		
				m.loGfx.FillEllipse(THIS._oMainBrush, tnX, lnY, m.ln3D, tnHeight)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, tnX, lnY, m.ln3D, tnHeight)
				ENDIF
				loPath.StartFigure()
		
		
		* Bottom Arc
				lnB2 = m.ln3D*m.ln3D/4
				lnA2 = tnHeight * tnHeight/4
				lnMY = lnB2 / tnWidth
				lnDet = (1-lnMY*lnMY/lnB2) * lnA2
				IF lnDet>0
					lnMX = SQRT(lnDet)
					lnAngle = RTOD(ATAN(lnMY/lnMX))
				ELSE
					lnAngle=90
					lnMX = tnHeight/2
					lnMY = 0
				ENDIF
				loPath.AddArc(tnX, lnY, m.ln3D, tnHeight, 90-lnAngle, 180 + lnAngle + lnAngle)
				loPath.Reverse()
				THIS.FillPathDim(THIS._oMainBrush, loPath)
				m.loGfx.DrawPath(m.loPen, loPath)
				IF lnMY = 0
					m.loGfx.Drawline(m.loPen, m.lnTopX + m.ln3D / 2, lnY + tnHeight/2, tnX + m.ln3D / 2 + lnMY, lnY + tnHeight/2-lnMX )
				ENDIF
		
		* Lines
				loPath.ADDLINE(tnX + m.ln3D / 2 + lnMY, ROUND(lnY + tnHeight/2+lnMX,0), m.lnTopX + m.ln3D / 2, lnY + tnHeight/2)
				loPath.ADDLINE(m.lnTopX + m.ln3D / 2, lnY + tnHeight/2, tnX + m.ln3D / 2 + lnMY, ROUND(lnY + tnHeight/2-lnMX,0))
		
		
		* Draw the path
				THIS.FillPathDim(THIS._oMainBrush, loPath)
				m.loGfx.DrawPath(m.loPen, loPath)
				IF lnMY = 0
					m.loGfx.Drawline(m.loPen, m.lnTopX + m.ln3D / 2, lnY + tnHeight/2, tnX + m.ln3D / 2 + lnMY, lnY + tnHeight/2-lnMX )
				ENDIF
				TEXT TO lcPoints	&& 	define the contour points for the recognition of the cone
		<<round(tnX + m.ln3D / 2 + lnMY,0)>>, <<round(lnY + tnHeight/2+lnMX,0)>>, <<round(m.lnTopX + m.ln3D / 2,0)>>, <<round(lnY + tnHeight/2,0)>>
		<<round(m.tnX,0)>>,<<round(lnY,0)>>,<<round(m.ln3D,0)>>,<<round(tnHeight,0)>>,<<90-lnAngle>>,<<180 +lnAngle+lnAngle>>
		<<round(tnX + m.ln3D / 2 + lnMY,0)>>,<<round(lnY + tnHeight/2-lnMX,0)>>,<<round(m.lnTopX + m.ln3D / 2,0)>>,<<round(lnY + tnHeight/2,0)>>
				ENDTEXT
				IF THIS.Charttype = 17 AND THIS._ChartIndex=1
					m.lnX0=m.lnTopX
				ENDIF
		
		
			ENDIF
			loShape = THIS._UpdateCoordinates(,"Rect", m.lnX0 + THIS._3d / 2, m.lnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints)
			THIS._DrawLegendinBar(m.lnX0, lnY, tnWidth, tnHeight, tnValue)
		
		ENDWITH
		RETURN lnHorDelta
		
	ENDPROC

	PROCEDURE _drawconoid
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D, tnMaxBarHeight
		* Yudin Alex 16 Apr 2013
		LOCAL lcFile, lcTopEllipse,lcTopEllipse1, llConoid,	ln, lnA, lnA2, lnAngle, lnB, lnB2, lnCount, lnDelta, lnDet, ;
			lnLine, lnMX, lnMY, lnRight, lnTop3D, lnTopHeight, lnTopWidth, lnX, lnY, lnY0, loTopBrush,	;
			lnBottomY, lnRectY, ln3D, lcPoints, lnAlpha, lnOrigAlpha, lnTopX, lnX0,lnHorDelta,	;
			loBottomBrush AS xfcBrush, loPen AS xfcPen, loGfx AS xfcGraphics,	;
			loPath AS xfcGraphicsPath
		m.loGfx = THIS.oGfx
		STORE '' TO m.lcPoints, lcFront
		THIS._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(THIS.SingleData, RECNO(),THIS._ChartIndex))
		m.loPen   = THIS._oBorderPen
		
		lnHorDelta=0
		
		lnOrigAlpha = THIS.AlphaChannel
		lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25))
		THIS.AlphaChannel = lnAlpha
		m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1)
		WITH _SCREEN.SYSTEM.Drawing
		
			DO CASE
		
				CASE THIS.BrushType = 1 && SolidColors
					loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20)))
					loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
		
				CASE THIS.BrushType = 2 && Gradient
					loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 50)))
					loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80)))
		
				CASE THIS.BrushType = 4 && TextureBrush
					lcFile = THIS.getTexture()
					IF EMPTY(lcFile)
						loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20)))
						loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
					ELSE
						loTopBrush = THIS._o3dBrush
						loBottomBrush = loTopBrush
					ENDIF
		
				OTHERWISE
					THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex))
					loTopBrush = THIS._oMainBrush
					loBottomBrush = loTopBrush
			ENDCASE
		
			THIS.AlphaChannel = lnOrigAlpha
		
			IF THIS._Orientation = 1 && Vertical
		************************
		*   Vertical conoid    *
		************************
		
				LOCAL lnRectY, lnX0, yBotCyl, loPath AS xfcGraphicsPath
				lnY = ROUND(tnY,0)
				lnB=0
				lnTopWidth = (tnMaxBarHeight-tnHeight) / tnMaxBarHeight * tnWidth
				lnTop3D = lnTopWidth * m.ln3D/tnWidth
				m.lnRectY = tnY - m.ln3D / 2
				yBotCyl = tnY + tnHeight - m.ln3D
				tnX= ROUND(tnx,0)
				lnX0 = ROUND(tnX + m.ln3D / 2,0)
		* Bottom ellipse
				m.loGfx.FillEllipse(loBottomBrush, lnX0, yBotCyl, tnWidth, m.ln3D)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, lnX0, yBotCyl, tnWidth, m.ln3D)
				ENDIF
		
				loPath = .Drawing2D.GraphicsPath.New()
				loPath.StartFigure()
		
		* Bottom arc
				lnB2 = m.ln3D*m.ln3D/4
				lnA2 = tnWidth * tnWidth/4
				lnMY = lnB2 / tnMaxBarHeight
				lnDet = (1-lnMY*lnMY/lnB2) * lnA2
		
		
				IF lnDet>0
					lnMX = SQRT(lnDet)
					lnAngle = RTOD(ATAN(lnMY/lnMX))
				ELSE
					lnAngle=90
					lnMX = tnWidth/2
					lnMY = 0
				ENDIF
				lnCenterX = lnX0 + tnWidth/2
				IF m.ln3D<3
					loPath.ADDLINE(m.lnX0+tnWidth, tnY + tnHeight-ln3D/2,m.lnX0, tnY + tnHeight-ln3D/2)
				ELSE
					loPath.AddArc(m.lnX0, yBotCyl, tnWidth, m.ln3D, 360-lnAngle, 180+lnAngle+lnAngle)
					loPath.Reverse()
				ENDIF
		
				loPath.AddArc(ROUND(lnX0 + tnWidth/2 - lnTopWidth/2,0), ROUND(m.lnRectY - m.lnTop3D/2,0), ROUND(lnTopWidth,0), ROUND(m.lnTop3D,0), MOD(360-lnAngle,360), MOD(180+lnAngle*2,360))
				loPath.Reverse()
				TEXT TO lcPoints
		<<round(m.lnX0,0)>>,<<round(yBotCyl,0)>>,<<round(tnWidth,0)>>,<<round(m.ln3D,0)>>,<<360-lnAngle>>,<<180+lnAngle*2>>
		
				ENDTEXT
		
				loPath.AddArc(m.lnX0, yBotCyl, tnWidth, m.ln3D, 180+lnAngle,0.01)	&& A начальну_ точку
		
				THIS.FillPathDim(THIS._oMainBrush, loPath)
		
		
		* Top ellipse
		
				IF m.lnTop3D<3
					loPath.ADDLINE(m.lnX0, tnY + tnHeight-ln3D/2,m.lnCenterX-lnTopWidth/2, tnY-ln3D/2)
					loPath.ADDLINE(m.lnCenterX+lnTopWidth/2, tnY-ln3D/2,m.lnCenterX-lnTopWidth/2, tnY-ln3D/2)
					loPath.ADDLINE(m.lnCenterX+lnTopWidth/2, tnY-ln3D/2,m.lnX0+tnWidth, tnY + tnHeight-ln3D/2)
					THIS.FillPathDim(THIS._oMainBrush, loPath)
					TEXT TO lcTopEllipse
		<<round(m.lnCenterX-lnTopWidth/2,0)>>,<<round(tnY-ln3D/2,0)>>,<<round(m.lnCenterX+lnTopWidth/2,0)>>,<<round(tnY-ln3D/2,0)>>
		
					ENDTEXT
					lcTopEllipse1=lcTopEllipse
				ENDIF
		* Draw the path
				m.loGfx.DrawPath(m.loPen, loPath)
		
				IF NOT m.lnTop3D<3
					m.loGfx.FillEllipse(loTopBrush, lnX0+tnWidth/2-lnTopWidth/2, m.lnRectY - m.lnTop3D/2, lnTopWidth, m.lnTop3D)
					IF VARTYPE(THIS._oDimBrush)='O'
						m.loGfx.FillEllipse(THIS._oDimBrush, lnX0+tnWidth/2-lnTopWidth/2, m.lnRectY - m.lnTop3D/2, lnTopWidth, m.lnTop3D)
					ENDIF
					m.loGfx.DrawEllipse(m.loPen   , lnX0+tnWidth/2-lnTopWidth/2, m.lnRectY - m.lnTop3D/2, lnTopWidth, m.lnTop3D)
					TEXT TO lcTopEllipse
		<<round(lnX0 + tnWidth/2 - lnTopWidth/2,0)>>,<<round(m.lnRectY - m.lnTop3D/2,0)>>,<<round(lnTopWidth,0)>>,<<round(m.lnTop3D,0)>>,180,180,1
		
					ENDTEXT
					TEXT TO lcTopEllipse1
		<<round(lnX0 + tnWidth/2 - lnTopWidth/2,0)>>,<<round(m.lnRectY - m.lnTop3D/2,0)>>,<<round(lnTopWidth,0)>>,<<round(m.lnTop3D,0)>>,180,-180,1
		
					ENDTEXT
				ENDIF
				lnHorDelta = (tnWidth - lnTopWidth) / 2
		
				TEXT TO lcFront
		<<lcPoints>>
		<<round(lnX0+tnWidth/2 - lnTopWidth/2,0)>>,<<round(m.lnRectY,0)>>,<<round(lnX0 + tnWidth/2-lnMX,0)>>,<<round(lnRectY + tnHeight - m.lnMY,0)>>,0
		<<lcTopEllipse1>>
		<<round(lnX0+tnWidth/2 + lnMx,0)>>,<<round(lnRectY + tnHeight - m.lnMY,0)>>,<<round(lnX0+tnWidth/2+lnTopWidth/2,0)>>,<<round(m.lnRectY,0)>>,0
				ENDTEXT
				TEXT TO lcPoints ADDITIVE
		<<round(lnX0+tnWidth/2 - lnTopWidth/2,0)>>,<<round(m.lnRectY,0)>>,<<round(lnX0 + tnWidth/2-lnMX,0)>>,<<round(lnRectY + tnHeight - m.lnMY,0)>>,0
		<<lcTopEllipse>>
		<<round(lnX0+tnWidth/2 + lnMx,0)>>,<<round(lnRectY + tnHeight - m.lnMY,0)>>,<<round(lnX0+tnWidth/2+lnTopWidth/2,0)>>,<<round(m.lnRectY,0)>>,0
				ENDTEXT
		
		
			ELSE &&_Orientation = 2
		
		*****************************************
		*										*
		*		      C o n o i d               *
		*			  Horizontal				*
		*										*
		*****************************************
				m.lnY = tnY - m.ln3D / 2
				m.lnTopX = tnX + tnWidth && - m.ln3D / 2
				m.lnX0 = tnX
				IF THIS.Charttype = 17 AND THIS._ChartIndex=1
					m.lnStore=m.lnTopX
					m.lnTopX = m.tnX
					m.tnX=m.lnStore
				ENDIF
		
				lnTopHeight = (tnMaxBarHeight-tnWidth) / tnMaxBarHeight * tnHeight
		
				lnTop3D = lnTopHeight * m.ln3D/tnHeight
				m.lnRectY = lnY &&- m.ln3D / 2
				yBotCyl = lnY + tnHeight && - m.ln3D
				lnX0 = tnX + m.ln3D / 2
				loPath = .Drawing2D.GraphicsPath.New()
				m.loGfx.DrawEllipse(m.loPen   , tnX, lnY, m.ln3D, tnHeight)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, tnX, lnY, m.ln3D, tnHeight)
				ENDIF
				lnHorDelta = (tnHeight - lnTopHeight) /2
				IF VARTYPE(tn3D)='N'
					tn3D = m.lnTop3D
				ENDIF
				loPath.StartFigure()
		*
		* Left arc of the ellipse
		*
				lnB2 = m.ln3D * m.ln3D / 4
				lnA2 = tnHeight * tnHeight / 4
				lnMY = lnB2 / tnMaxBarHeight
				lnDet = (1-lnMY*lnMY/lnB2) * lnA2
		
				IF lnDet>=0
					lnMX = SQRT(lnDet)
					lnAngle = RTOD(ATAN(lnMY/lnMX))
				ELSE
					lnAngle=90
					lnMX = tnHeight/2
					lnMY = 0
				ENDIF
				loPath.StartFigure()
				loPath.AddArc(tnX, lnY, m.ln3D, tnHeight, 90-lnAngle, 180 + lnAngle + lnAngle)
		*			loPath.Reverse()
		
		*	Left arc of the ellipse
				IF m.ln3D<3
					TEXT TO lcLeftEllipsePoint
		<<round(m.lnX0,0)>>,<<round(tnY + tnHeight,0)>>,<<Round(m.lnX0,0)>>,<<Round(tnY ,0)>>
		
					ENDTEXT
				ELSE
					TEXT TO lcLeftEllipsePoint
		<<round(m.tnX,0)>>,<<round(lnY,0)>>,<<round(m.ln3D,0)>>,<<round(tnHeight,0)>>,<<90-lnAngle>>,<<180 +lnAngle+lnAngle>>
		
					ENDTEXT
		
				ENDIF
		
				IF m.lnTop3D<3
					lnX = m.lnTopX+ m.ln3D / 2 - lnTop3D/2
					loPath.ADDLINE(lnX,		lnY + tnHeight/2 - lnTopHeight/2,	;
						lnX,	lnY + tnHeight/2 + lnTopHeight/2)
					STORE 0 TO lnMx2, lnMy2
					TEXT TO lcPoints	&& 	Define the contour points for the recognition of the cone
		<<round(m.lnX,0)>>,<<round(lnY + tnHeight/2 - lnTopHeight/2,0)>>,<<Round(m.lnX,0)>>,<<Round(lnY + tnHeight/2 + lnTopHeight/2,0)>>
		<<round(tnX + m.ln3D/2 + m.lnMY ,0)>>,<<round(lnY+m.tnHeight/2 + lnmX,0 )>>,<<round(m.lnTopX + m.ln3D/2 - m.lnMy2,0)>>,<<round(lnY+m.tnHeight/2 + lnMx2,0)>>,0
		<<lcLeftEllipsePoint>>
		<<round(tnX + m.ln3D/2 + m.lnMY ,0)>>,<<round(lnY+m.tnHeight/2 - lnmX,0 )>>,<<round(lnX,0)>>,<<round(lnY + tnHeight/2 - lnTopHeight/2,0)>>
		
					ENDTEXT
					lcFront = lcPoints
				ENDIF
		* Draw the path
				m.loGfx.DrawPath(m.loPen, loPath)
		
				IF NOT m.lnTop3D<3	&& Not small
					lnB2 = m.lnTop3D * m.lnTop3D /4
					lnA2 = lnTopHeight * lnTopHeight / 4
					lnMy2 = lnB2 / (tnMaxBarHeight-tnWidth)
					lnDet = (1-lnMy2*lnMy2/lnB2) * lnA2
					IF lnDet>=0
						lnMx2 = SQRT(lnDet)
					ELSE
						lnMx2 = tnHeight/2
						lnMy2 = 0
					ENDIF
					loPath.AddArc(m.lnTopX+ m.ln3D / 2 - lnTop3D/2 , lnY + tnHeight/2 - lnTopHeight/2 , lnTop3D, lnTopHeight, 270+lnAngle,180 - lnAngle * 2)
					loPath.AddArc(tnX, lnY, m.ln3D, tnHeight, 90 - lnAngle,0.001)
		
					TEXT TO lcPoints	&& 	Define the contour points for the recognition of the cone
		<<round(m.lnTopX+ m.ln3D / 2 - lnTop3D/2,0)>>,<<round(lnY + tnHeight/2 - lnTopHeight/2,0)>>,<<Round(lnTop3D,0)>>,<<Round(m.lnTopHeight,0)>>,<<270+lnAngle>>,<<180-lnAngle*2>>,1
		<<round(tnX + m.ln3D/2 + m.lnMY ,0)>>,<<round(lnY+m.tnHeight/2 + lnmX,0 )>>,<<round(m.lnTopX + m.ln3D/2 - m.lnMy2,0)>>,<<round(lnY+m.tnHeight/2 + lnMx2,0)>>,0
		<<lcLeftEllipsePoint>>
		<<round(tnX + m.ln3D/2 + m.lnMY ,0)>>,<<round(lnY+m.tnHeight/2 - lnmX,0 )>>,<<round(m.lnTopX + m.ln3D/2 + m.lnMy2,0)>>,<<round(lnY+m.tnHeight/2 - lnMX2,0)>>
					ENDTEXT
		
					TEXT TO lcFront	&& 	points of the front surface
		<<round(m.lnTopX+ m.ln3D / 2 - lnTop3D/2,0)>>,<<round(lnY + tnHeight/2 - lnTopHeight/2,0)>>,<<Round(lnTop3D,0)>>,<<Round(m.lnTopHeight,0)>>,<<270+lnAngle>>,<<-180+lnAngle*2>>,0
		<<round(tnX + m.ln3D/2 + m.lnMY ,0)>>,<<round(lnY+m.tnHeight/2 + lnmX,0 )>>,<<round(m.lnTopX + m.ln3D/2 - m.lnMy2,0)>>,<<round(lnY+m.tnHeight/2 + lnMx2,0)>>,0
		<<lcLeftEllipsePoint>>
		<<round(tnX + m.ln3D/2 + m.lnMY ,0)>>,<<round(lnY+m.tnHeight/2 - lnmX,0 )>>,<<round(m.lnTopX + m.ln3D/2 + m.lnMy2,0)>>,<<round(lnY+m.tnHeight/2 - lnMX2,0)>>
		
					ENDTEXT
				ENDIF
		
				THIS.FillPathDim(THIS._oMainBrush, loPath)
		
				m.loGfx.DrawPath(m.loPen, loPath)
				IF lnMY = 0
		*				m.loGfx.Drawline(m.loPen, m.lnTopX + m.ln3D / 2, lnY + tnHeight/2, tnX + m.ln3D / 2 + lnMY, lnY + tnHeight/2-lnMX )
				ENDIF
		* Right ellipse
		*		m.loGfx.FillEllipse(THIS._o3dBrush, m.lnTopX+ m.ln3D / 2 - lnTop3D/2 , lnY + tnHeight/2 - lnTopHeight/2 , lnTop3D, lnTopHeight)
				m.loGfx.DrawEllipse(m.loPen   , m.lnTopX+ m.ln3D / 2 - lnTop3D/2 , lnY + tnHeight/2 - lnTopHeight/2 , lnTop3D, lnTopHeight)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, m.lnTopX+ m.ln3D / 2 - lnTop3D/2 , lnY + tnHeight/2 - lnTopHeight/2 , lnTop3D, lnTopHeight)
				ENDIF
				IF THIS.Charttype = 17 AND THIS._ChartIndex=1
					m.lnX0 = m.lnTopX
		
				ENDIF
		
			ENDIF
		
			IF VARTYPE(tn3D)='N'
				tn3D = m.lnTop3D
			ENDIF
			loShape = THIS._UpdateCoordinates(,"Rect", m.lnX0 + THIS._3d / 2, m.lnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints,,lcFront)
			THIS._DrawLegendinBar(m.lnX0, lnY, tnWidth, tnHeight, tnValue)
		
		ENDWITH
		RETURN lnHorDelta
		
	ENDPROC

	PROCEDURE _drawcylinder
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D
		LOCAL lcFile, ln, lnY, lcPoints, lnA, lnA2, lnB, lnB2, lnCount, lnDelta, lnLine, lnX	;
			,lnAlpha, lnOrigAlpha, loTopBrush AS xfcBrush, loBotBrush AS xfcBrush	;
			,loPen AS xfcPen, loGfx AS xfcGraphics
		This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex))
		m.loPen   = THIS._oBorderPen
		m.loGfx = THIS.oGfx
		
		lnOrigAlpha = THIS.AlphaChannel
		lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25))
		THIS.AlphaChannel = lnAlpha
		m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1)
		lnY = tnY
		
		WITH _SCREEN.SYSTEM.Drawing
		
			DO CASE
		
				CASE THIS.BrushType = 1 && SolidColors
					loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20)))
					loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
		
				CASE THIS.BrushType = 2 && Gradient
					loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 50)))
					loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80)))
				CASE THIS.BrushType = 4 && TextureBrush
					lcFile = THIS.getTexture()
					IF EMPTY(lcFile)
						loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20)))
						loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
					ELSE
						loTopBrush = THIS._o3dBrush
						loBotBrush = loTopBrush
					ENDIF
		
				OTHERWISE
					THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex))
					loTopBrush = THIS._oMainBrush
					loBotBrush = loTopBrush
			ENDCASE
		
			THIS.AlphaChannel = lnOrigAlpha
		
			IF THIS._Orientation = 1 && Vertical
		
				LOCAL lnRectY, lnX0, yTopCyl, yBotCyl
		
				lnRectY = tnY - (m.ln3D / 2)
				yTopCyl = tnY - m.ln3D
				yBotCyl = tnY + tnHeight - m.ln3D
				lnX0 = tnX + m.ln3D / 2
		
		* Нижний эллипс
				m.loGfx.FillEllipse(loBotBrush, lnX0, yBotCyl, tnWidth, m.ln3D)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, lnX0, yBotCyl, tnWidth, m.ln3D)
				ENDIF
		
		* Draw the front shape using a GraphicsPath object
		* Prepare the Main Path
				LOCAL loPath AS xfcGraphicsPath
				loPath = .Drawing2D.GraphicsPath.New()
				loPath.FillMode = .Drawing2D.FillMode.ALTERNATE
		
				loPath.StartFigure()
		
		
		* Нижняя дуга
				loPath.AddArc(lnX0, yBotCyl, tnWidth, m.ln3D, 180, -180)
		*		loPath.Reverse()
		
		* Правая боковая линия
				loPath.ADDLINE(lnX0 + tnWidth, lnRectY + tnHeight, lnX0 + tnWidth, lnRectY)
		
		* Верхняя дуга
				loPath.AddArc(lnX0, yTopCyl, tnWidth, m.ln3D, 0, 180)
		
		* Рисуем дорожку
				THIS.FillPathDim(THIS._oMainBrush, loPath)
				m.loGfx.DrawPath(m.loPen, loPath)
				loPath = .Drawing2D.GraphicsPath.New()
		* Верхний эллипс
				loPath.StartFigure()
				loPath.AddEllipse(lnX0, yTopCyl, tnWidth, m.ln3D)
				loTopBrush=_Screen.FoxChartsHelper.PathGradient( , m.loPath, THIS._nColor,-1, lnX0+tnWidth/2, yTopCyl+m.ln3D/2)
		
				m.loGfx.FillEllipse(loTopBrush, lnX0, yTopCyl, tnWidth, m.ln3D)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, lnX0, yTopCyl, tnWidth, m.ln3D)
				ENDIF
				m.loGfx.DrawEllipse(m.loPen   , lnX0, yTopCyl, tnWidth, m.ln3D)
		
		*
		*	Координаты контура
		*
				TEXT TO lcPoints
		<<ROUND(lnX0,0)>>,<<ROUND(yBotCyl,0)>>,<<ROUND(tnWidth,0)>>,<<ROUND(m.ln3D,0)>>,0, 180
		<<ROUND(lnX0,0)>>,<<ROUND(lnRectY + tnHeight,0)>>,<<ROUND(lnX0,0)>>,<<ROUND(lnRectY,0)>>
		<<ROUND(lnX0,0)>>,<<ROUND(yTopCyl,0)>>,<<ROUND(tnWidth,0)>>,<<ROUND(m.ln3D,0)>>,-180,180,1
		<<ROUND(m.lnX0+tnWidth,0)>>,<<ROUND(lnRectY,0)>>,<<ROUND(m.lnX0+tnWidth,0)>>,<<ROUND(lnRectY + tnHeight,0)>>
				ENDTEXT
		
		
			ELSE &&_Orientation = 2  - Horizontal
		***************************************
		*                                     *
		*       Горизонтальный цилиндр        *
		*                                     *
		***************************************
		
				LOCAL xRect
		
				xRect = tnX - m.ln3D / 2
				xTopCyl = tnX + tnWidth  &&- m.ln3D / 2
				xBotCyl = tnX - m.ln3D
				lnY = tnY - m.ln3D / 2
		
		* Draw the left-most ellipse
				m.loGfx.FillEllipse(loBotBrush      , tnX, lnY, m.ln3D, tnHeight)
				m.loGfx.FillEllipse(THIS._oMainBrush, tnX, lnY, m.ln3D, tnHeight)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, tnX, lnY, m.ln3D, tnHeight)
					m.loGfx.FillEllipse(THIS._oDimBrush, tnX, lnY, m.ln3D, tnHeight)
		
				ENDIF
		
		* Draw the front shape using a GraphicsPath object
		* Prepare the Main Path
				LOCAL loPath AS xfcGraphicsPath
				loPath = .Drawing2D.GraphicsPath.New()
				loPath.StartFigure()
		
		
		* Нижняя дуга
				loPath.AddArc(tnX, lnY, m.ln3D, tnHeight, 90, 180)
				loPath.Reverse()
		
		* Нижняя линия
				loPath.ADDLINE(tnX + m.ln3D / 2, lnY + tnHeight, xTopCyl + m.ln3D / 2, lnY + tnHeight)
		
		* Top Arc
				loPath.AddArc(xTopCyl, lnY, m.ln3D, tnHeight, 90, 180)
		
		* Top Line
				loPath.ADDLINE(xTopCyl + m.ln3D / 2, lnY, tnX + m.ln3D / 2, lnY)
		
		* Draw the path
				THIS.FillPathDim(THIS._oMainBrush, loPath)
				m.loGfx.DrawPath(m.loPen, loPath)
		
		
		
		
		* Draw the upper ellipse
				m.loGfx.FillEllipse(loTopBrush, xTopCyl, lnY, m.ln3D, tnHeight)
				IF VARTYPE(THIS._oDimBrush)='O'
					m.loGfx.FillEllipse(THIS._oDimBrush, xTopCyl, lnY, m.ln3D, tnHeight)
				ENDIF
				m.loGfx.DrawEllipse(m.loPen, xTopCyl, lnY, m.ln3D, tnHeight)
		
		*
		*	Координаты контура
		*
				TEXT TO lcPoints
		<<Round(tnX + m.ln3D / 2,0)>>,<<Round(lnY + tnHeight,0)>>,<<Round(xTopCyl + m.ln3D / 2,0)>>,<<Round(lnY + tnHeight,0)>>
		<<Round(tnX,0)>>,<<Round(lnY,0)>>,<<Round(m.ln3D,0)>>,<<Round(tnHeight,0)>>, 90, 180
		<<Round(tnX + m.ln3D / 2,0)>>,<<Round(lnY,0)>>,<<Round(xTopCyl + m.ln3D / 2,0)>>,<<Round(lnY,0)>>
		<<Round(xTopCyl,0)>>,<<Round(lnY,0)>>,<<Round(m.ln3D,0)>>,<<Round(tnHeight,0)>>, 270,180,1
				ENDTEXT
			ENDIF
		
			loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + THIS._3d / 2, m.lnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints)
		
			THIS._DrawLegendinBar(tnX, lnY, tnWidth, tnHeight, tnValue,,loShape)
		ENDWITH
		
	ENDPROC

	PROCEDURE _drawdoughnutslice
		LPARAMETERS  tnX, tnY, tnWidth, tnHeight, tnStart, tnSweep, tnValue, toShape
		
		IF tnWidth <=0 OR tnHeight <=0
			RETURN
		ENDIF
		
		WITH THIS
		
			._AdjustStartSweep(@tnStart, @tnSweep, tnWidth, tnHeight)
			toShape = THIS._UpdateCoordinates(toShape,"Pie", tnX, tnY, tnWidth, tnHeight, tnValue, tnStart, tnSweep)
		
			LOCAL lnXBrush, lnYBrush
			IF THIS.PieEnhancedDrawing
				lnXBrush = tnX
				lnYBrush = tnY
			ELSE
				lnXBrush = 0
				lnYBrush = 0
			ENDIF
			THIS._PrepareBrushes(lnXBrush, lnYBrush, m.tnWidth, m.tnHeight, .F., RECNO())
		
		
			LOCAL loPen AS xfcPen, loGfx AS xfcGraphics, loMainBrush AS xfcBrush, lo3dBrush AS xfcBrush, ln3d, lnFinalAngle
			m.loPen = THIS._oBorderPen
			m.loGfx = THIS.oGfx
			m.loMainBrush = THIS._oMainBrush
			lo3dBrush = THIS._o3DBrush
		
			m.ln3d = THIS._3D
			lnFinalAngle = tnStart + tnSweep
			IF lnFinalAngle > 360
				lnFinalAngle = lnFinalAngle - 360
			ENDIF
		ENDWITH
		
		
		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
				loMainPath = .Drawing2D.GraphicsPath.New()
		
				LOCAL loRect AS xfcRectangle, loRect2 AS xfcRectangle, lnRatio
				lnRatio = THIS.DonutRatio
		
				loRect  = .Rectangle.New(tnX, tnY, tnWidth, tnHeight)
				loRect2 = .Rectangle.New(;
					tnX + (tnWidth  * (1 - lnRatio) / 2), ;
					tnY + (tnHeight * (1 - lnRatio) / 2), ;
					tnWidth  * lnRatio, ;
					tnHeight * lnRatio)
		
		
				LOCAL lnXInt, lnYInt, lnHInt, lnWInt
				lnXInt = loRect2.X
				lnYInt = loRect2.Y
				lnWInt = loRect2.WIDTH
				lnHInt = loRect2.HEIGHT
		
		
				LOCAL loPoint0 AS xfcPointF, loPoint1 AS xfcPointF, loPoint2 AS xfcPointF, loPoint3 AS xfcPointF, loPath AS xfcGraphicsPath
		
		* Obtaining the needed points
				loMainPath.AddArc(loRect, tnStart, 0.0001)
				loPoint0 = loMainPath.GetLastPoint()
		
				loMainPath.AddArc(loRect2, tnStart, 0.0001)
				loPoint3 = loMainPath.GetLastPoint()
		
				loMainPath.AddArc(loRect, tnStart, tnSweep)
				loPoint1 = loMainPath.GetLastPoint()
		
				loMainPath.AddArc(loRect2, tnStart, tnSweep)
				loPoint2 = loMainPath.GetLastPoint()
		
				loPoint4 = .POINT.New(loPoint3.X, loPoint3.Y + m.ln3d)
				loPoint5 = .POINT.New(loPoint0.X, loPoint0.Y + m.ln3d)
				loPoint6 = .POINT.New(loPoint1.X, loPoint1.Y + m.ln3d)
		
		* Prepare the Main Path
				loPath = .Drawing2D.GraphicsPath.New()
		
				loPath.StartFigure()
				loPath.AddArc(loRect2, tnStart, tnSweep)
				loPath.Reverse()
				loPath.ADDLINE(loPoint3.X, loPoint3.Y, loPoint0.X, loPoint0.Y)
				loPath.AddArc(loRect, tnStart, tnSweep)
				loPath.ADDLINE(loPoint1.X, loPoint1.Y, loPoint2.X, loPoint2.Y)
		
		
				IF ln3d = 0 OR THIS.SHADOW
		
		* Draw shadow
					IF THIS.SHADOW
		
		* Prepare the Shadow Path
						LOCAL loPath2 AS xfcGraphicsPath
						loPath2 = .Drawing2D.GraphicsPath.New()
		
						loPath2.StartFigure()
						loPath2.AddArc(loRect2.X, loRect2.Y + ln3d, loRect2.WIDTH, loRect2.HEIGHT, tnStart, tnSweep)
						loPath2.Reverse()
						loPath2.ADDLINE(loPoint3.X, loPoint3.Y + ln3d, loPoint0.X, loPoint0.Y + ln3d)
						loPath2.AddArc(loRect.X, loRect.Y + ln3d, loRect.WIDTH, loRect.HEIGHT, tnStart, tnSweep)
						loPath2.ADDLINE(loPoint1.X, loPoint1.Y + ln3d, loPoint2.X, loPoint2.Y + ln3d)
		
		* Prepare the shadow brush
						LOCAL loShadowBrush AS xfcSolidBrush
						m.loShadowBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel,128,128,128))
		
		* Draw the shadow
						THIS.FillPathDim(loShadowBrush, loPath2)
					ENDIF
		
		* Draw the Main doughnut slice (path)
					THIS.FillPathDim(m.loMainBrush, loPath)
					m.loGfx.DrawPath(m.loPen, loPath)
					RETURN
				ENDIF
		
		
		* Continue Drawing, for 3D chart
		
		* Prepare the polygon points for the final part of the slice
				DIMENSION laEndPoints(4)
				laEndPoints(1) = loPoint1
				laEndPoints(2) = loPoint2
				laEndPoints(3) = .POINT.New(loPoint2.X, loPoint2.Y + m.ln3d)
				laEndPoints(4) = loPoint6
		
		* Prepare the polygon points for the beginning part of the slice
				DIMENSION laStartPoints(4)
				laStartPoints(1) = loPoint0
				laStartPoints(2) = loPoint5
				laStartPoints(3) = loPoint4
				laStartPoints(4) = loPoint3
		
		
		* If the slice ends in the left side, draw the Ending polygon before the top face of the slice
				IF BETWEEN(lnFinalAngle, 90.001, 269.999)
					m.loGfx.DrawPolygon(m.loPen, @laEndPoints)
					m.loGfx.FillPolygon(lo3dBrush, @laEndPoints)
					IF VARTYPE(THIS._oDimBrush)='O'
						m.loGfx.FillPolygon(THIS._oDimBrush, @laEndPoints)
					ENDIF
				ENDIF
		
				IF NOT (tnStart >= 90 AND tnStart <= 270)
					m.loGfx.DrawPolygon(m.loPen, @laStartPoints)
					IF VARTYPE(THIS._oDimBrush)='O'
						m.loGfx.FillPolygon(THIS._oDimBrush, @laStartPoints)
					ENDIF
				ENDIF
		
		
		
		
		
		* Draw the external and internal paths
				LOCAL lnFinalAngle
				lnFinalAngle = tnStart + tnSweep
				IF lnFinalAngle > 360
					lnFinalAngle = lnFinalAngle - 360
				ENDIF
		
		
				LOCAL lnAdjStart, lnAdjSweep
				lnAdjStart = tnStart
				lnAdjSweep = tnSweep
		
				LOCAL loAdjPoint0 AS xfcPoint, loAdjPoint1 AS xfcPoint
				loAdjPoint0 = loPoint0
				loAdjPoint1 = loPoint1
		
				LOCAL loAdjPoint2 AS xfcPoint, loAdjPoint3 AS xfcPoint
				loAdjPoint2 = loPoint3
				loAdjPoint3 = loPoint2
		
		
				IF tnStart >= 270 AND ;
						tnStart < 360 AND ;
						BETWEEN(lnFinalAngle, 0, 270)
		
					LOCAL loTempPoint AS xfcPoint
					loTempPoint = .POINT.New(tnX + tnWidth, tnY + tnHeight / 2)
		
					LOCAL loTempPoint2 AS xfcPoint
					loTempPoint2 = .POINT.New(lnXInt + lnWInt, lnYInt + lnHInt / 2)
		
		* External part
					THIS._DrawSliceExternal(tnX, tnY, tnWidth, tnHeight, tnStart, 360 - tnStart, loPoint0, loTempPoint)
		
		* Internal part
					THIS._DrawSliceExternal(lnXInt, lnYInt, lnWInt, lnHInt, tnStart, 360 - tnStart, loPoint3, loTempPoint2)
		
		
					lnAdjStart = 0
					lnAdjSweep = tnSweep - (360 - tnStart)
					loAdjPoint0 = loTempPoint
					loAdjPoint1 = loPoint1
		
		* Internal
					loAdjPoint2 = loTempPoint2
					loAdjPoint3 = loPoint2
		
				ENDIF
		
		
				LOCAL llDrawExtAtEnd
				llDrawExtAtEnd = .F.
		
		
				IF (tnStart < 180 AND lnFinalAngle > 180) OR ;
						(tnStart >= 270 AND lnFinalAngle > 180 AND lnFinalAngle < 270.01)
		
					IF tnStart >= 270
						lnAdjStart = 0
						lnAdjSweep = 180
					ELSE
						lnAdjStart = tnStart
						lnAdjSweep = 180 - tnStart
					ENDIF
		
					loAdjPoint1 = .POINT.New(tnX, tnY + tnHeight / 2)
					loAdjPoint3 = .POINT.New(lnXInt, lnYInt + lnHInt / 2)
		
		* External part
					llDrawExtAtEnd = .T.
					LOCAL lnStartB, lnSweepB, loPoint0B, loPoint1B
					lnStartB = lnAdjStart
					lnSweepB = lnAdjSweep
					loPoint0B = loAdjPoint0
					loPoint1B = loAdjPoint1
		
		* Internal part
					THIS._DrawSliceExternal(lnXInt, lnYInt, lnWInt, lnHInt, lnAdjStart, lnAdjSweep, loAdjPoint2, loAdjPoint3)
		
					loAdjPoint0 = loAdjPoint1
					loAdjPoint2 = loAdjPoint3
		
					lnAdjStart = 180
					lnAdjSweep = lnFinalAngle - 180
				ENDIF
		
		
				IF BETWEEN(lnFinalAngle, 0,180)
		* Internal part
					THIS._DrawSliceExternal(lnXInt, lnYInt, lnWInt, lnHInt, lnAdjStart, lnAdjSweep, loAdjPoint2, loPoint2)
		* External part
					THIS._DrawSliceExternal(tnX, tnY, tnWidth, tnHeight, lnAdjStart, lnAdjSweep, loAdjPoint0, loPoint1)
				ELSE
		* External part
					THIS._DrawSliceExternal(tnX, tnY, tnWidth, tnHeight, lnAdjStart, lnAdjSweep, loAdjPoint0, loPoint1)
		* Internal part
					THIS._DrawSliceExternal(lnXInt, lnYInt, lnWInt, lnHInt, lnAdjStart, lnAdjSweep, loAdjPoint2, loPoint2)
				ENDIF
		
		
				IF llDrawExtAtEnd
					THIS._DrawSliceExternal(tnX, tnY, tnWidth, tnHeight, lnStartB, lnSweepB, loPoint0B, loPoint1B)
				ENDIF
		
		
		* Draw polygon at the beginning of the doughnut
				IF tnStart > 90 AND tnStart < 270
					m.loGfx.DrawPolygon(m.loPen, @laStartPoints)
					m.loGfx.FillPolygon(lo3dBrush, @laStartPoints)
					IF VARTYPE(THIS._oDimBrush)='O'
						m.loGfx.FillPolygon(THIS._oDimBrush, @laStartPoints)
					ENDIF
				ENDIF
		
				IF NOT BETWEEN(lnFinalAngle, 90, 270)
					m.loGfx.DrawPolygon(m.loPen, @laEndPoints)
					m.loGfx.FillPolygon(lo3dBrush, @laEndPoints)
					IF VARTYPE(THIS._oDimBrush)='O'
						m.loGfx.FillPolygon(THIS._oDimBrush, @laEndPoints)
					ENDIF
				ENDIF
		
		
		* Draw the main path
				THIS.FillPathDim(m.loMainBrush, loPath)
				m.loGfx.DrawPath(m.loPen, loPath)
		
			ENDWITH
		
		
		ELSE && This.PieEnhancedDrawing .F. - This is the old Behavior
		
			WITH _SCREEN.SYSTEM.Drawing
		
		
				LOCAL loBmp AS xfcBitmap
				loBmp = poTempBmp
				LOCAL loTempGfx AS xfcGraphics
				loTempGfx = .Graphics.FromImage(loBmp)
				loTempGfx.CLEAR(.COLOR.Transparent)
				loTempGfx.SmoothingMode = .Drawing2D.SmoothingMode.AntiAlias
		
		
		
		* Create a GraphicsPath object.
				LOCAL loTempPath AS xfcGraphicsPath
				loTempPath = .Drawing2D.GraphicsPath.New()
		
				LOCAL loRect AS xfcRectangle, loRect2 AS xfcRectangle, lnRatio
				lnRatio = THIS.DonutRatio
		
				loRect  = .Rectangle.New(0, 0, tnWidth, tnHeight)
				loRect2 = .Rectangle.New(;
					(tnWidth  * (1 - lnRatio) / 2), ;
					(tnHeight * (1 - lnRatio) / 2), ;
					tnWidth  * lnRatio, ;
					tnHeight * lnRatio)
		
				LOCAL loPoint0 AS xfcPointF, loPoint1 AS xfcPointF, loPoint2 AS xfcPointF, loPoint3 AS xfcPointF
		
		* Obtaining the needed points
				loTempPath.AddArc(loRect, tnStart, 0.0001)
				loPoint0 = loTempPath.GetLastPoint()
		
				loTempPath.AddArc(loRect2, tnStart, 0.0001)
				loPoint3 = loTempPath.GetLastPoint()
		
				loTempPath.AddArc(loRect, tnStart, tnSweep)
				loPoint1 = loTempPath.GetLastPoint()
		
				loTempPath.AddArc(loRect2, tnStart, tnSweep)
				loPoint2 = loTempPath.GetLastPoint()
		
				loPoint4 = .POINT.New(loPoint3.X, loPoint3.Y + m.ln3d)
				loPoint5 = .POINT.New(loPoint0.X, loPoint0.Y + m.ln3d)
				loPoint6 = .POINT.New(loPoint1.X, loPoint1.Y + m.ln3d)
		
		* Prepare the Main Path
				LOCAL loPath AS xfcGraphicsPath
				loPath = .Drawing2D.GraphicsPath.New()
		
				loPath.StartFigure()
				loPath.ADDLINE(loPoint0.X, loPoint0.Y, loPoint3.X, loPoint3.Y)
				loPath.AddArc(loRect2, tnStart, tnSweep)
				loPath.StartFigure()
				loPath.AddArc(loRect, tnStart, tnSweep)
				loPath.ADDLINE(loPoint1.X, loPoint1.Y, loPoint2.X, loPoint2.Y)
		
		
				IF m.ln3d > 0
		
		* Create a new Path for the 3D
					LOCAL lo3DPath AS xfcPath, loMatrix AS xfcMatrix
					lo3DPath = loPath.CLONE()
					loMatrix = .Drawing2D.Matrix.New()
					loMatrix.Translate(0,+1)
		
		
		* Prepare the polygon points for the final part of the slice
					DIMENSION laPointsB(4)
					laPointsB(1) = loPoint1
					laPointsB(2) = loPoint2
					laPointsB(3) = .POINT.New(loPoint2.X, loPoint2.Y + m.ln3d)
					laPointsB(4) = loPoint6
		
		
		* If the slice ends in the left side, draw the polygon before the top face of the slice
					IF BETWEEN(lnFinalAngle, 90, 270)
						loTempGfx.DrawPolygon(m.loPen, @laPointsB)
					ENDIF
		
		
					LOCAL N
					FOR N = 1 TO m.ln3d - 1
						lo3DPath.TRANSFORM(loMatrix)
						loTempGfx.FillPathDim(lo3dBrush, lo3DPath)
					NEXT
		
		* Draw the side Polygons
		
		* Draw polygon at the beginning of the donut
					IF tnStart > 90 AND tnStart < 270
						DIMENSION laPoints(4)
						laPoints(1) = loPoint0
						laPoints(2) = loPoint5
						laPoints(3) = loPoint4
						laPoints(4) = loPoint3
						loTempGfx.DrawPolygon(m.loPen, @laPoints)
					ENDIF
		
		* Draw polygon at the end of the donut
					IF lnFinalAngle < 90 OR lnFinalAngle > 270
						loTempGfx.DrawPolygon(m.loPen, @laPointsB)
					ENDIF
				ENDIF
		
		
		* Draw the path
				loTempGfx.FillPathDim(m.loMainBrush, loPath)
				loTempGfx.DrawPath(THIS._oBorderPen, loPath)
		
				loBmp.ApplyColorMatrix(poClrMatrix)
				m.loGfx.DrawImage(loBmp, tnX, tnY)
		
			ENDWITH
		
		ENDIF
		
	ENDPROC

	PROCEDURE _drawfrustum
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D, tnMaxBarHeight
		* Yudin Alex 21 May 2013
		LOCAL lcFront, lcPoints, 	;
			ln3D, lnAlpha, lnHorDelta, lnOrigAlpha, lnStore, lnTop3D, lnTopHeight, lnTopWidth, lnTopX, lnTopY, 	;
			loBotBrush, loGfx, loPen
		
		m.lnHorDelta=0
		m.tnHeight = ABS(m.tnHeight)
		m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1)
		
		m.loGfx = THIS.oGfx
		
		m.lnOrigAlpha = THIS.AlphaChannel
		m.lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25))
		THIS.AlphaChannel = lnAlpha
		m.lcFront=''
		
		THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex))
		m.loPen   = THIS._oBorderPen
		
		WITH _SCREEN.SYSTEM.Drawing
		
			DO CASE
		
				CASE THIS.BrushType = 1 && SolidColors
					loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
		
				CASE THIS.BrushType = 2 && Gradient
					loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80)))
		
				OTHERWISE
		*			THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex))
					loBotBrush = THIS._oMainBrush
			ENDCASE
		
			THIS.AlphaChannel = lnOrigAlpha
			lcPoints=''
		
		
			LOCAL laPoints(4)
		
		* Draw the 3D Bar using the 3DBrush
			IF THIS._Orientation = 1 && Vertical
				lnTopWidth = (tnMaxBarHeight-tnHeight) / tnMaxBarHeight * tnWidth
				lnTop3D = lnTopWidth * m.ln3D/tnWidth
				lnHorDelta = (tnWidth - lnTopWidth) /2
		
				lnTopX = m.tnX + (m.tnWidth - lnTopWidth)/2 + (ln3D - lnTop3D)/2
				lnTopY = m.tnY - (ln3D - lnTop3D)/2
		
		* Prepare points to draw the 3D part of the Pyramid
		* Bottom
				m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight)
				m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D + m.tnHeight)
				m.laPoints(3) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D + m.tnHeight)
				m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight)
		
				m.loGfx.FillPolygon(m.loBotBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		* Left wall
				LOCAL laPoints(4)
		
				m.laPoints(1) = .PointF.New(m.tnX, m.tnY + m.tnHeight)
				m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D + m.tnHeight)
				m.laPoints(3) = .PointF.New(m.lnTopX + m.lnTop3D, lnTopY - m.lnTop3D)
				m.laPoints(4) = .PointF.New(m.lnTopX, lnTopY)
		
				m.loGfx.FillPolygon(THIS._o3DBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		* Top
				m.laPoints(1) = .PointF.New(m.lnTopX + lnTopWidth, lnTopY)
				m.laPoints(2) = .PointF.New(m.lnTopX + lnTopWidth + m.lnTop3D, lnTopY - m.lnTop3D)
				m.laPoints(3) = .PointF.New(m.lnTopX + m.lnTop3D, lnTopY - m.lnTop3D)
		*			m.laPoints(4) = .PointF.New(m.lnTopX, m.tnY)
		
				m.loGfx.FillPolygon(m.loBotBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		
		
		* Front
		
				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.lnTopX + lnTopWidth, m.lnTopY)
				m.loGfx.FillPolygon(THIS._oMainBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		
		*	Right wall
				m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight)
				m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D + m.tnHeight)
				m.laPoints(3) = .PointF.New(m.lnTopX + lnTopWidth+ m.lnTop3D, lnTopY - m.lnTop3D)
				m.laPoints(4) = .PointF.New(m.lnTopX + lnTopWidth,lnTopY)
		
				m.loGfx.FillPolygon(THIS._oRightbrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
				TEXT TO lcPoints
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D + m.tnHeight,0)>>
		<<ROUND(m.lnTopX + m.lnTopWidth + m.lnTop3D,0)>>,<<ROUND(m.lnTopY - m.lnTop3D,0)>>
		<<ROUND(m.lnTopX +m.lnTop3D,0)>>,<<ROUND(m.lnTopY - m.lnTop3D ,0)>>
		<<ROUND(m.lnTopX ,0)>>,<<ROUND(m.lnTopY ,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
				ENDTEXT
				TEXT TO lcFront
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.lnTopX + m.lnTopWidth,0)>>,<<ROUND(m.lnTopY,0)>>
		<<ROUND(m.lnTopX ,0)>>,<<ROUND(m.lnTopY ,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
				ENDTEXT
				IF VARTYPE(tn3D)='N'
					tn3D= m.lnTop3D
				ENDIF
		
			ELSE
		****************
		*              *
		*  Horizontal  *
		*              *
		****************
				lnTopHeight = (tnMaxBarHeight-tnWidth) / tnMaxBarHeight * tnHeight
				lnTop3D = lnTopHeight * m.ln3D/tnHeight
				lnHorDelta = (tnHeight - lnTopHeight) /2
		
				lnTopX = m.tnX  + m.tnWidth + (ln3D - lnTop3D)/2
				lnTopY = m.tnY + (m.tnHeight - lnTopHeight)/2 + (ln3D - lnTop3D)/2	-(ln3D - lnTop3D)
				IF THIS.Charttype = 17 AND THIS._ChartIndex=1
					m.lnStore=m.lnTopX
					m.lnTopX = m.tnX
					m.tnX=m.lnStore
				ENDIF
		
		* Left bottom
				m.laPoints(1) = .PointF.New(m.tnX, m.tnY)
				m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D)
				m.laPoints(3) = .PointF.New(m.tnX+ m.ln3D, m.tnY + m.tnHeight - m.ln3D)
				m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight)
		
				m.loGfx.FillPolygon(m.loBotBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		* Right bottom
				m.laPoints(1) = .PointF.New(m.lnTopX, m.lnTopY)
				m.laPoints(2) = .PointF.New(m.lnTopX + m.lnTop3D, m.lnTopY - m.lnTop3D)
				m.laPoints(3) = .PointF.New(m.lnTopX + m.lnTop3D, m.lnTopY + m.lnTopHeight - m.lnTop3D)
				m.laPoints(4) = .PointF.New(m.lnTopX, m.lnTopY + m.lnTopHeight)
		
				m.loGfx.FillPolygon(m.loBotBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		* Walls
		* 1.Top
				m.laPoints(1) = .PointF.New(m.tnX, m.tnY)
				m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D)
				m.laPoints(3) = .PointF.New(m.lnTopX + m.lnTop3D, m.lnTopY - m.lnTop3D)
				m.laPoints(4) = .PointF.New(m.lnTopX, m.lnTopY)
		
				m.loGfx.FillPolygon(THIS._o3DBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		
		* 2. Front
				m.laPoints(1) = .PointF.New(m.tnX, m.tnY)
				m.laPoints(2) = .PointF.New(m.lnTopX, m.lnTopY)
				m.laPoints(3) = .PointF.New(m.lnTopX, m.lnTopY + m.lnTopHeight)
				m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight)
		
				m.loGfx.FillPolygon(THIS._oMainBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
				TEXT TO lcPoints
		<<ROUND(m.tnX ,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY,0)>>
		<<ROUND(m.tnX + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D,0)>>
		<<ROUND(m.lnTopX + m.lnTop3D,0)>>,<<ROUND(m.lnTopY - m.lnTop3D,0)>>
		<<ROUND(m.lnTopX + m.lnTop3D,0)>>,<<ROUND(m.lnTopY + m.lnTopHeight - m.lnTop3D,0)>>
		<<ROUND(m.lnTopX,0)>>,<<ROUND(m.lnTopY + m.lnTopHeight,0)>>
		<<ROUND(m.tnX ,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
				ENDTEXT
				TEXT TO lcFront
		<<ROUND(m.tnX ,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY,0)>>
		<<ROUND(m.lnTopX,0)>>,<<ROUND(m.lnTopY,0)>>
		<<ROUND(m.lnTopX,0)>>,<<ROUND(m.lnTopY + m.lnTopHeight,0)>>
		<<ROUND(m.tnX ,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
				ENDTEXT
				IF VARTYPE(tn3D)='N'
					tn3D= m.lnTop3D
				ENDIF
				IF THIS.Charttype = 17 AND THIS._ChartIndex=1
					m.tnX=m.lnTopX
				ENDIF
		
			ENDIF
			loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints,,lcFront)
			THIS._DrawLegendinBar(tnX, tnY, tnWidth, tnHeight, tnValue)
		
		ENDWITH
		RETURN lnHorDelta
		
	ENDPROC

	PROCEDURE _drawlegendinbar
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tnIndex, loShapeObject
		
		* Zero values in Stacked charts will not have space for drawing legends
		* so we'll ignore this case
		LOCAL lcCaption, lcLegend, lcValue, lnDecimals, loObject
		IF VARTYPE(tnHeight) # 'N'
			tnHeight = 8
		ENDIF
		WITH THIS
			IF ._Stacked AND tnValue = 0
				RETURN
			ENDIF
			.CurrIndex = ._nIndex
		
			LOCAL lnLeftMargin
			lnLeftMargin = ._yAxisWidth + ._LeftOffset
		
		*!*	Other available properties
		*!*		.CurrValue
		*!*		.CurrLegend
		*!*		.CurrObjType
		*!*		.CurrRecno
		*!*		.CurrColumn
		
			IF TYPE('.Fields(._ChartIndex)') # 'U' AND NOT .FIELDS(._ChartIndex).ShowValuesOnShape
				RETURN
			ENDIF
		
			m.lcLegend = ''
			LOCAL lcExpr, lnAlign, lnDirection
			lcExpr = .ShapeLegendExpression
		
			IF (VARTYPE(lcExpr) = "C") AND (NOT EMPTY(lcExpr))
				.ShapeLegend._Value = EVALUATE(lcExpr)
			ELSE
		
				IF ._SumRow AND .ShowPercentages
		* Show percentages as values
					DO CASE
						CASE EMPTY(.ShapeLegend.FORMAT) AND EMPTY(.ShapeLegendExpression)
							.ShapeLegend._ForceFormat = ;
								._GetFieldType(.SourceAlias, EVALUATE(".Fields(.ChartRow).FieldValue"), .T.) + "%"
						CASE NOT "%" $ .ShapeLegend.FORMAT
							.ShapeLegend._ForceFormat = .ShapeLegend.FORMAT + "%"
					ENDCASE
					LOCAL lnValue
					lnValue = ROUND(m.tnValue / .ChartSum * 100,0)
					.ShapeLegend._Value = lnValue
				ELSE
					.ShapeLegend._Value = tnValue
				ENDIF
			ENDIF
			lnDecimals = SET("Decimals")
			SET DECIMALS TO .ShowDecimals
			lcValue = IIF(VARTYPE(.ShapeLegend._Value)='N',	;
				TRANSFORM(.ShapeLegend._Value,[999 999 999 999]+IIF(.ShowDecimals>0,[.]+REPLICATE([9],.ShowDecimals),'')),	;
				.ShapeLegend._Value)
			.ShapeLegend._Value = IIF(EMPTY(m.lcLegend),'', m.lcLegend + CHR(13)+CHR(10)) + IIF(.ShowValue,ALLTRIM(lcValue),'')
			IF VARTYPE(loShapeObject)='O'
				loShapeObject.CAPTION=.ShapeLegend._Value
			ENDIF
			SET DECIMALS TO lnDecimals
			IF NOT .ShowValuesOnShapes OR EMPTY(.ShapeLegend._Value)
				RETURN
			ENDIF
			lnAlign = .ShapeLegend.ALIGNMENT
		
		*!*		IF ._InvertShapeLegendAlignment = .T.
		*!*			DO CASE
		*!*			CASE lnAlign = 0 && Left
		*!*				lnAlign = 1 && Right
		
		*!*			CASE lnAlign = 1 && Right
		*!*				lnAlign = 0 && Left
		
		*!*			OTHERWISE
		
		*!*			ENDCASE
		*!*		ENDIF
		
		
			lnDirection = IIF(EMPTY(.ShapeLegend.ROTATION),.BarLegendDirection,0)
			IF lnDirection = 0 && Horizontal
		* Draw the Values inside the shapes
		
				IF ._Orientation = 1 && Vertical
		*!*				IF (tnHeight < .ShapeLegend._Height) AND (NOT ._Stacked)
		*!*					LOCAL y0
		*!*					y0 = .ChartCanvas.HEIGHT - ._XAxisHeight + 1
		*!*					tnY = y0 - .ShapeLegend._Height
		*!*				ENDIF
					DO CASE
						CASE .ShapeLegendVertAlignment=2
							tnY=tnY+tnHeight/2 - .ShapeLegend._Height/2
						CASE .ShapeLegendVertAlignment=1
							tnY=tnY+tnHeight -  .ShapeLegend._Height
					ENDCASE
		
					DO CASE
		
						CASE .ShapeLegend.ROTATION # 0 AND .BarLegendType = 1
							tnY = tnY - .ShapeLegend._Height - 2
							loShape = .ShapeLegend._DrawString(tnX + tnWidth / 2, tnY)
		
						CASE lnAlign = 0 && Left
							loShape = .ShapeLegend._DrawString(tnX, tnY)
		
						CASE lnAlign = 1 && Right
							loShape = .ShapeLegend._DrawString(tnX + tnWidth, tnY)
		
						CASE lnAlign = 2 && Center
							x1=tnX + tnWidth / 2
							loShape = .ShapeLegend._DrawString(x1, tnY)
		
						OTHERWISE
		
					ENDCASE
		
		
				ELSE && ._Orientation = 2 && Horizontal
					DO CASE
						CASE lnAlign = 2 && Center
							IF .ShapeLegend._Width > tnWidth && force left
								.ShapeLegend.ALIGNMENT = 0
								loShape = .ShapeLegend._DrawString(tnX, tnY)
								.ShapeLegend.ALIGNMENT = 2
							ELSE
								loShape = .ShapeLegend._DrawString(tnX + tnWidth / 2, tnY)
							ENDIF
		
		
		
						CASE lnAlign = 0 AND tnValue >= 0 && Left
							loShape = .ShapeLegend._DrawString(tnX, tnY)
		
						CASE lnAlign = 1 AND tnValue >= 0 && Right
							IF .ShapeLegend._Width > tnWidth && force left
								.ShapeLegend.ALIGNMENT = 0
								loShape = .ShapeLegend._DrawString(tnX, tnY)
								.ShapeLegend.ALIGNMENT = 1
							ELSE
								loShape = .ShapeLegend._DrawString(tnX + tnWidth, tnY)
							ENDIF
		
						CASE lnAlign = 1 AND tnValue < 0 && Force Left
							.ShapeLegend.ALIGNMENT = 0
							loShape = .ShapeLegend._DrawString(tnX, tnY)
							.ShapeLegend.ALIGNMENT = 1
		
						CASE lnAlign = 0 AND tnValue < 0 && Force Right
							.ShapeLegend.ALIGNMENT = 1
							loShape = .ShapeLegend._DrawString(tnX + tnWidth, tnY)
							.ShapeLegend.ALIGNMENT = 0
		
						OTHERWISE
					ENDCASE
		
				ENDIF
		
			ELSE && BarLegendDirection = 1 && Vertical
		
				IF lnDirection = 2 && Invert Direction
					LOCAL lnRotCenter
					lnRotCenter = .ShapeLegend.RotationCenter
					.ShapeLegend.RotationCenter = lnRotCenter + 180
				ENDIF
				IF tnValue >= 0 OR lnAlign = 2
					loShape = .ShapeLegend._DrawString(tnX, tnY, tnWidth, tnHeight, .T.)
				ELSE
					IF lnAlign = 0
						.ShapeLegend.ALIGNMENT = 1
					ELSE
						.ShapeLegend.ALIGNMENT = 0
					ENDIF
					loShape = .ShapeLegend._DrawString(tnX, tnY, tnWidth, tnHeight, .T.)
					.ShapeLegend.ALIGNMENT = lnAlign
				ENDIF
		
		
				IF lnDirection = 2 && Invert Direction
					.ShapeLegend.RotationCenter = lnRotCenter
				ENDIF
		
			ENDIF
			loShape.CAPTION=.ShapeLegend._Value
		ENDWITH
		
	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
		LPARAMETERS toShape
		LOCAL lcCursor, ln3D, lnDetachAngle, lnDetachPixels, lnHeight, lnMaxHeight, lnMaxWidth, lnNativeValue, ;
			lnStart, lnSweep, lnTempStart, lnTempSweep, lnTotal, lnValue, lnWidth, lnX, lnX1, lnY, lnY1, lnRow, loShape
		
		lnRow = IIF(TYPE('toShape.CurrentRow')='N', toShape.CurrentRow, 0)
		WITH THIS
			SELECT ( ._DataCursor )
			lnLines = RECCOUNT()
		
		
			m.lnDetachPixels = .PieDetachPixels
		
			m.lnMaxWidth = .ChartCanvas.WIDTH - ._LeftOffset - ._RightOffset - (lnDetachPixels * 2)
			m.lnMaxHeight = .ChartCanvas.HEIGHT - (.MARGIN * 2) - .MarginBottom - ;
				.MarginTop - ._TitleHeight - ._3d - ;
				(lnDetachPixels * 2) - ;
				._LegendHeight
		
			m.lnMaxHeight = .ChartCanvas.HEIGHT-(.MARGIN * 2)-.MarginBottom-.MarginTop-._TitleHeight-._3d- ;
				(lnDetachPixels*2)-._LegendHeight
		
			m.lnWidth = MIN(lnMaxWidth, lnMaxHeight)
			m.lnHeight = m.lnWidth
		
		
			IF NOT .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 = ._3d
		
			IF .PieCompensateAngles
				m.lnWidth = m.lnMaxWidth
			ENDIF
			IF m.lnWidth <= 10 OR ;
					lnHeight <= 10 OR ;
					lnHeight <= ln3D
				RETURN
			ENDIF
		
		
		* Calculate the chart basic positions
			lnX = lnDetachPixels + .MARGIN + ._LeftOffset + ((lnMaxWidth - m.lnWidth) / 2)
			lnY = .MARGIN + ._TopOffSet + ((lnMaxHeight - m.lnHeight) / 2) + lnDetachPixels
		
			lnTotal = .ChartSum
		
		
			IF NOT .PieEnhancedDrawing && Draws without taking care of slices edges
		* Prepare the Gdi+ objects
				WITH _SCREEN.SYSTEM.Drawing
					PRIVATE poTempBmp AS xfcBitmap, poClrMatrix AS xfcColorMatrix
					poTempBmp = .BITMAP.New(m.lnWidth + m.ln3D + 2, m.lnHeight + m.ln3D + 2)
					poClrMatrix = .Imaging.ColorMatrix.New()
					poClrMatrix.Matrix33 = .AlphaChannel / 255
				ENDWITH
			ENDIF
		
		
		
			LOCAL laLegends(lnLines + 1, 3), lnRec, llHidden, llDrawLegend, lnPixelsOut
			llDrawLegend = .ShowValuesonShapes
			lnRec = 1
		
			._ChartIndex = .ChartRow
			._Pie1stDetached = .F.
		
			IF .PieDirection = 1 && Anticlockwise
				SET ORDER TO REVERT
			ENDIF
		
		
		* Draw the pie
		* Draw the RIGHT side of the pie
			lnStart = 270
		
			.COLUMN = IIF(BETWEEN(._ChartIndex, 1, .ChartsCount), ._ChartIndex,1)
			FOR .ROW = 1 TO RECCOUNT()
				IF lnStart >=450
					EXIT
				ENDIF
				.GetValue()
		*SCAN FOR lnStart < 450
				lnX1 = lnX
				lnY1 = lnY
		
		* Calculate Start point and Sweep
				lnNativeValue = .VALUE
				lnValue = ABS(lnNativeValue)
				IF lnValue <= 0
					LOOP
				ENDIF
		
				lnSweep = lnValue / lnTotal * 360
				IF lnSweep > 359.99
					lnSweep = 359.99
				ENDIF
		
				llHidden = lSliceHidden OR (NOT EMPTY(lnRow) AND lnRow#.ROW)
				IF lDetach
					IF lnRec = 1
						._Pie1stDetached = .T.
						._PieX0 = lnX1
						._PieY0 = lnY1
					ENDIF
		
					IF VARTYPE(._PieAnimatedRec) ='N' AND .ROW = ._PieAnimatedRec
						lnPixelsOut = ._PieAnimationPix
					ELSE
						lnPixelsOut = lnDetachPixels
					ENDIF
		
					lnTempStart = lnStart
					lnTempSweep = lnSweep
					._AdjustStartSweep(@lnTempStart, @lnTempSweep, m.lnWidth, m.lnHeight)
					lnDetachAngle = 360 - (lnTempStart + (lnTempSweep / 2))
					lnX1 = lnX + (COS(DTOR(lnDetachAngle)) * lnPixelsOut)
					lnY1 = lnY - (SIN(DTOR(lnDetachAngle)) * lnPixelsOut)
				ELSE
					lnX1 = lnX
					lnY1 = lnY
				ENDIF
		
				IF lnStart + lnSweep > 450
					EXIT
				ENDIF
		
		
				loShape = IIF(lnRow>0,toShape, ._UpdateCoordinates(,"Pie",0,0,0,0,0,,,,,lnRec))
				IF NOT llHidden
					IF .ChartType = 1 && Pie
						._DrawSlice(lnX1, lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue,loShape)
					ELSE && 2 - Doughnut
						._DrawDoughnutSlice(lnX1, lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue,loShape)
					ENDIF
					IF llDrawLegend
						._PrepareLegendinSlice(@lnX1, @lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue)
						laLegends(lnRec,1) = lnX1
						laLegends(lnRec,2) = lnY1
						laLegends(lnRec,3) = lnNativeValue
						lnRec = lnRec + 1
					ENDIF
				ENDIF
				lnStart = lnStart + lnSweep
		
			NEXT
		
		* Draw the LEFT side of the pie
			.ROW = RECCOUNT()
			lnStart = 270
			DO WHILE lnStart >= 90
				IF lnStart < 90
					EXIT
				ENDIF
				.GetValue()
		
		* Calculate Start point and Sweep
				IF .VALUE = 0
					IF .ROW = 1
						EXIT
					ENDIF
					.ROW = .ROW -1
					LOOP
				ENDIF
				lnX1 = lnX
				lnY1 = lnY
				lnNativeValue = .VALUE
				lnValue = ABS(lnNativeValue)
		
				lnSweep = lnValue / lnTotal * 360
				IF lnSweep > 359.99
					lnSweep = 359.99
				ENDIF
		
				lnStart = lnStart - lnSweep
				llHidden = lSliceHidden OR (NOT EMPTY(lnRow) AND lnRow # .ROW)
		
				IF lDetach
					lnTempStart = lnStart
					lnTempSweep = lnSweep
		
					IF lnStart + lnSweep >= 269.9
						._Pie1stDetached = .T.
						._PieX0 = lnX1
						._PieY0 = lnY1
					ENDIF
		
		
					IF VARTYPE(._PieAnimatedRec) ='N' AND .ROW = ._PieAnimatedRec
						lnPixelsOut = ._PieAnimationPix
					ELSE
						lnPixelsOut = lnDetachPixels
					ENDIF
		
					._AdjustStartSweep(@lnTempStart, @lnTempSweep, m.lnWidth, m.lnHeight)
					lnDetachAngle = 360 - (lnTempStart + (lnTempSweep / 2))
					lnX1 = lnX + (COS(DTOR(lnDetachAngle)) * lnPixelsOut)
					lnY1 = lnY - (SIN(DTOR(lnDetachAngle)) * lnPixelsOut)
				ENDIF
		
				loShape = IIF(lnRow>0,toShape, ._UpdateCoordinates(,"Pie",0,0,0,0,0,,,,,lnRec))
				IF NOT llHidden
					IF .ChartType = 1 && Pie
						._DrawSlice(lnX1, lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue,loShape)
					ELSE && 2 - Doughnut
						._DrawDoughnutSlice(lnX1, lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue,loShape)
					ENDIF
		
					IF llDrawLegend
						._PrepareLegendinSlice(@lnX1, @lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue)
						laLegends(lnRec,1) = lnX1
						laLegends(lnRec,2) = lnY1
						laLegends(lnRec,3) = lnNativeValue
						lnRec = lnRec + 1
					ENDIF
		
				ENDIF
				IF .ROW=1
					EXIT
				ENDIF
				.ROW = .ROW - 1
			ENDDO
		* Draw the legends at the end of the process in order to avoid
		*   a slice hiding a legend
		
		
			IF TYPE('.FIELDS(._ChartIndex).ShowValuesOnShape') # 'L' OR .FIELDS(._ChartIndex).ShowValuesOnShape
		
				IF llDrawLegend
					LOCAL lnOrigAlign, N
					lnOrigAlign = .ShapeLegend.ALIGNMENT
					.ShapeLegend.ALIGNMENT = 2 && Force Center
		
		lc=''
					FOR N = 1 TO lnRec - 1
		
						LOCAL lcExpr
						lcExpr = .ShapeLegendExpression
						IF VARTYPE(lcExpr) = "C" AND NOT EMPTY(lcExpr)
		*!*	Other available properties
		*!*		.CurrValue
		*!*		.CurrLegend
		*!*		.CurrObjType
		*!*		.CurrRecno
		*!*		.CurrColumn
							.CurrIndex = N
							lnValue = EVALUATE(lcExpr)
						ELSE
		
							IF .PieShowPercent
								DO CASE
									CASE EMPTY(.ShapeLegend.FORMAT) AND EMPTY(lcExpr)
										.ShapeLegend._ForceFormat = ;
											._GetFieldType(._DataCursor, 'nValue'+ALLTRIM(STR(.ChartRow)), .T.) + "%"
		
									CASE NOT "%" $ .ShapeLegend.FORMAT
										.ShapeLegend._ForceFormat = .ShapeLegend.FORMAT + "%"
		
								ENDCASE
		
								lnValue = (laLegends(N,3) / lnTotal) * 100
							ELSE
								lnValue = laLegends(N,3)
							ENDIF
		
						ENDIF
		
						.ShapeLegend._Value = lnValue
		TEXT TO lc addi
		<<.CurrLegend>> (<<.CurrIndex>>) : <<INT(laLegends(N,1))>>,  <<INT(laLegends(N,2))>>,  <<INT(laLegends(N,3))>>   <<N>>
		
		endtext
						lnX1 = laLegends(N,1)
						IF VARTYPE(lnX1) <> "N"
							EXIT
						ENDIF
		
						lnY1 = laLegends(N,2)
		
		* Draw the Text
		
						.ShapeLegend._DrawString( lnX1, lnY1,,,,,loShape)
		
					NEXT
					.ShapeLegend._ForceFormat = ""
					.ShapeLegend.ALIGNMENT = lnOrigAlign
				ENDIF
			ENDIF
		
			IF .PieDirection = 1 && Anticlockwise
				SET ORDER TO
			ENDIF
		ENDWITH
		
	ENDPROC

	PROCEDURE _drawpyramid
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D
		* Yudin Alex 21 May 2013
		LOCAL lcFront, lcPoints, 	;
			llLeftRight, ln3D, lnAlpha, lnOrigAlpha, lnStore, lnTopX, lnTopY, 	;
			loBotBrush, loGfx, loPen
		m.tnHeight = ABS(m.tnHeight)
		m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1)
		m.loGfx = THIS.oGfx
		
		lnOrigAlpha = THIS.AlphaChannel
		lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25))
		THIS.AlphaChannel = lnAlpha
		THIS._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(THIS.SingleData, RECNO(),THIS._ChartIndex))
		
		
		WITH _SCREEN.SYSTEM.Drawing
		
			DO CASE
		
				CASE THIS.BrushType = 1 && SolidColors
					loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
		
				CASE THIS.BrushType = 2 && Gradient
					loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80)))
		
				OTHERWISE
					THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex))
					loBotBrush = THIS._oMainBrush
			ENDCASE
		
			m.loPen   = THIS._oBorderPen
			THIS.AlphaChannel = lnOrigAlpha
		
			STORE '' TO lcPoints, lcFront
		
		
		
			LOCAL laPoints(4)
		
		* Draw the 3D Bar using the 3DBrush
			IF THIS._Orientation = 1 && Vertical
		
		* Points for 3D pyramid parts
		* Bottom
				m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight)
				m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D + m.tnHeight)
				m.laPoints(3) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D + m.tnHeight)
				m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight)
		
				m.loGfx.FillPolygon(m.loBotBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		
		* Left wall
				LOCAL laPoints(3)
				m.laPoints(1) = .PointF.New(m.tnX, m.tnY + m.tnHeight)
				m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D + m.tnHeight)
				m.laPoints(3) = .PointF.New(m.tnX + m.tnWidth/2 + m.ln3D/2, m.tnY - m.ln3D/2)
		
				m.loGfx.FillPolygon(THIS._o3DBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		
		* Front wall
		
				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.loGfx.FillPolygon(THIS._oMainBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
				m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight)
				m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D + m.tnHeight)
		
				m.loGfx.FillPolygon(THIS._oRightbrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
				TEXT TO lcPoints
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth/2 + m.ln3D/2,0)>>,<<ROUND(m.tnY - m.ln3D/2,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
				ENDTEXT
				TEXT TO lcFront
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX + m.tnWidth/2 + m.ln3D/2,0)>>,<<ROUND(m.tnY - m.ln3D/2,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
				ENDTEXT
		
			ELSE
		*Horizont
				llLeftRight = THIS.Charttype # 17 AND THIS._ChartIndex>1
				lnTopX = m.tnX + m.tnWidth + m.ln3D/2 * IIF(llLeftRight,1,0)
				lnTopY = m.tnY + m.tnHeight/2 - m.ln3D/2
				IF THIS.Charttype = 17 AND THIS._ChartIndex=1
					m.lnStore=m.lnTopX
					m.lnTopX = m.tnX
					m.tnX=m.lnStore
				ENDIF
		* Bottom
				m.laPoints(1) = .PointF.New(m.tnX, m.tnY)
				m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D)
				m.laPoints(3) = .PointF.New(m.tnX+ m.ln3D, m.tnY + m.tnHeight - m.ln3D)
				m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight)
		
				m.loGfx.FillPolygon(m.loBotBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		* Walls
				LOCAL laPoints(3)
				m.laPoints(1) = .PointF.New(m.tnX, m.tnY)
				m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D)
				m.laPoints(3) = .PointF.New(lnTopX, lnTopY)
		
				m.loGfx.FillPolygon(THIS._o3DBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		
				m.laPoints(1) = .PointF.New(m.tnX, m.tnY)
				m.laPoints(2) = .PointF.New(m.tnX , m.tnY + m.tnHeight)
				m.laPoints(3) = .PointF.New(lnTopX, lnTopY)
		
				m.loGfx.FillPolygon(THIS._oMainBrush, @laPoints)
				m.loGfx.DrawPolygon(m.loPen, @laPoints)
		
				TEXT TO lcPoints
		<<ROUND(m.tnX ,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY,0)>>
		<<ROUND(m.tnX + m.ln3D,0)>>,<<ROUND(m.tnY - m.ln3D,0)>>
		<<ROUND(m.lnTopX,0)>>,<<ROUND(m.lnTopY,0)>>
		<<ROUND(m.tnX ,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
				ENDTEXT
				TEXT TO lcFront
		<<ROUND(m.tnX ,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
		<<ROUND(m.tnX,0)>>,<<ROUND(m.tnY,0)>>
		<<ROUND(m.lnTopX,0)>>,<<ROUND(m.lnTopY,0)>>
		<<ROUND(m.tnX ,0)>>,<<ROUND(m.tnY + m.tnHeight,0)>>
				ENDTEXT
				IF THIS.Charttype = 17 AND THIS._ChartIndex=1
					m.tnX=m.lnTopX
				ENDIF
		
			ENDIF
			loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints,,lcFront)
			THIS._DrawLegendinBar(tnX, tnY, tnWidth, tnHeight, tnValue)
		
		ENDWITH
		
	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
		
			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)
		
		****************************************************************
		*   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
		* Yudin: Escape zero divide
				m.lnScaleHeight = IIF(m.lnMaxValue=0,0,(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)
		
				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, luShape, tnBartype
		LOCAL lnX1, lnY1, loRect, luShape, lcType, lnIndex, lnTipPixels, lnColor, loGfx AS xfcGraphics, loObject AS OBJECT
		
		lnTipPixels = THIS._TipPixels
		lnIndex = THIS._ChartIndex
		tnBartype = EVL(tnBartype,0)
		IF EMPTY(tcObjType)
			tcObjType = "Rect"
		ENDIF
		IF THIS.BrushType = 3 && Monochrome
			lnColor = 0
		ELSE
			lnColor = EVL(THIS.aColors(lnIndex),0)
		ENDIF
		
		
		DO CASE
			CASE VARTYPE(luShape)='O'
		
			CASE NOT EMPTY(THIS.LineCapsShape)
				luShape = THIS.LineCapsShape
			OTHER
				luShape = THIS.FIELDS(lnIndex).SHAPE
		ENDCASE
		lcType  = VARTYPE(luShape)
		
		m.loGfx = THIS.oGfx
		
		DO CASE
		
			CASE lcType = "N" OR lcType = "O" && Graphics path using predefined Shape
		
				LOCAL loPath AS xfcGraphicsPath, lnWidth, lnHeight, loBrush AS xfcSolidBrush, loAdjPath AS xfcGraphicsPath, loMatrix AS xfcMatrix
		
				IF VARTYPE(THIS._aShapes(lnIndex, 1)) = "O"
					m.loPath    = THIS._aShapes(lnIndex, 1)
				ELSE
					IF lcType = "O"
						loPath = luShape.CLONE()
						THIS._CenterPath(loPath, .T.)
					ELSE
						loPath = THIS._GetShapePath(luShape)
						THIS._CenterPath(loPath, .T.)
					ENDIF
		
				ENDIF
		
				loRect = loPath.GetBounds()
				lnWidth = loRect.WIDTH
				lnHeight = loRect.HEIGHT
		
				loBrush = .SolidBrush.New(.COLOR.FromRGB(lnColor))
		
				loAdjPath = loPath.CLONE()
				loMatrix = _SCREEN.SYSTEM.Drawing.Drawing2D.Matrix.New()
				loMatrix.Translate(tnX, tnY)
				loAdjPath.TRANSFORM(loMatrix)
				THIS.FillPathDim(loBrush, loAdjPath)
		
		
				lnX1 = tnX - (m.lnWidth  / 2)
				lnY1 = tnY - (lnHeight / 2)
		
				loObject = loPath
		
		
			CASE lcType = "C" && Image File
		
				LOCAL loBmp AS xfcBitmap, lnWidth, lnHeight
		
				IF VARTYPE(THIS._aShapes(lnIndex, 1)) = "O"
					loBmp    = THIS._aShapes(lnIndex, 1)
					lnWidth  = THIS._aShapes(lnIndex, 2)
					lnHeight = THIS._aShapes(lnIndex, 3)
				ELSE
					loBmp = _SCREEN.SYSTEM.Drawing.BITMAP.FromVarbinary(FILETOSTR(luShape))
					lnWidth  = loBmp.WIDTH
					lnHeight = loBmp.HEIGHT
				ENDIF
		
				lnX1 = tnX - (m.lnWidth /2)
				lnY1 = tnY - (lnHeight /2)
		
				m.loGfx.DrawImage(loBmp, lnX1, lnY1)
		
				loObject = loBmp
		
			OTHERWISE
		
		ENDCASE
		
		* Fix by Anal Roy Chowdhurry
		IF NOT (THIS.LineCaps AND INLIST(This.ChartType, 5, 18)) AND tnBartype#7
			THIS._UpdateCoordinates(,tcObjType, lnX1, lnY1,	m.lnWidth, lnHeight, tnValue)
		ENDIF
		* End of Revision new checking
		
		
		THIS._aShapes(lnIndex, 1) = loObject
		THIS._aShapes(lnIndex, 2) = lnWidth
		THIS._aShapes(lnIndex, 3) = lnHeight
		
	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 lcCaption, llHorizontal, lnWidth, lnHeight, lnX1, lnY1,	;
			lnAvailableHeight, lnChart, lnCount, lnExternalMargin, lnLegendHeight, lnLength, lnMargin, lnNeededHeight, lnOrigAlignment, lnOrigIndex, lnPosition, lnStart, lnTopMargin, lnVertHeight
		
		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.
		
		
		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)
		IF this.ChartType=17
		m.lnCount = MIN(2,m.lnCount)
		ENDIF
		
		m.lnTopMargin = THIS.MarginTop + THIS.MARGIN + THIS._TitleHeight
		
		WITH _SCREEN.SYSTEM.Drawing
		* 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.lnX1 = THIS.MARGIN + THIS.MarginLeft + m.lnExternalMargin
					m.lnY1 = m.lnTopMargin
		
				CASE m.lnPosition = 2 && Vertical Bottom Left Side
					m.lnX1 = THIS.MARGIN + THIS.MarginLeft + m.lnExternalMargin
					m.lnY1 = THIS.ChartCanvas.HEIGHT - THIS.MarginBottom - THIS.MARGIN - m.lnVertHeight
		
				CASE m.lnPosition = 11 && Vertical Center Left Side
					m.lnX1 = THIS.MARGIN + THIS.MarginLeft + m.lnExternalMargin
					m.lnY1 = (THIS.ChartCanvas.HEIGHT - THIS.MarginBottom - m.lnTopMargin - m.lnVertHeight) / 2 + m.lnTopMargin
		
		
		
				CASE m.lnPosition = 3 && Vertical Top Right Side (Default)
					m.lnX1 = THIS.ChartCanvas.WIDTH - THIS._RightOffset + m.lnExternalMargin + THIS._Axis2ScaleWidth
					m.lnY1 = m.lnTopMargin
		
				CASE m.lnPosition = 4 && Vertical Bottom Right Side (Default)
					m.lnX1 = THIS.ChartCanvas.WIDTH - THIS._RightOffset + m.lnExternalMargin + THIS._Axis2ScaleWidth
					m.lnY1 = THIS.ChartCanvas.HEIGHT - THIS.MarginBottom - THIS.MARGIN - m.lnVertHeight
		
				CASE m.lnPosition = 12 && Vertical Center Right Side
					m.lnX1 = THIS.ChartCanvas.WIDTH - THIS._RightOffset + m.lnExternalMargin + THIS._Axis2ScaleWidth
					m.lnY1 = (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
					STORE 0 TO m.lnLength, m.lnStart
		
		* Obtain the needed width for the whole horizontal legend
					FOR m.lnChart = 1 TO m.lnCount
						THIS.SideLegend.CAPTION = THIS._aSideLegends(m.lnChart,1)
						m.lnLength = m.lnLength + m.lnWidth + 10 + THIS.SideLegend._Width
					NEXT
		
		
					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.lnX1 = THIS._LeftOffset + m.lnStart
		
					IF INLIST(m.lnPosition , 5, 6, 7) && Horizontal Top
						m.lnY1 = m.lnTopMargin + m.lnExternalMargin
					ELSE && Horizontal Bottom
						m.lnY1 = THIS.ChartCanvas.HEIGHT - THIS._LegendHeight - THIS.MARGIN - THIS.MarginBottom + THIS._LegendExternalMargin
					ENDIF
			ENDCASE
		
		
			LOCAL loLinePen AS xfcPen
		
		* Save the current _CharIndex
			m.lnOrigIndex = THIS._ChartIndex
		
			FOR m.lnChart = 1 TO m.lnCount
				IF m.lnY1 <= 0
					EXIT
				ENDIF
		
				THIS._ChartIndex = m.lnChart
		
				m.lcCaption = THIS._aSideLegends(m.lnChart,1)
				IF EMPTY(m.lcCaption)
					LOOP
				ENDIF
		
				THIS.SideLegend.CAPTION = m.lcCaption
				THIS.SideLegend._DrawString(m.lnX1 + m.lnWidth + 3, m.lnY1)
		
				THIS._UpdateCoordinates(,"Legend", m.lnX1, m.lnY1, m.lnWidth + THIS.SideLegend._Width + 5, m.lnLegendHeight, m.lnChart, 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 = .PEN.New(THIS._oClrBlack, 3)
						m.loLinePen.DashStyle = m.lnChart - 1 && _Screen.System.Drawing.Drawing2D.DashStyle.Dash
						THIS.oGfx.DrawLine(m.loLinePen, m.lnX1, m.lnY1 + m.lnHeight / 2, m.lnX1 + m.lnWidth, m.lnY1 + m.lnHeight / 2)
		
					CASE (THIS.ChartType = 4 ; && Point
						OR (INLIST(THIS.ChartType, 5, 18) AND THIS._3D = 0 AND THIS.LineCaps)) ; && Plain line
						AND NOT THIS.Multichart
						LOCAL loPath AS xfcGraphicsPath
						m.loPath = THIS._aShapes(m.lnChart,1)
		
						IF VARTYPE(m.loPath) <> "O"
							RETURN
						ENDIF
		
						IF INLIST(LOWER(m.loPath.CLASS),"xfcbitmap", "xfcimage")
							THIS.oGfx.DrawImage(m.loPath, m.lnX1, m.lnY1, m.lnWidth, m.lnHeight)
						ELSE
		
							THIS._DrawShape(m.lnX1 + m.lnWidth / 2, m.lnY1 + m.lnHeight / 2, 0, "Legend")
							IF THIS._aShapes(m.lnChart,3) > m.lnLegendHeight
								m.lnLegendHeight = THIS._aShapes(m.lnChart,3) + 1
		*					m.lnY1 = m.lnY1 + This._aShapes(m.lnChart,3) + 3
							ENDIF
						ENDIF
		
					OTHERWISE
		
						THIS._PrepareBrushes(m.lnX1, m.lnY1, m.lnWidth, m.lnHeight, .T., m.lnChart, .T.)	&& 7-th parameter. Avoid GradientShapeDirection>2. Yudin
						THIS.oGfx.FillRectangle(THIS._oMainBrush, m.lnX1, m.lnY1, m.lnWidth, m.lnHeight)
						THIS.oGfx.DrawRectangle(THIS._oBorderPen, m.lnX1, m.lnY1, m.lnWidth, m.lnHeight)
		
				ENDCASE
		
				IF m.llHorizontal && Horizontal side legends
					m.lnX1 = m.lnX1 + m.lnWidth + 10 + THIS.SideLegend._Width
				ELSE
					m.lnY1 = m.lnY1 + m.lnLegendHeight
				ENDIF
		
			NEXT
		
		* Restore the current _CharIndex
			THIS._ChartIndex = m.lnOrigIndex
		
		ENDWITH
		
		WITH THIS.SideLegend
			.TOP    = m.lnTopMargin
			.LEFT   = m.lnX1
			.WIDTH  = THIS._LegendWidth
			.HEIGHT = MAX(0, m.lnY1 - m.lnTopMargin)
		* Restore the alignment value to the original
			.ALIGNMENT = m.lnOrigAlignment
		ENDWITH
		
		THIS._InLegend = .F.
		
	ENDPROC

	PROCEDURE _drawslice
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnStart, tnSweep, tnNativeValue, toShape
		LOCAL llAdjLeft, llAdjRight, ln3D, lnFinalAngle, lnXBrush, lnYBrush
		IF m.tnWidth <=0 OR m.tnHeight <=0
			RETURN
		ENDIF
		WITH THIS
		
			LOCAL loPen AS xfcPen, loGfx AS xfcGraphics, loMainBrush AS xfcBrush, lo3dBrush AS xfcBrush
		
			._AdjustStartSweep(@tnStart, @tnSweep, m.tnWidth, m.tnHeight)
			toShape = ._UpdateCoordinates(toShape, "Pie", m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnNativeValue, m.tnStart, m.tnSweep)
			lcShapeName = TRANSFORM(toShape.CoordNum)
		
			IF .PieEnhancedDrawing
				lnXBrush = m.tnX
				lnYBrush = m.tnY
			ELSE
				lnXBrush = 0
				lnYBrush = 0
			ENDIF
			._PrepareBrushes(lnXBrush, lnYBrush, m.tnWidth, m.tnHeight, .F., RECNO())
		
		
			m.loPen = ._oBorderPen
			m.loGfx = .oGfx
			m.loMainBrush = ._oMainBrush
			lo3dBrush = ._o3DBrush
		
		
			lnFinalAngle = m.tnStart + m.tnSweep
			IF lnFinalAngle > 360
				lnFinalAngle = lnFinalAngle - 360
			ENDIF
			m.ln3D = ._3D
		ENDWITH
		
		
		WITH _SCREEN.SYSTEM.Drawing
		
			IF THIS.PieEnhancedDrawing
		
		* Draw the 3D Slice using the GraphicsPath class
				IF ln3D > 0 AND NOT THIS.SHADOW
		
					x = m.tnX
					Y = m.tnY
					w = m.tnWidth
					h = m.tnHeight
		
		
		* Draw the bottom slice
					m.loGfx.FillPie(m.loMainBrush, x, Y + m.ln3D, w, h, m.tnStart, m.tnSweep)
					m.loGfx.DrawPie(m.loPen, x, Y, w, h, m.tnStart, m.tnSweep)
		
		
		* Get the start point
					LOCAL loPath AS xfcGraphicsPath, loPoint1 AS xfcPoint, loPoint2 AS xfcPoint
					loPath = _SCREEN.SYSTEM.Drawing.Drawing2D.GraPHICSPATH.New()
					loPath.AddPie(x,Y,w,h, m.tnStart, 0.0001)
					loPoint1 = loPath.GetLastpoint()
		
					loPath.AddPie(x,Y,w,h, m.tnStart, m.tnSweep)
					loPoint2 = loPath.GetLastpoint()
		
		
		* Draw side Polygon 1
					LOCAL laPointsA(4), laPointsB(4), lnCenterX, lnCenterY
					lnCenterX = x + (w/2)
					lnCenterY = Y + (h/2)
		
					laPointsA(1) = .POINT.New(lnCenterX, lnCenterY)
					laPointsA(2) = .POINT.New(lnCenterX, lnCenterY + m.ln3D)
					laPointsA(3) = .POINT.New(loPoint1.x, loPoint1.Y + m.ln3D)
					laPointsA(4) = loPoint1
		
		
		
		* Draw side Polygon 2
					laPointsB(1) = laPointsA(1)
					laPointsB(2) = laPointsA(2)
					laPointsB(3) = .POINT.New(loPoint2.x, loPoint2.Y + m.ln3D)
					laPointsB(4) = loPoint2
		
		
					IF m.tnStart <= 90 OR m.tnStart > 270
						m.loGfx.DrawPolygon(m.loPen, @laPointsA)
						m.loGfx.FillPolygon(lo3dBrush, @laPointsA)
					ENDIF
		
		
					IF lnFinalAngle < 270 AND lnFinalAngle > 90
						m.loGfx.FillPolygon(lo3dBrush, @laPointsB)
						m.loGfx.DrawPolygon(m.loPen, @laPointsB)
					ENDIF
		
		
		* Draw the external 3d Face
					LOCAL loPath2 AS xfcGraphicsPath
					loPath2 = _SCREEN.SYSTEM.Drawing.Drawing2D.GraPHICSPATH.New()
					loPath2.FillMode = _SCREEN.SYSTEM.Drawing.Drawing2D.FillMode.winding
		
		
					loPath2.StartFigure()
		
					LOCAL lnAdjStart, lnAdjSweep
					lnAdjStart = m.tnStart
					lnAdjSweep = m.tnSweep
		
		
					IF m.tnStart >= 270 AND ;
							m.tnStart < 360 AND ;
							BETWEEN(lnFinalAngle, 0, 270)
		
						llAdjRight = .T.
		
		* Create a new partial path for the 1st part
						LOCAL loPath3 AS xfcGraphicsPath
						loPath3 = _SCREEN.SYSTEM.Drawing.Drawing2D.GraPHICSPATH.New()
						loPath3.StartFigure()
		
		
						loPath3.AddArc(x,Y,w,h, m.tnStart, 360 - m.tnStart)
						loPath3.Reverse()
						loPath3.ADDLINE(loPoint1.x, loPoint1.Y, loPoint1.x, loPoint1.Y + m.ln3D)
						loPath3.AddArc(x,Y + m.ln3D, w, h, m.tnStart, 360 - m.tnStart)
						loPath3.ADDLINE(m.tnX + m.tnWidth, lnCenterY + m.ln3D, m.tnX + m.tnWidth, lnCenterY)
						THIS.FillPathDim(lo3dBrush, loPath3)
						m.loGfx.DrawPath(m.loPen, loPath3)
		
						loPoint1 = .POINT.New(m.tnX + m.tnWidth, lnCenterY)
						lnAdjStart = 0
		
						lnAdjSweep = m.tnSweep - (360 - m.tnStart)
					ENDIF
		
		
		
					IF (m.tnStart < 180 AND lnFinalAngle > 180) OR ;
							(m.tnStart >= 270 AND lnFinalAngle > 180 AND lnFinalAngle < 270.01)
		
		
		*			IF (m.tnStart < 180 AND lnFinalAngle > 180) OR ;
		(m.tnStart >= 270 AND lnFinalAngle > 180 AND lnFinalAngle < 269.9999)
		
						llAdjLeft = .T.
		
		* Create a new partial path for the 1st part
						LOCAL loPath4 AS xfcGraphicsPath
						loPath4 = _SCREEN.SYSTEM.Drawing.Drawing2D.GraPHICSPATH.New()
						loPath4.StartFigure()
		
						IF m.tnStart >= 270
							lnAdjStart = 0
							lnAdjSweep = 180
						ELSE
							lnAdjStart = m.tnStart
							lnAdjSweep = 180 - m.tnStart
						ENDIF
		
		
						loPath4.AddArc(x,Y,w,h, lnAdjStart, lnAdjSweep)
		
		
						loPath4.Reverse()
						loPath4.ADDLINE(loPoint1.x, loPoint1.Y, loPoint1.x, loPoint1.Y + m.ln3D)
		
						loPath4.AddArc(x,Y + m.ln3D, w, h, lnAdjStart, lnAdjSweep)
						loPath4.ADDLINE(m.tnX, lnCenterY + m.ln3D, m.tnX, lnCenterY)
		
						THIS.FillPathDim(lo3dBrush, loPath4)
						m.loGfx.DrawPath(m.loPen, loPath4)
		
						loPoint1 = .POINT.New(m.tnX, lnCenterY)
		
						lnAdjStart = 180
						lnAdjSweep = lnFinalAngle - 180
		
		
					ENDIF
		
		
		
		
					loPath2.AddArc(x,Y,w,h, lnAdjStart, lnAdjSweep)
					loPath2.Reverse()
					loPath2.ADDLINE(loPoint1.x, loPoint1.Y, loPoint1.x, loPoint1.Y + m.ln3D)
					loPath2.AddArc(x,Y + m.ln3D, w, h, lnAdjStart, lnAdjSweep)
					loPath2.ADDLINE(loPoint2.x, loPoint2.Y + m.ln3D, loPoint2.x, loPoint2.Y)
					THIS.FillPathDim(lo3dBrush, loPath2)
					m.loGfx.DrawPath(m.loPen, loPath2)
		
		
					IF m.tnStart > 90 AND m.tnStart < 270
						m.loGfx.DrawPolygon(m.loPen, @laPointsA)
						m.loGfx.FillPolygon(lo3dBrush, @laPointsA)
					ENDIF
		
					IF lnFinalAngle > 270 OR lnFinalAngle <= 90
						m.loGfx.FillPolygon(lo3dBrush, @laPointsB)
						m.loGfx.DrawPolygon(m.loPen, @laPointsB)
					ENDIF
		
		* Draw the top slice
					m.loGfx.FillPie(m.loMainBrush, x, Y, w, h, m.tnStart, m.tnSweep)
					m.loGfx.DrawPie(m.loPen, x, Y, w, 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(loShadowBrush, m.tnX, m.tnY + 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
				loBmp = poTempBmp
		
				LOCAL loTempGfx AS xfcGraphics
				loTempGfx = .Graphics.FromImage(loBmp)
				loTempGfx.CLEAR(.COLOR.Transparent)
				loTempGfx.SmoothingMode = .Drawing2D.SmoothingMode.AntiAlias
		
		
		* Draw the 3D Slice using the Hatch Brush
				IF ln3D > 0
		
					LOCAL lnY1, N
					lnY1 = m.ln3D
		
		* Draw the contour of the 3D Slice
					loTempGfx.FillPie(m.loMainBrush, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
					loTempGfx.DrawPie(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
		
		
					FOR N = 1 TO m.ln3D
						lnY1 = lnY1 - 1
		* Draw the Normal Slice using the Solid Brush
						loTempGfx.FillPie(lo3dBrush, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) && draw the slice
						IF m.tnStart > 90
							loTempGfx.DrawArc(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, 0.25)
						ENDIF
						loTempGfx.DrawArc(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart + m.tnSweep - .25, 0.35)
					NEXT
					loTempGfx.FillPie(m.loMainBrush, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) && draw the slice
		
		
		* Draw border line from center of pie
					LOCAL lnX, lnY
					lnX = (m.tnWidth / 2)
					lnY = (m.tnHeight / 2) + lnY1
		
		
					IF m.tnStart > 90
						loTempGfx.DrawLine(m.loPen, lnX, lnY, lnX, lnY + m.ln3D)
					ENDIF
		
		
					loTempGfx.DrawPie(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
		
					loTempGfx.FillPie(m.loMainBrush, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
					loTempGfx.DrawPie(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep)
		
		* Draw the Image
					loBmp.ApplyColorMatrix(poClrMatrix)
					m.loGfx.DrawImage(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
		
	ENDPROC

	PROCEDURE _drawstackedareachart
		* Generates Stacked and Full-Stacked area Charts (ChartTypes  and 16)
		WITH THIS
			SELECT (._DataCursor )
		
			LOCAL lnIndex, lnMargin, lnWidth, lnHeight, lnValue, lnRecs, lnBetween, lnRec, 	lnChartsCount,;
				lnLine, lnMaxValue, lnPointHeight, ln3D, lnYBase, lnTipPixels, lnX1, lnY1, lnTipPixels, llMultiChart
			llMultiChart = .F.
		
			lnTipPixels = ._TipPixels
			lnMargin = .MARGIN
			m.ln3D = ._3D
			lnRecs = RECCOUNT()
			lnChartsCount = .ChartsCount
		* Calculate the maximum width of the chart
			lnHeight = .ChartCanvas.HEIGHT - ._XAxisHeight - ._TopOffSet - ._3D
			m.lnWidth = .ChartCanvas.WIDTH - ._YAxisWidth - ._LeftOffset - ln3D - ._RightOffset
		
			IF m.lnWidth < 10 OR m.lnHeight < 10 OR lnRecs < 2
				RETURN
			ENDIF
		
			LOCAL loGfx AS xfcGraphics
			m.loGfx = .oGfx
		
		* Get the maximum value of the chart
			lnMaxValue = ._ScaleRange
		
		* Get the lower Y point
			lnYBase = .ChartCanvas.HEIGHT - ._XAxisHeight
		
		* If MultiChart mode, the chart needs to start half a position further
			IF llMultiChart
				lnBetween = m.lnWidth / (lnRecs)
			ELSE
				lnBetween = m.lnWidth / (lnRecs - 1)
			ENDIF
		
		* Prepare array of points
		* All the main points will be defined here
			LOCAL laPointsX(lnRecs), laPointsY(lnRecs, lnChartsCount), laPointsYAV(lnRecs, lnChartsCount)	;
				, lnPrevPoint, lnTotRow, laValues(lnChartsCount)	;
				, laPointsI(lnRecs, lnChartsCount) && Points Index
		
		
			FOR .ROW = 1 TO RECCOUNT()
				lnRec = .Row
				lnPrevPoint = 0
		
				lnX1 = ._YAxisWidth + (lnBetween * (lnRec - 1)) + IIF(llMultiChart, (lnBetween / 2), 0) + ._LeftOffset  && lnMargin
				laPointsX(lnRec) = lnX1
				._aPoints(lnRec,1) = lnX1 + ln3D
		
		
				m.lnTotRow = 0
		* Get the total for the current row
				FOR .COLUMN = 1 TO .ChartsCount
					.GetValue()
					laValues(.Column) =.Value
					m.lnTotRow = m.lnTotRow + .Value
				NEXT
		
		
				FOR .COLUMN = 1 TO .ChartsCount
		
					m.lnValue = laValues(THIS.COLUMN)
		
					._ChartIndex = .Column
		
					IF .ChartType = 16 && Full-stacked Area
						lnPointHeight = IIF( EMPTY( m.lnTotRow ), 0, lnValue / m.lnTotRow * lnHeight)
					ELSE
						lnPointHeight = lnValue / lnMaxValue * lnHeight
					ENDIF
		
					lnY1 = lnYBase - (lnPointHeight + lnPrevPoint)
					laPointsY(lnRec, .Column) = lnY1
					laPointsYAV(lnRec, .Column)= lnYBase - (lnPointHeight / 2 + lnPrevPoint)
		
					lnPrevPoint = lnPointHeight + lnPrevPoint
		
					IF lnValue = 0
						._UpdateCoordinates(,"Rect", 0, 0, 0, 0, lnValue, lnTotRow)
					ELSE
						._UpdateCoordinates(,"Rect", lnX1 - lnTipPixels/2, lnY1, lnTipPixels, lnPointHeight, lnValue, lnTotRow)
					ENDIF
					laPointsI(lnRec,.Column) = ._nIndex
				NEXT
		
			NEXT
		
		
		* Draw the vertical line only for the first line
			._DrawVerticalLineBack()
		
			LOCAL laMainPolygon(lnRecs * 2), laLinePolygon(4), laSidePolygon(4), lnCompl, loBrush AS xfcBrush
		
			m.loBrush = IIF( .BrushType = 1,"This._o3dbrush", "This._oMainBrush")
		ENDWITH
		
		
		WITH _SCREEN.SYSTEM.Drawing
		
			FOR THIS.COLUMN = 1 TO THIS.ChartsCount
		
		* Fill the main polygon
				FOR lnRec = 1 TO lnRecs
					lnCompl = (lnRecs * 2) - lnRec + 1
					laMainPolygon(lnRec) = .POINT.New(laPointsX(lnRec), laPointsY(lnRec, THIS.Column))
		
					IF THIS.Column = 1
						laMainPolygon(lnCompl) = .POINT.New(laPointsX(lnRec), lnYBase)
					ELSE
						laMainPolygon(lnCompl) = .POINT.New(laPointsX(lnRec), laPointsY(lnRec, THIS.Column-1))
					ENDIF
				NEXT
		
				THIS._PrepareBrushes(0,0,THIS.ChartCanvas.WIDTH, THIS.ChartCanvas.HEIGHT, .F., THIS.Column)
		
				m.loGfx.FillPolygon(THIS._oMainBrush, @laMainPolygon)
				m.loGfx.DrawPolygon(THIS._oBorderPen, @laMainPolygon)
		
		
				IF m.ln3D > 0
		
		* Draw the 3D line above the main polygon
					FOR lnRec = 1 TO lnRecs - 1
		
						laLinePolygon(1) = laMainPolygon(lnRec)
						laLinePolygon(2) = .POINT.New(laMainPolygon(lnRec).X + m.ln3D, laMainPolygon(lnRec).Y - m.ln3D)
						laLinePolygon(3) = .POINT.New(laMainPolygon(lnRec+1).X + m.ln3D, laMainPolygon(lnRec+1).Y - m.ln3D)
						laLinePolygon(4) = laMainPolygon(lnRec+1)
						THIS._PrepareBrushes(laMainPolygon(lnRec).X, laMainPolygon(lnRec).Y - m.ln3D, ;
							laMainPolygon(lnRec+1).X + m.ln3D - laMainPolygon(lnRec).X, ;
							MAX(2,ABS(laMainPolygon(lnRec).Y - laMainPolygon(lnRec+1).Y)), .F., THIS.Column)
		
		
		
						m.loGfx.FillPolygon(EVALUATE(m.loBrush), @laLinePolygon)
						m.loGfx.DrawPolygon(THIS._oBorderPen, @laLinePolygon)
					NEXT
		* Fill the right-most external side of the area
		* Draw the last 3D polygon, to fill the Area
					laSidePolygon(1) = laLinePolygon(3)
					laSidePolygon(2) = laLinePolygon(4)
					laSidePolygon(3) = laMainPolygon(lnRecs + 1)
					laSidePolygon(4) = .POINT.New(laSidePolygon(3).X + m.ln3D, laSidePolygon(3).Y - m.ln3D)
		
					THIS._PrepareBrushes(laSidePolygon(2).X, laSidePolygon(1).Y, ;
						m.ln3D, 2, .F., THIS.Column)
		
					m.loGfx.FillPolygon(EVALUATE(m.loBrush), @laSidePolygon)
					m.loGfx.DrawPolygon(THIS._oBorderPen, @laSidePolygon)
				ENDIF
		
			NEXT
		
		
		* Adjust _aPoints Array to show the information in the correct position
			FOR lnRec = 1 TO lnRecs
				THIS._aPoints(lnRec,1) = THIS._aPoints(lnRec,1) - ln3D
			NEXT
		
		
			IF THIS.ShowValuesOnShapes
		
				FOR lnLine = 1 TO lnChartsCount
		
					IF TYPE('THIS.FIELDS(lnLine).ShowValuesOnShape') = 'U' OR THIS.FIELDS(lnLine).ShowValuesOnShape
		*** Draw Legends above the points
						FOR lnRec = 1 TO lnRecs
							lnX1 = laPointsX(lnRec)
							lnY1 = laPointsYAV(lnRec, lnLine)
		
							lnIndex = laPointsI(lnRec,lnLine)
							THIS._DrawShapeLegend(lnX1, lnY1, lnIndex)
						NEXT
					ENDIF
		
				NEXT
			ENDIF
		
			THIS._DrawXAxisLegend()
		
		ENDWITH
		
	ENDPROC

	PROCEDURE _drawtrianglebar
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D
		LOCAL loGfx AS xfcGraphics, loTopBrush AS xfcBrush, loBotBrush AS xfcBrush	;
			,lnColor, ln3D, loPen AS xfcPen, lnAlpha, lnOrigAlpha, loShape
		m.loGfx = THIS.oGfx
		
		lnOrigAlpha = THIS.AlphaChannel
		lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25))
		THIS.AlphaChannel = lnAlpha
		
		THIS._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(THIS.SingleData, RECNO(),THIS._ChartIndex))
		WITH _SCREEN.SYSTEM.Drawing
		
			m.lnColor = THIS.ChangeColor(THIS._nColor, + 60)
			m.loPen = .PEN.New(.COLOR.FromRGB(lnColor))
			m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1)
		
		
		
		
			DO CASE
		
				CASE THIS.BrushType = 1 && SolidColors
					loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20)))
					loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
					loLeftBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20)))
					loRightBrush = THIS._oMainBrush
		
				CASE THIS.BrushType = 2 && Gradient
					loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor))
					loBotBrush = loTopBrush
					loLeftBrush = loTopBrush
					loRightBrush = THIS._oMainBrush
				CASE THIS.BrushType = 4 && Треугольный столбик
					loTopBrush =  THIS._o3DBrush
					loBotBrush = loTopBrush
					loLeftBrush = loTopBrush
					loRightBrush = THIS._oMainBrush
		
				OTHERWISE
					THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex))
					loTopBrush = THIS._oMainBrush
					loBotBrush = loTopBrush
					loLeftBrush = loTopBrush
					loRightBrush = THIS._oMainBrush
		
			ENDCASE
		
		
			THIS.AlphaChannel = lnOrigAlpha
		
		
			IF THIS._Orientation = 1 && Vertical
		
		
				LOCAL lnCenterX, x0, x1
				x0 = tnX + m.ln3D / 2
				x1 = x0 + tnWidth
				lnCenterX = x0 + (tnWidth / 2)
		
		* Prepare the bottom triangle
				LOCAL yBott
				yBott = tnY + tnHeight
		
				LOCAL laBotPoints(3), laLeftPoints(4)
				laBotPoints(1) = .POINT.New(lnCenterX, yBott)
				laBotPoints(2) = .POINT.New(x0, yBott - m.ln3D)
				laBotPoints(3) = .POINT.New(x1, yBott - m.ln3D)
		
		
		
		
				m.loGfx.FillPolygon(loBotBrush, @laBotPoints)
				m.loGfx.DrawPolygon(m.loPen, @laBotPoints)
		
		
		* Prepare the top triangle
				LOCAL laTopPoints(3)
				laTopPoints(1) = .POINT.New(lnCenterX, tnY)
				laTopPoints(2) = .POINT.New(x0, tnY - m.ln3D)
				laTopPoints(3) = .POINT.New(x1, tnY - m.ln3D)
				LOCAL loPath AS xfcGraphicsPath
				loPath = .Drawing2D.GraphicsPath.New()
				loPath.FillMode = .Drawing2D.FillMode.ALTERNATE
		
				loPath.StartFigure()
				loPath.ADDLINE(lnCenterX, tnY, x0, tnY - m.ln3D)
				loPath.ADDLINE(x0, tnY - m.ln3D, x1, tnY - m.ln3D)
				loPath.ADDLINE(x1, tnY - m.ln3D, lnCenterX, tnY)
				loTopBrush=_Screen.FoxChartsHelper.PathGradient( , m.loPath, THIS._nColor,-1, m.lnCenterX, tnY - m.ln3D/2,,,THIS.AlphaChannel)
		
				m.loGfx.FillPolygon(loTopBrush, @laTopPoints)
				m.loGfx.DrawPolygon(m.loPen, @laTopPoints)
		
		
		* Prepare the LEFT face of the 3d triangle (polygon)
				laLeftPoints(1) = laTopPoints(1)
				laLeftPoints(2) = laTopPoints(2)
				laLeftPoints(3) = laBotPoints(2)
				laLeftPoints(4) = laBotPoints(1)
		
				m.loGfx.DrawPolygon(m.loPen, @laLeftPoints)
				m.loGfx.FillPolygon(loLeftBrush, @laLeftPoints)
		
		* Prepare the RIGHT face of the 3d triangle (polygon)
				LOCAL laRightPoints(4)
				laRightPoints(1) = laTopPoints(1)
				laRightPoints(2) = laTopPoints(3)
				laRightPoints(3) = laBotPoints(3)
				laRightPoints(4) = laBotPoints(1)
		
				m.loGfx.DrawPolygon(m.loPen, @laRightPoints)
				m.loGfx.FillPolygon(loRightBrush, @laRightPoints)
		
		
				TEXT TO lcPoints
		<<ROUND(X0,0)>>,<<ROUND(m.yBott - m.ln3D,0)>>
		<<ROUND(lnCenterX,0)>>,<<ROUND(m.yBott,0)>>
		<<ROUND(X1,0)>>,<<ROUND(m.yBott - m.ln3D,0)>>
		<<ROUND(X1,0)>>,<<ROUND(tnY - m.ln3D,0)>>
		<<ROUND(X0,0)>>,<<ROUND(tnY - m.ln3D,0)>>
		<<ROUND(X0,0)>>,<<ROUND(m.yBott - m.ln3D,0)>>
				ENDTEXT
				loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints)
		
		
			ELSE  && Horizontal
		
				LOCAL lnCenterY, y0, ln3D
				m.ln3D = MAX(THIS._3d, 1)
				x0 = tnX
				x1 = x0 + tnWidth
				lnCenterY = tnY + tnHeight / 2
		
				TEXT TO lcPoints
		<<ROUND(X0 + ln3d,0)>>,<<ROUND(tnY,0)>>
		<<ROUND(X0,0)>>,<<ROUND(m.lnCenterY,0)>>
		<<ROUND(X0 + ln3d,0)>>,<<ROUND(m.tnY + tnHeight,0)>>
		<<ROUND(X1 + ln3d,0)>>,<<ROUND(tnY + tnHeight,0)>>
		<<ROUND(X1 + ln3d,0)>>,<<ROUND(tnY,0)>>
		<<ROUND(X0 + ln3d,0)>>,<<ROUND(tnY,0)>>
				ENDTEXT
				loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints)
		
		* Prepare the right (top) triangle
				LOCAL laRightPoints(3)
				laRightPoints(1) = .POINT.New(x1, lnCenterY)
				laRightPoints(2) = .POINT.New(x1 + ln3D, tnY)
				laRightPoints(3) = .POINT.New(x1 + ln3D, tnY + tnHeight)
		
				m.loGfx.DrawPolygon(m.loPen, @laRightPoints)
				m.loGfx.FillPolygon(loTopBrush, @laRightPoints)
		
		* Prepare the Left triangle
				LOCAL laLeftPoints(3)
				laLeftPoints(1) = .POINT.New(x0, lnCenterY)
				laLeftPoints(2) = .POINT.New(x0 + ln3D, tnY)
				laLeftPoints(3) = .POINT.New(x0 + ln3D, tnY + tnHeight)
		
				m.loGfx.DrawPolygon(m.loPen, @laLeftPoints)
				m.loGfx.FillPolygon(loBotBrush, @laLeftPoints)
		
		* Prepare the Top face of the 3d triangle (polygon)
				LOCAL laTopPoints(4)
				laTopPoints(1) = laLeftPoints(1)
				laTopPoints(2) = laLeftPoints(2)
				laTopPoints(3) = laRightPoints(2)
				laTopPoints(4) = laRightPoints(1)
		
				m.loGfx.DrawPolygon(m.loPen, @laTopPoints)
				m.loGfx.FillPolygon(loLeftBrush, @laTopPoints)
		
		* Prepare the BOTTOM face of the 3d triangle (polygon)
				LOCAL laBotPoints(4)
				laBotPoints(1) = laLeftPoints(1)
				laBotPoints(2) = laLeftPoints(3)
				laBotPoints(3) = laRightPoints(3)
				laBotPoints(4) = laRightPoints(1)
		
				m.loGfx.DrawPolygon(m.loPen, @laBotPoints)
				m.loGfx.FillPolygon(loRightBrush, @laBotPoints)
		
			ENDIF
		
		
		
		* Draw the Values inside the shapes
			THIS._DrawLegendinBar(x0, tnY, tnWidth, tnHeight, tnValue)
		
		
		ENDWITH
		
	ENDPROC

	PROCEDURE _drawyaxis
		LPARAMETERS tn3D, tnMinLeft, tnYAxisHeight, toBrush, toPen, tnIndex
		
		LOCAL lcPoints, 	;
			ln3d, lnBottom, lnHeight, lnLeft, lnMaxValue, lnMinLeft, lnRight, lnScaleHeight, lnTop, lnX, lnX0, lnX1, lnXWidth, lnY, lnY0, lnY1, lnYAxisHeight, lnYaxisWidth, lnYaxisWidth2, 	;
			loBrush, loGfx, loPen
		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
		
		m.lnY0 = ROUND(THIS.ChartCanvas.HEIGHT - THIS._XAxisHeight,0)
		m.lnY1 = ROUND(THIS._TopOffSet,0)
		
		IF m.lnY0 - m.lnY1 < 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
					m.lnYaxisWidth  = m.lnY0 - m.lnY1
					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.lnY1 + m.lnYaxisWidth, m.lnYaxisWidth, m.lnYAxisHeight)
					lnLeft= INT(THIS._LeftOffset)
					DO CASE
						CASE THIS.YAxis.ALIGNMENT = 0
							lnTop = INT(lnY1 + m.lnYaxisWidth - THIS.YAxis._Width)
						CASE THIS.YAxis.ALIGNMENT = 1
							lnTop = INT(lnY1)
						OTHER
							lnTop = INT(lnY1 + (m.lnYaxisWidth - THIS.YAxis._Width)/2)
					ENDCASE
		
					lnRight = INT(lnLeft + THIS.YAxis._Height)
					lnBottom = INT(lnTop + THIS.YAxis._Width)
					TEXT TO lcPoints
		<<Round(lnLeft,0)>>,<<Round(lnTop,0)>>
		<<Round(lnRight,0)>>,<<Round(lnTop,0)>>
		<<Round(lnRight,0)>>,<<Round(lnbottom,0)>>
		<<Round(lnLeft,0)>>,<<Round(lnbottom,0)>>
		<<Round(lnLeft,0)>>,<<Round(lnTop,0)>>
					ENDTEXT
					THIS._UpdateCoordinates(,"YaxisCaption", lnLeft, lnTop, m.lnYAxisHeight, THIS.YAxis._Width, 0, THIS.YAxis.CAPTION, lcPoints)
				ENDIF
			ENDIF  && tnIndex = 1
		
			IF tnIndex = 2
				IF EMPTY(THIS.YAxis2.CAPTION)
					THIS._yAxisWidth2	 = 0
				ELSE
					m.lnYaxisWidth2  = m.lnY0 - m.lnY1
					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.lnX0 = THIS.ChartCanvas.WIDTH - THIS._RightOffset - m.ln3d - m.lnYAxisHeight + THIS._ScaleW2 + 6
					THIS.YAxis2._DrawString( m.lnX0, m.lnY1 + m.lnYaxisWidth2, m.lnYaxisWidth2, m.lnYAxisHeight)
					lnLeft= INT(lnX0)
					DO CASE
						CASE THIS.YAxis2.ALIGNMENT = 0
							lnTop = INT(lnY1 + m.lnYaxisWidth2 - THIS.YAxis2._Width)
						CASE THIS.YAxis.ALIGNMENT = 1
							lnTop = INT(lnY1)
						OTHER
							lnTop = INT(lnY1 + (m.lnYaxisWidth2 - THIS.YAxis2._Width)/2)
					ENDCASE
		
					lnRight = INT(lnLeft + THIS.YAxis2._Height)
					lnBottom = INT(lnTop + THIS.YAxis2._Width)
					TEXT TO lcPoints
		<<Round(lnLeft,0)>>,<<Round(lnTop,0)>>
		<<Round(lnRight,0)>>,<<Round(lnTop,0)>>
		<<Round(lnRight,0)>>,<<Round(lnbottom,0)>>
		<<Round(lnLeft,0)>>,<<Round(lnbottom,0)>>
		<<Round(lnLeft,0)>>,<<Round(lnTop,0)>>
					ENDTEXT
					THIS._UpdateCoordinates(,"Yaxis2Caption", lnLeft, lnTop, m.lnYAxisHeight, THIS.YAxis._Width, 0, THIS.YAxis.CAPTION, lcPoints)
		
				ENDIF
			ENDIF && tnIndex = 2
		
			m.lnMaxValue = THIS._ScaleRange
		
			WITH _SCREEN.SYSTEM.Drawing
		* Draw the Y Axis
				IF m.tnIndex = 2
					m.lnX0 = THIS.ChartCanvas.WIDTH - THIS._RightOffset - m.ln3d + 2 - THIS._yAxisWidth2
				ELSE
					m.lnX0 = THIS._yAxisWidth + THIS._LeftOffset
				ENDIF
		
		
				m.lnX1 = m.lnX0 + m.ln3d + THIS._ScaleW
		
				IF m.ln3d = 0
					m.loGfx.DrawLine(m.loPen, m.lnX0 - 1, m.lnY0, m.lnX0 - 1, m.lnY1)
				ELSE
					LOCAL laPoints(4)
					m.laPoints(1) = .POINT.New(m.lnX0, m.lnY0)
					m.laPoints(2) = .POINT.New(m.lnX0, THIS._TopOffSet + m.ln3d)
					m.laPoints(3) = .POINT.New(m.lnX0 + m.ln3d, THIS._TopOffSet)
					m.laPoints(4) = .POINT.New(m.lnX0 + m.ln3d, m.lnY0 - 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.lnX0, m.lnY0 + 4)
					m.laPointsB(2) = .POINT.New(m.lnX0 - 4, m.lnY0 + 4)
					m.laPointsB(3) = .POINT.New(m.lnX0 - 4, THIS._TopOffSet + m.ln3d)
		
					m.laPointsB(4) = .POINT.New(m.lnX0 - 4 + m.ln3d, THIS._TopOffSet)
					m.laPointsB(5) = .POINT.New(m.lnX0 + m.ln3d, THIS._TopOffSet)
					m.laPointsB(6) = .POINT.New(m.lnX0, THIS._TopOffSet + m.ln3d)
		
					m.loGfx.FillPolygon(m.loBrush, @m.laPointsB)
					m.loGfx.DrawPolygon(m.loPen, @m.laPointsB)
					TEXT to lcPoints
		<<Round(lnX0,0)>>,<<Round(lnY0,0)>>
		<<Round(lnX0,0)>>,<<Round(This._TopOffSet + m.ln3D,0)>>
		<<Round(lnX0 + m.ln3D,0)>>,<<Round(This._TopOffSet,0)>>
		<<Round(lnX0 + m.ln3D,0)>>,<<Round(lnY0 - m.ln3D,0)>>
		<<Round(lnX0,0)>>,<<Round(lnY0,0)>>
					ENDTEXT
					THIS._UpdateCoordinates (, IIF(m.tnIndex=2,'RightSide','LeftSide'), lnx0, lny0, This._TopOffSet + m.ln3D, m.ln3D, '', 0, lcPoints, 0)
				ENDIF
				IF NOT EMPTY(THIS.BackImage) AND FILE(THIS.BackImage)
					m.lnHeight = THIS.HEIGHT - THIS._XAxisHeight - THIS._TopOffSet - m.ln3d
					lnXWidth = THIS.WIDTH - THIS._LeftOffset - THIS._RightOffset - THIS._yAxisWidth - m.ln3d
					lnScaleHeight = (THIS.GetScaleValue (0)- THIS._MinScale) / m.lnMaxValue * lnHeight
					lnY = THIS.HEIGHT - lnScaleHeight - THIS._XAxisHeight - m.ln3d
					lnX = THIS._yAxisWidth + THIS._LeftOffset + m.ln3d
					THIS.oGfx.DrawImage(_SCREEN.SYSTEM.Drawing.BITMAP.FromVarbinary(FILETOSTR(FULLPATH(THIS.BackImage))), lnX, lnY, lnXWidth, m.lnHeight)
				ENDIF
			ENDWITH
		ENDIF
		
	ENDPROC

	PROCEDURE _getchartprop
		LPARAMETERS toPropertiesList, tcProperty, tnType, toSavedProps, lcDescription, tlShowDescriptions
		
		LOCAL  lcCRLF
		lcCRLF = CHR(13)
		
		LOCAL lbChanged, lcNewType, lcOldType, lnBlue, lnDope, lnGreen, lnPos, lnRed
		
		DO CASE
			CASE tnType = 1
				lbChanged = .T.
			CASE tnType = 2
				IF "." $ tcProperty
					lnPos = RAT (".", tcProperty)
					lbChanged = PEMSTATUS ( EVALUATE ("This." + LEFT(tcProperty, lnPos - 1)), SUBSTR(tcProperty, lnPos + 1), 0)
				ELSE
					lbChanged = PEMSTATUS(THIS, tcProperty, 5) AND PEMSTATUS(THIS, tcProperty, 0)
		
		*            lbChanged = Pemstatus (This, tcProperty, 0)
				ENDIF
			CASE tnType = 3
				lcNewType = TYPE("toPropertiesList." + tcProperty)
				lcOldType = TYPE("toSavedProps." + tcProperty)
				lbChanged = (lcNewType # lcOldType) OR NOT ;
					EVALUATE("toPropertiesList." + tcProperty) ==  EVALUATE("toSavedProps." + tcProperty)
		ENDCASE
		
		IF NOT lbChanged
			RETURN ''
		ENDIF
		
		m.lcName  = TRIM(tcProperty)
		m.lxValue = EVALUATE ("toPropertiesList." + tcProperty)
		m.lcType  = VARTYPE (lxValue)
		
		DO CASE
			CASE m.lcType = 'C'
				m.lxValue = TRIM(lxValue)
				DO CASE
					CASE NOT ['] $ m.lxValue
						m.lcValue = ['] + m.lxValue + [']
					CASE NOT ["] $ lxValue
						m.lcValue = ["] + m.lxValue + ["]
					OTHERWISE
						m.lcValue = '[' + m.lxValue + ']'
				ENDCASE
				IF CHR(13)+CHR(10) $ lcValue
					lcapostrophe1 = LEFT(lcValue,1)
					lcapostrophe2 = RIGHT(lcValue,1)
					m.lcValue = STRTRAN(m.lcValue, CHR(13)+CHR(10),[<<CHR(13)+CHR(10)>>]+ lcapostrophe2+'+ ;'+CHR(13)+CHR(10)+lcapostrophe1)
				ENDIF
		
			CASE m.lcType = "O"
				m.lcValue = " " + CHR(38) + CHR(38) + "Custom object - " + m.lxValue.NAME
				RETURN "* ." + m.lcName + " = " + m.lcValue +  lcCRLF
		
			CASE m.lcType = "N"
				LOCAL lcUpName
				lcUpName = UPPER(lcName)
				lnDope = AT('***', lcDescription)
				IF INLIST(ALLTRIM(RIGHT('.' + lcUpName,10)), ;
						'.FORECOLOR', '.BACKCOLOR') OR ;
						('BACKCOLOR2' $ lcUpName) OR ;
						(').COLOR' $ lcUpName) OR ;
						(lnDope > 0 AND "COLOR" == UPPER(ALLTRIM(SUBSTR(lcDescription, lnDope + 3))))
					lnRed   = BITAND(lxValue, 255)
					lnGreen = BITRSHIFT(BITAND(lxValue, 256 * 255), 8)
					lnBlue  = BITRSHIFT(BITAND(lxValue, 256 * 256 * 255), 16)
					m.lcValue = 'RGB(' + TRANSFORM(lnRed) + ',' + TRANSFORM(lnGreen) + ',' + TRANSFORM(lnBlue) + ')'
				ELSE
					m.lcValue = TRANSFORM(m.lxValue)
				ENDIF
		
			OTHERWISE
				m.lcValue = TRANSFORM(m.lxValue)
		ENDCASE
		
		RETURN IIF (EMPTY (lcDescription) OR NOT tlShowDescriptions, '', '* ' + lcDescription + lcCRLF) + "." + m.lcName + " = " + m.lcValue + 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))
				IF EMPTY(.ReadOnlyProps)
					TEXT to .ReadOnlyProps
		,ACOLORS,ALTERED,APALETTECOLORS,CHARTSUM,CHARTTYPE1,COLOR1,COLUMN,CURRCOLUMN,CURRRECNO,CURRINDEX,CURRVALUE,CURRLEGEND,CURROBJTYPE,FIELDVALUE1,FIELDXAXIS,CONTOURGRAPHICS,CONTOURPEN,INVISIBLESHAPES,LCPALETTES,LEGEND1,MINVALUE,OBMP,OGFX,OLDMOUSEINDEX,PICTURETOSAVE,READONLYPROPS,ROW,ROWCOLPROPS,SINGLEDATA,SHAPE1,VALUE,VERSION,WIDTH,HEIGHT,SLEEP
					ENDTEXT
				ENDIF
		
		        Do Case
		
					CASE lcType = 'Property' ; && ReadOnly properties
						AND NOT ','+UPPER (m.lcName)+',' $ .ReadOnlyProps ;
							AND  "_" # LEFT(m.lcName, 1) AND  "On_" # LEFT(m.lcName, 3) ;
							AND (PEMSTATUS(THIS, m.lcName, 4) OR ;
							INLIST( UPPER(lcName), 'BACKCOLOR', 'FORECOLOR', 'MARGIN', 'SHOWTIPS', 'WIDTH', 'HEIGHT'))
		
						ADDPROPERTY (loProperties, lcName, EVALUATE ("This." + 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 lcType = 'Object'  ;
							AND INLIST (lcName, "Title", "Subtitle", "Xaxis", "Axislegend2", "Yaxis", "Shapelegend", "Scalelegend", "Sidelegend", "Deltalegend", "Yaxis2", "CommentsSet")
		
		                * 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 object
		                IF INLIST (lcName,"CommentsSet")
		                MESSAGEBOX(loObject.Name)
		                endi
		                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 _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)
		ADDPROPERTY(m.loData,"BarType",-1)
		
		RETURN m.loData  
	ENDPROC

	PROCEDURE _preparebrushes
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlRect, tnCount, llFromLegend
		LOCAL lnShape AS NUMBER
		EXTERNAL ARRAY XFCGDIPROTATETEXTURETRANSFORM, xfcGdipSetPathGradientSurroundColorsWithCount
		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, lnGradientPosition
		m.lnBrushType = THIS.BrushType
		
		m.lnMainColor = THIS.aColors(m.tnCount)
		
		IF VARTYPE(m.lnMainColor) <> "N"
			m.lnMainColor = THIS._GetRandomColor()
		ENDIF
		THIS._nColor = m.lnMainColor
		lnGradientPosition=MAX(0.05,MIN(0.95,THIS.GradientPosition))
		
		
		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)))
					THIS._oRightbrush=THIS._o3DBrush
		
				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(lnGradientPosition, 1.0)
							ELSE && BlendTriangularShape
								m.loPathGradBrush.SetBlendTriangularShape(lnGradientPosition, 1.0)
							ENDIF
		
							THIS._oMainBrush = m.loPathGradBrush
		
						CASE THIS._GeneralType = "Bar" OR tlRect && Bar Chart
							lnGradientShapeDirection = EVL(THIS.GradientShapeDirection, 0)
							lnGradientHorcount = THIS.GradientHorcount	&& 2
							lnGradientVertcount = THIS.GradientVertcount	&& 3
							IF llFromLegend
								lnGradientShapeDirection = MIN(1,MAX(0,lnGradientShapeDirection))
							ELSE
								m.lnGradientShapeDirection = MIN(3,MAX(0,m.lnGradientShapeDirection))
							ENDIF
		
							m.tnWidth  = MAX(1, m.tnWidth/lnGradientVertcount)
							m.tnHeight = MAX(1, m.tnHeight/lnGradientHorcount)
							LOCAL loLinGradBrush AS xfcLinearGradientBrush
		
							loLinGradBrush = .Drawing2D.LinearGradientBrush.New(;
								.Rectangle.New(m.tnX, m.tnY, m.tnWidth, m.tnHeight), ;
								loColor1, loColor2, lnGradientShapeDirection)
		
		
		
							IF THIS.GradientType = 0 && SigmaBell
								loLinGradBrush.SetSigmaBellShape(lnGradientPosition, 1)
							ELSE && BlendTriangularShape
								loLinGradBrush.SetBlendTriangularShape(lnGradientPosition, 1.0)
							ENDIF
		
							THIS._oMainBrush = 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(lnGradientPosition, 1)
							ELSE && BlendTriangularShape
								m.loLinGradBrush.SetBlendTriangularShape(lnGradientPosition, 1.0)
							ENDIF
		
							THIS._oMainBrush = m.loLinGradBrush
		
					ENDCASE
		
					THIS._o3DBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(m.lnMainColor, - 15)))
					THIS._oRightbrush=THIS._o3DBrush
		
				CASE INLIST( m.lnBrushType, 3, 5) &&  HatchBrush: 3-monochrome, 5 - color
					LOCAL lnHatchBrushValue
					IF THIS.ChartsCount > 1 AND NOT THIS.SingleData && Pie, Bar or Donut
						m.lnHatchBrushValue = 4 + m.tnCount * 2
					ELSE
						m.lnHatchBrushValue =  IIF(m.lnBrushType=3,lnMainColor * 2, 6)
					ENDIF
		
					THIS._oMainBrush = .Drawing2D.HatchBrush.New( m.lnHatchBrushValue, ; && HatchStyle
					THIS._oClrBlack, ; && ForeColor
					IIF(m.lnBrushType=3,THIS._oClrWhite,.COLOR.FromARGB(THIS.AlphaChannel, m.lnMainColor)) ) && BackColor
		
					THIS._o3DBrush = .Drawing2D.HatchBrush.New( m.lnHatchBrushValue , ; && HatchStyle
					IIF(m.lnBrushType=3,.COLOR.Gray, .COLOR.FromRGB(m.lnMainColor )), ; && ForeColor
					.COLOR.LightGray) && BackColor
					THIS._oRightbrush=THIS._oMainBrush
				CASE m.lnBrushType = 4 && TextureBrush
					m.lcTextureTheme = THIS.Texturetheme
		
					LOCAL lcFile
					lcFile = THIS.GetTexture (m.lcTextureTheme,m.tnCount)
					IF EMPTY(lcFile)
						THIS._oMainBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, m.lnMainColor))
						THIS._o3DBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(m.lnMainColor, - 20)))
						THIS._oRightbrush = THIS._o3DBrush
					ELSE
		
						THIS._oDimBrush = .Drawing2D.LinearGradientBrush.New(;
							.Rectangle.New(m.tnX, m.tnY, m.tnWidth+THIS._3d, m.tnHeight), ;
							.COLOR.FromARGB(THIS.AlphaChannel/2,.COLOR.White),	;
							.COLOR.FromARGB(THIS.AlphaChannel/2,.COLOR.Black), 	;
							0)
						THIS._oDimBrush.SetSigmaBellShape(lnGradientPosition, 1)
		
						loBmp = .BITMAP.FromVarbinary(FILETOSTR(lcFile))
						THIS._oMainBrush = .TextureBrush.New(loBmp)
						THIS._o3DBrush = .TextureBrush.New(loBmp)
						THIS._o3DBrush.WrapMode = .Drawing2D.WrapMode.TileFlipX
						XFCGDIPROTATETEXTURETRANSFORM(THIS._o3DBrush.Handle, -45, _SCREEN.SYSTEM.Drawing.Drawing2D.MatrixOrder.APPEND)
						THIS._oRightbrush = .TextureBrush.New(loBmp)
						=xfcGdipRotateTextureTransform(THIS._oRightbrush.Handle, 45, _SCREEN.SYSTEM.Drawing.Drawing2D.MatrixOrder.APPEND)
					ENDIF
			ENDCASE
		
		ENDWITH
		
	ENDPROC

	PROCEDURE _preparecolors
		*
		* Grigory Meriam (Aviv Advanced Solutions Ltd.)
		* Here I put code sent by Grigory Meriam.
		* Gradient colors depend on values.
		* You can see it for m.lnColorType = 3 and ChartType=7
		*
		SELECT(THIS._DataCursor)
		
		LOCAL lnColorType, N , m.nIndex
		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(lnColorType - 4, m.N)
		
				ENDCASE
		
				THIS.aColors(m.N) = m.lnColor
		
			ENDFOR
		ELSE
		
			IF THIS.charttype = 7
				IF m.lnColorType = 3  AND THIS.BrushType != 3 && Gradient
		
					SELECT RECNO() AS nn ;
						FROM (THIS._DataCursor) ;
						ORDER BY  Nvalue1 DESC    ;
						INTO CURSOR curPrepareColors
		
					SELECT curPrepareColors
				ENDIF
			ENDIF
		
		
		
			DIMENSION THIS.aColors(THIS._nRecords)
		
			SCAN
		
				IF USED('curPrepareColors')
					m.nIndex = INT(curPrepareColors.nn)
				ELSE
					m.nIndex = RECNO()
				ENDIF
				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(lnColorType - 4, m.N)
		
		
					OTHERWISE && Custom color and not Line or Area chart
		
				ENDCASE
		
				THIS.aColors(m.nIndex) = m.lnColor
		
			ENDSCAN
		
			IF USED('curPrepareColors')
				USE IN  SELECT ('curPrepareColors')
				SELECT(THIS._DataCursor)
			ENDIF
		
		ENDIF
		
		THIS._UpdateRandomColors = .F.
		
	ENDPROC

	PROCEDURE _preparedata
		WITH THIS
		* Comments
			IF TYPE('.CommentsSet')='U'
				.ADDOBJECT('CommentsSet','FoxChartsBeta.fields')
				TEXT TO lcFieldsDesc
		Left,N
		Top,N
		Caption,C
		FontName,C,ARIAL
		FontSize,I,<<.Comments.FontSize>>
		FontBold,L,<<.Comments.FontBold>>
		FontUnderLine,L
		FontItalic,L
		ForeColor,I,<<.Comments.ForeColor>>
		BackColor,I,<<.Comments.BackColor>>
		ForeColorAlpha,I,255
		BackColorAlpha,I,128
		Rotation,I,0
		GradientLevel,I,5
		Alignment,I,0
		Type,I,1
		PointerSide,I,0
		PointerSubSide,I,1
		PointerWidth,N,10
				ENDTEXT
				.CommentsSet.DESC = lcFieldsDesc
			ENDIF
			lnLines = IIF(EMPTY(.CommentsSetPack),0,ALINES(la,.CommentsSetPack))
			.CommentsSet.SetCount(lnLines)
			.CommentsSet.UNPACK(.CommentsSetPack)
		ENDWITH
		DODEFAULT()
		
	ENDPROC

	PROCEDURE _preparetitle
		WITH _SCREEN.SYSTEM.Drawing
		
			LOCAL lcPoint, lnTitleHeight, lnSubtitleHeight, lnTitleColor, lnLeft
			STORE 0 TO lnTitleHeight, lnSubtitleHeight
		
			* Check if Title was assigned
			IF NOT EMPTY(This.Title.Caption)
				This.Title.Reset()
				lnTop = This.Margin + This.MarginTop
				This.Title._DrawString(0, This.Margin + This.MarginTop, This.ChartCanvas.Width, This.ChartCanvas.Height)
				lnTitleHeight = This.Title._height 
				lnLeft = ICASE(This.Title.Alignment = 0,0,This.Title.Alignment =1,This.ChartCanvas.Width -This.Title._Width,(This.ChartCanvas.Width - This.Title._Width)/2)
				TEXT TO lcPoint
		<<Round(lnLeft,0)>>,<<Round(lnTop,0)>>
		<<Round(lnLeft+This.Title._Width,0)>>,<<Round(lnTop,0)>>
		<<Round(lnLeft+This.Title._Width,0)>>,<<Round(lnTop+lnTitleHeight,0)>>
		<<Round(lnLeft,0)>>,<<Round(lnTop+lnTitleHeight,0)>>
				ENDTEXT
				This._UpdateCoordinates(,"Title", lnLeft, This.Title.Top, This.Title._Width, lnTitleHeight, 0, This.Title.Caption, lcPoint)
			ENDIF
		
			* Check if Subtitle was assigned
			IF NOT EMPTY(This.Subtitle.Caption)
				This.Subtitle.Reset()
				lnTop = This.Margin + This.MarginTop + lnTitleHeight
				This.Subtitle._DrawString(0, lnTop, This.ChartCanvas.Width, This.ChartCanvas.Height)
				lnSubtitleHeight = This.Subtitle._Height
				lnLeft = ICASE(This.SubTitle.Alignment = 0,0,This.SubTitle.Alignment =1,This.ChartCanvas.Width -This.SubTitle._Width,(This.ChartCanvas.Width - This.SubTitle._Width)/2)
				TEXT TO lcPoint
		<<Round(lnLeft,0)>>,<<Round(lnTop,0)>>
		<<Round(lnLeft+This.Subtitle._Width,0)>>,<<Round(lnTop,0)>>
		<<Round(lnLeft+This.Subtitle._Width,0)>>,<<Round(lnTop+lnSubtitleHeight,0)>>
		<<Round(lnLeft,0)>>,<<Round(lnTop+lnSubtitleHeight,0)>>
				ENDTEXT
		
				This._UpdateCoordinates(,"Subtitle", lnLeft, lnTop, This.Subtitle._Width, lnSubtitleHeight, 0, This.Subtitle.Caption, lcPoint)
			ENDIF
		
			This._TitleHeight = lnTitleHeight + lnSubtitleHeight
		ENDWITH
	ENDPROC

	PROCEDURE _updatecoordinates
		LPARAMETERS loShape, tcObjType, tnX, tnY, tnWidth, tnHeight, tnValue, tnStart, tnSweep, lnColor, tcFront, tnIndex
		LOCAL lcFourthDimensionLegend, lcLegend, lcObjectName, 	;
			lnFourthIndex, lnLine, lnRow, ;
			loObject
		WITH THIS
		* During DrawReport(), there's no need to update the coordinates
			SELECT (._DataCursor)
			m.lcLegend=.F.
			._nIndex = ._nIndex + 1
			DO CASE
				CASE tcObjType = "Legend"
					lcLegend = IIF(VARTYPE(m.tnStart) = "C", m.tnStart, "")
				CASE tcObjType $ 'Title,Subtitle,YaxisCaption,LeftSide,BottomSide'
				OTHERWISE
		
					IF .SingleData OR .ChartsCount = 1
						m.lcLegend = cLegend
					ELSE
						IF BETWEEN(._ChartIndex,1,.ChartsCount)
								m.lcLegend = .FIELDS(._ChartIndex).Legend
						ELSE
							m.lcLegend = ''
						ENDIF
					ENDIF
			ENDCASE
			IF VARTYPE(loShape) # 'O'
				lnIndex = IIF(EMPTY(tnIndex),.Shapes.OBJECTS.COUNT+1,tnIndex)
				lcObjectName='Shape'+ALLTRIM(STR(lnIndex))
				IF TYPE('.Shapes.'+lcObjectName) = 'U'
				.Shapes.ADDOBJECT(lcObjectName,[FoxChartsBeta.Figure])
				ENDIF
				loShape = EVALUATE('THIS.Shapes.' + lcObjectName)
			ENDIF
		ENDWITH
		
		
		WITH loShape
			.TYPE = m.tcObjType
			.LEFT = ROUND(m.tnX,0)
			.TOP = ROUND(m.tnY,0)
			.WIDTH = ROUND(m.tnWidth,0)
			.HEIGHT = ROUND(m.tnHeight,0)
			.VALUE = EVL(m.tnValue,0)
			.START = m.tnStart
			.Sweep = m.tnSweep
			.Contour = m.tnSweep
			.Front = tcFront
		
			.ChartIndex = THIS._ChartIndex && ChartRow
			.Currentrow = EVL(THIS._Currentrow, IIF(tcObjType = "Legend", tnValue, RECNO((This._DataCursor))))	&& on "Legend" mode, tnValue passes the index
		
			.Legend = m.lcLegend
			.COLOR = EVL(lnColor,THIS._nColor)
			.CoordNum = VAL(SUBSTR(.NAME,6))
			.RowSum =  IIF(m.tcObjType = "Rect", EVL(tnStart,0), 0) && Sum of the current row
		ENDWITH
		RETURN loShape
		
	ENDPROC

	PROCEDURE AxisLegend2._drawstring
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor
		
		LOCAL x1, y1, lnAlign, lnMode, xBack
		
		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
		
		lnBackColor=EVL(lnBackColor,THIS.BACKCOLOR)
		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, 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, loRect AS xfcRectangle
					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)
		
					loRect = .Rectangle.New(tnX, tnY, tnWidth, THIS._Height)
		
					x1 = tnX
					y1 = tnY
		
					IF tlVertical
						xBack = tnX + (tnWidth - 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 - 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, 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
		
				WITH _SCREEN.SYSTEM.Drawing
			lnRotationCenter = THIS.RotationCenter
		* Center Rotation
			IF lnRotationCenter <> 0
					LOCAL loMatrixC AS xfcMatrix, loPointFC AS xfcPointF
					loMatrixC = .Drawing2D.Matrix.New()
					loPointFC = .PointF.New(xBack + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation
		
					loMatrixC.RotateAt(lnRotationCenter, loPointFC)
					loGfx.MultiplyTransform(loMatrixC)
			ENDIF
		
		
		*	IF THIS.BackColorAlpha > 0
		* Draw the BackGround Rectangle
					IF lnMode = 0 && default
						lnX=x1
						lnY=y1
						lnWidth = THIS._Width-2
						lnHeight=THIS._Height-4
					ELSE
						lnX=xBack+2
						lnY=y1+2
						lnWidth = THIS._Width-4
						lnHeight=THIS._Height-4
					ENDIF
					loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ;
						lnX, lnY, lnWidth, lnHeight)
		
					IF lnMode = 0
						loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight)
					ENDIF
		*	ENDIF
			lnX1=lnX
			lnY1=lnY
		
			lnX2=lnX+lnWidth
			lnY2=lnY
		
			lnX3=lnX2
			lnY3=lnY+lnHeight
		
			lnX4=lnX
			lnY4=lnY3
			IF lnRotation # 0
				lnX0 = loPointF.X
				lnY0 = loPointF.Y
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotation)
			ENDIF
			IF lnRotationCenter # 0
				lnX0 = loPointFC.X
				lnY0 = loPointFC.Y
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotationCenter)
			ENDIF
		
			TEXT TO lcPoints
		<<Round(lnX1,0)>>,<<Round(lnY1,0)>>
		<<Round(lnX2,0)>>,<<Round(lnY2,0)>>
		<<Round(lnX3,0)>>,<<Round(lnY3,0)>>
		<<Round(lnX4,0)>>,<<Round(lnY4,0)>>
			ENDTEXT
			LOCAL laPoints(4)
			laPoints(1) = .POINT.New(lnX1, lnY1)
			laPoints(2) = .POINT.New(lnX2, lnY2)
			laPoints(3) = .POINT.New(lnX3, lnY3)
			laPoints(4) = .POINT.New(lnX4, lnY4)
		ENDWITH
		
		* Draw the Text
		IF lnMode = 0
			LOCAL loStringFmt AS xfcStringFormat, 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
		
			loRect = .Rectangle.New(x1, y1, CEILING(THIS._Width), THIS._Height + 2)
			loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt)
		ELSE
			IF tlVertical
				loRect = .Rectangle.New(xBack, y1, THIS._Width, THIS._Height)
			ENDIF
			loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt)
		ENDIF
		
		THIS.PARENT._updatecoordinates (,'AxisLegend2', lnx1, lnY1, lnWidth, lnHeight, THIS._TransfCaption, lnRotationCenter, lcPoints, 0)
		
		IF lnRotation # 0 OR lnRotationCenter # 0
			loGfx.ResetTransform()
		ENDIF
		
		ENDWITH
		
	ENDPROC

	PROCEDURE ChartCanvas.Click
		LOCAL lnCoordIndex, lnX, lnY, lnValue, loObject
		lnCoordIndex = 0
		
		lnX = MCOL(0,3)
		lnY = MROW(0,3)
		
		WITH THIS.PARENT
			._CheckMousePosition(0, 0, lnX, lnY, @lnValue, @lnCoordIndex, @loObject)
		
			.CurrValue = lnValue
			.CurrIndex = lnCoordIndex
			.CurrObjType = IIF(TYPE('loObject.Type')='C',loObject.Type,'')
		
			.CLICK()
		ENDWITH
		
	ENDPROC

	PROCEDURE ChartCanvas.DblClick
		LOCAL lnCoordIndex, lnX, lnY, lnValue, loObject
		lnCoordIndex = 0
		
		lnX = MCOL(0,3)
		lnY = MROW(0,3)
		
		WITH THIS.PARENT
			._CheckMousePosition(0, 0, lnX, lnY, @lnValue, @lnCoordIndex, @loObject)
		
			.CurrValue = lnValue
			.CurrIndex = lnCoordIndex
			.CurrObjType = IIF(TYPE('loObject.Type')='C',loObject.Type,'')
		
			.DBLCLICK()
		ENDWITH
		
	ENDPROC

	PROCEDURE ChartCanvas.draw
		LPARAMETERS tnWidth, tnHeight, toGfx
		IF THIS.PARENT.Sleep
			RETURN
		ENDIF
		DODEFAULT(tnWidth, tnHeight, toGfx)
		
	ENDPROC

	PROCEDURE ChartCanvas.Init
		WITH THIS
			.WIDTH  = .PARENT.WIDTH
			.HEIGHT = .PARENT.HEIGHT
			IF VARTYPE(.nButton) = 'U'
				.ADDPROPERTY ('nButton',-1)
				.ADDPROPERTY ('nShift',-1)
				.ADDPROPERTY ('nXCoord',-1)
				.ADDPROPERTY ('nYCoord',-1)
			ENDIF
		ENDWITH
		
		DODEFAULT()
		
	ENDPROC

	PROCEDURE ChartCanvas.MouseDown
		LPARAMETERS nButton, nShift, nXCoord, nYCoord
		
		LOCAL loObject, lnCoordIndex
		lnCoordIndex = 0
		
		THIS.PARENT._CheckMousePosition(nButton, nShift, nXCoord, nYCoord, , @lnCoordIndex, @loObject)
		* Update the index property, that will allow all the other "curr"properties to be up to date
		THIS.PARENT.CurrIndex = lnCoordIndex
		THIS.PARENT.MOUSEDOWN( nButton, nShift, nXCoord, nYCoord, loObject)
		
	ENDPROC

	PROCEDURE ChartCanvas.MouseMove
		LPARAMETERS nButton, nShift, nXCoord, nYCoord
		LOCAL lnCoordIndex, loObject
		IF nXCoord=THIS.nXCoord AND nYCoord=THIS.nYCoord AND nButton=THIS.nButton AND nShift = THIS.nShift
			RETURN
		ENDIF
		THIS.nXCoord = nXCoord
		THIS.nYCoord = nYCoord
		THIS.nButton = nButton
		THIS.nShift  = nShift
		
		m.lnCoordIndex = 0
		loObject = .F.
		
		WITH THIS.PARENT
		
			._CheckMousePosition(nButton, nShift, nXCoord, nYCoord, , @lnCoordIndex, @loObject)
		
		* Update the index property, that will allow all the other "curr"properties to be up to date
			THIS.PARENT.Currindex = lnCoordIndex
			.MOUSEMOVE(nButton, nShift, nXCoord, nYCoord, loObject)
		
		ENDWITH
		
	ENDPROC

	PROCEDURE ChartCanvas.MouseUp
		LPARAMETERS nButton, nShift, nXCoord, nYCoord
		LOCAL lcObjectType, lnCoordIndex, loShape
		
		lnCoordIndex = 0
		
		
		WITH THIS.PARENT
			._CheckMousePosition(nButton, nShift, nXCoord, nYCoord, , @lnCoordIndex, @loShape)
		* Update the index property, that will allow all the other "curr"properties to be up to date
			.Currindex = lnCoordIndex
			lcObjectType = IIF(TYPE('loShape.Type')='C', loShape.TYPE, '' )
		
			.MOUSEUP(nButton, nShift, nXCoord, nYCoord, loShape)
		
			IF TYPE('loShape') = 'O' AND ._GeneralType = "Pie" AND nButton=1
				.Column = loShape.CurrentRow
				.Row = loShape.ChartIndex
				IF lcObjectType = "Pie" AND .PieDetachSliceonClick
					._DetachClickedSlice(lnCoordIndex)
				ENDIF
		
				IF lcObjectType = "Legend" AND .PieDetachSliceonLegendClick
					._DetachClickedSlice(lnCoordIndex)
				ENDIF
		
			ENDIF
		ENDWITH
		
	ENDPROC

	PROCEDURE Comments.caption_assign
		lparameters tcText
		This.Caption = tcText
		
	ENDPROC

	PROCEDURE Comments._drawstring
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor, tnAlignMent
		LOCAL lnAlign, lnHeight, lnMode, lnRotationCenter, lnWidth, lnX, lnY,	;
		 loGfx as xfcGraphics,	loSize as xfcSize,	loStringFmt as xfcStringFormat
		
		lnMode = 0 && 0 = x,y Coordinates    ;    1 = xfcRectangle coordinates
		lnAlign = IIF(VARTYPE(tnAlignMent)='N',tnAlignMent,This.Alignment)
			* 0 = Left    1 = Right    2 = Center
		
		loGfx = This.Parent.oGfx
		
		lnBackColor=EVL(lnBackColor,this.BackColor)
		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
		
				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
		
				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 - 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 - 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, loMatrixC as xfcMatrix
					loMatrixC = .Drawing2D.Matrix.New()
					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
		
		
		* Draw the BackGround Rectangle
					IF lnMode = 0 && default
						lnX=x1
						lnY=y1
						lnWidth = THIS._Width-2
						lnHeight=THIS._Height-4
					ELSE
						lnX=xBack+2
						lnY=y1+2
						lnWidth = THIS._Width-4
						lnHeight=THIS._Height-4
					ENDIF
		if THIS.BackColorAlpha<255
					loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ;
						lnX, lnY, lnWidth, lnHeight)
		ENDIF
		
					IF lnMode = 0
						loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight)
					ENDIF
		
			* Draw the Text
			IF lnMode = 0
				LOCAL loStringFmt as xfcStringFormat, 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
		
	ENDPROC

	PROCEDURE DeltaLegend.caption_assign
		lparameters tcText
		This.Caption = tcText
		
	ENDPROC

	PROCEDURE DeltaLegend._drawstring
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor, tnAlignMent
		LOCAL lnAlign, lnHeight, lnMode, lnRotationCenter, lnWidth, lnX, lnY,	;
			loGfx AS xfcGraphics,	loSize AS xfcSize,	loStringFmt AS xfcStringFormat
		
		lnMode = 0 && 0 = x,y Coordinates    ;    1 = xfcRectangle coordinates
		lnAlign = IIF(VARTYPE(tnAlignMent)='N',tnAlignMent,THIS.ALIGNMENT)
		* 0 = Left    1 = Right    2 = Center
		
		loGfx = THIS.PARENT.oGfx
		
		lnBackColor=EVL(lnBackColor,THIS.BACKCOLOR)
		this._Setup
		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
		
					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
		
					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 - 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 - 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, loMatrixC AS xfcMatrix
					loMatrixC = .Drawing2D.Matrix.New()
					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
		
		
		* Draw the BackGround Rectangle
			IF lnMode = 0 && default
				lnX=x1
				lnY=y1
				lnWidth = THIS._Width-2
				lnHeight=THIS._Height-4
			ELSE
				lnX=xBack+2
				lnY=y1+2
				lnWidth = THIS._Width-4
				lnHeight=THIS._Height-4
			ENDIF
			IF THIS.BackColorAlpha<255
				loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ;
					lnX, lnY, lnWidth, lnHeight)
			ENDIF
		
			IF lnMode = 0
				loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight)
			ENDIF
		
		* Draw the Text
			IF lnMode = 0
				LOCAL loStringFmt AS xfcStringFormat, 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
		
	ENDPROC

	PROCEDURE ScaleLegend._drawstring
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor
		
		LOCAL x1, y1, lnAlign, lnMode, xBack
		
		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
		
		lnBackColor=EVL(lnBackColor,THIS.BACKCOLOR)
		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, 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, loRect AS xfcRectangle
					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)
		
					loRect = .Rectangle.New(tnX, tnY, tnWidth, THIS._Height)
		
					x1 = tnX
					y1 = tnY
		
					IF tlVertical
						xBack = tnX + (tnWidth - 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 - 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, 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
		
				WITH _SCREEN.SYSTEM.Drawing
			lnRotationCenter = THIS.RotationCenter
		* Center Rotation
			IF lnRotationCenter <> 0
					LOCAL loMatrixC AS xfcMatrix, loPointFC AS xfcPointF
					loMatrixC = .Drawing2D.Matrix.New()
					loPointFC = .PointF.New(xBack + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation
		
					loMatrixC.RotateAt(lnRotationCenter, loPointFC)
					loGfx.MultiplyTransform(loMatrixC)
			ENDIF
		
		
		*	IF THIS.BackColorAlpha > 0
		* Draw the BackGround Rectangle
					IF lnMode = 0 && default
						lnX=x1
						lnY=y1
						lnWidth = THIS._Width-2
						lnHeight=THIS._Height-4
					ELSE
						lnX=xBack+2
						lnY=y1+2
						lnWidth = THIS._Width-4
						lnHeight=THIS._Height-4
					ENDIF
					loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ;
						lnX, lnY, lnWidth, lnHeight)
		
					IF lnMode = 0
						loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight)
					ENDIF
		*	ENDIF
			lnX1=lnX
			lnY1=lnY
		
			lnX2=lnX+lnWidth
			lnY2=lnY
		
			lnX3=lnX2
			lnY3=lnY+lnHeight
		
			lnX4=lnX
			lnY4=lnY3
			IF lnRotation # 0
				lnX0 = loPointF.X
				lnY0 = loPointF.Y
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotation)
			ENDIF
			IF lnRotationCenter # 0
				lnX0 = loPointFC.X
				lnY0 = loPointFC.Y
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotationCenter)
			ENDIF
		
			TEXT TO lcPoints
		<<Round(lnX1,0)>>,<<Round(lnY1,0)>>
		<<Round(lnX2,0)>>,<<Round(lnY2,0)>>
		<<Round(lnX3,0)>>,<<Round(lnY3,0)>>
		<<Round(lnX4,0)>>,<<Round(lnY4,0)>>
			ENDTEXT
			LOCAL laPoints(4)
			laPoints(1) = .POINT.New(lnX1, lnY1)
			laPoints(2) = .POINT.New(lnX2, lnY2)
			laPoints(3) = .POINT.New(lnX3, lnY3)
			laPoints(4) = .POINT.New(lnX4, lnY4)
		ENDWITH
		
		* Draw the Text
		IF lnMode = 0
			LOCAL loStringFmt AS xfcStringFormat, 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
		
			loRect = .Rectangle.New(x1, y1, CEILING(THIS._Width), THIS._Height + 2)
			loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt)
		ELSE
			IF tlVertical
				loRect = .Rectangle.New(xBack, y1, THIS._Width, THIS._Height)
			ENDIF
			loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt)
		ENDIF
		
		THIS.PARENT._updatecoordinates (,'ScaleLegend', lnX1, lnY1, lnWidth, lnHeight, THIS._TransfCaption, lnRotationCenter, lcPoints, 0)
		
		IF lnRotation # 0 OR lnRotationCenter # 0
			loGfx.ResetTransform()
		ENDIF
		
		ENDWITH
		
	ENDPROC

	PROCEDURE ShapeLegend._drawstring
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor, toParentShape
		LOCAL lcPoints, 	;
			lnHeight, lnMargin, lnRotationCenter, lnWidth, lnX, lnX0, lnX1, lnX2, lnX3, lnX4, lnY, lnY0, lnY1, lnY2, lnY3, lnY4, 	;
			loGfx, loShape , loThisShape
		LOCAL x1, y1, lnAlign, lnMode, xBack, lnNum
		
		IF THIS.PARENT.Bartype = 1
			tnX = tnX +THIS.PARENT._3D/2
		ENDIF
		*!*	if this.Rotation#0 and tlVertical
		*!*	this.Rotation=MOD(this.Rotation+90,360)
		*!*	ENDIF
		
		lnMode = 0 && 0 = x,y Coordinates    ;    1 = xfcRectangle coordinates
		lnAlign = THIS.ALIGNMENT
		* 0 = Left    1 = Right    2 = Center
		
		loGfx = THIS.PARENT.oGfx
		
		lnBackColor=EVL(lnBackColor,THIS.BACKCOLOR)
		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, 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, loRect AS xfcRectangle
					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)
		
					loRect = .Rectangle.New(tnX, tnY, tnWidth, THIS._Height)
		
					x1 = tnX
					y1 = tnY
		
					IF tlVertical
						xBack = tnX + (tnWidth - 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 - 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
				LOCAL loPointF AS xfcPointF, 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)
			ENDIF
		
			lnRotationCenter = THIS.RotationCenter
		* Center Rotation
			IF lnRotationCenter # 0
				LOCAL loMatrixC AS xfcMatrix, loPointFC AS xfcPointF
				loMatrixC = .Drawing2D.Matrix.New()
				loPointFC = .PointF.New(xBack + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation
		
				loMatrixC.RotateAt(lnRotationCenter, loPointFC)
				loGfx.MultiplyTransform(loMatrixC)
			ENDIF
		
		
		*	IF THIS.BackColorAlpha > 0
		* Draw the BackGround Shape
			IF lnMode = 0 && default
				lnX=x1
				lnY=y1
				lnWidth = THIS._Width-2
				lnHeight=THIS._Height-4
			ELSE
				lnX=xBack+2
				lnY=y1+2
				lnWidth = THIS._Width-4
				lnHeight=THIS._Height-4
			ENDIF
		
			IF THIS.PARENT.ShapeLegendType = 1
				loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ;
					lnX, lnY, lnWidth, lnHeight)
				=IIF( lnMode = 0,loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight),0)
			ELSE
				lnMargin=4
				loGfx.FillEllipse( .SolidBrush.New(.COLOR.FromRGB(RGB(192,192,192)), 1), ;
					lnX-lnMargin, lnY, lnWidth+lnMargin*2, lnHeight+lnMargin*2)
				loGfx.FillEllipse( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ;
					lnX-lnMargin, lnY-lnMargin, lnWidth+lnMargin*2, lnHeight+lnMargin*2)
		
				=IIF( lnMode = 0, loGfx.DrawEllipse( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX-lnMargin, lnY-lnMargin, lnWidth+lnMargin*2, lnHeight+lnMargin*2),0)
				lnY = lnY + lnMargin
			ENDIF
		
		
			lnX1=lnX
			lnY1=lnY
		
			lnX2=lnX+lnWidth
			lnY2=lnY
		
			lnX3=lnX2
			lnY3=lnY+lnHeight
		
			lnX4=lnX
			lnY4=lnY3
			IF lnRotation # 0
				lnX0 = loPointF.X
				lnY0 = loPointF.Y
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotation)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotation)
			ENDIF
			IF lnRotationCenter # 0
				lnX0 = loPointFC.X
				lnY0 = loPointFC.Y
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotationCenter)
				THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotationCenter)
			ENDIF
		
			TEXT TO lcPoints
		<<ROUND(lnX1,0)>>,<<ROUND(lnY1,0)>>
		<<ROUND(lnX2,0)>>,<<ROUND(lnY2,0)>>
		<<ROUND(lnX3,0)>>,<<ROUND(lnY3,0)>>
		<<ROUND(lnX4,0)>>,<<ROUND(lnY4,0)>>
		<<ROUND(lnX1,0)>>,<<ROUND(lnY1,0)>>
			ENDTEXT
			LOCAL laPoints(4)
			laPoints(1) = .POINT.New(lnX1, lnY1)
			laPoints(2) = .POINT.New(lnX2, lnY2)
			laPoints(3) = .POINT.New(lnX3, lnY3)
			laPoints(4) = .POINT.New(lnX4, lnY4)
		
		* Draw the Text
			IF lnMode = 0
				LOCAL loStringFmt AS xfcStringFormat, 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
		
				loRect = .Rectangle.New(x1, y1, CEILING(THIS._Width), THIS._Height + 2)
				loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt)
			ELSE
				IF tlVertical
					loRect = .Rectangle.New(xBack, y1, THIS._Width, THIS._Height)
				ENDIF
				loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt)
			ENDIF
		
			loThisShape=.F.
			lnNum=0
			IF VARTYPE(toParentShape)='O'
				lnNum = toParentShape.CoordNum
				FOR EACH loShape IN THIS.PARENT.Shapes.OBJECTS
					IF loShape.ParentCoord = lnNum
						loThisShape = loShape
					ENDIF
				NEXT
			ENDIF
			loThisShape = THIS.PARENT._updatecoordinates (loThisShape,'ShapeLegend', lnX1, lny1, lnWidth, lnHeight, THIS._TransfCaption, lnRotationCenter, lcPoints, 0)
			loThisShape.ParentCoord = lnNum
			IF lnRotation # 0 OR lnRotationCenter # 0
				loGfx.ResetTransform()
			ENDIF
		RETURN loThisShape
		ENDWITH
		
	ENDPROC

ENDDEFINE

DEFINE CLASS foxchartshelper AS custom 
 	*< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" />

	*<DefinedPropArrayMethod>
		*m: arcandpoint
		*m: arrows
		*m: drawcontour
		*m: drawpath
		*m: insidepath
		*m: lineandpoint
		*m: newarrowrow
		*m: newrow
		*m: objform
		*m: pathgradient
		*m: rotate
		*m: rotatepath
		*m: shell
		*m: simplifypath
		*m: sl
		*m: unaxonometric
		*m: unrgb
	*</DefinedPropArrayMethod>

	*<PropValue>
		Name = "foxchartshelper"
	*</PropValue>
	
	PROCEDURE arcandpoint
		LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnAngle1, tnSwap, tlInverse, tnMouseX, tnMouseY
		* Coordinates
		LOCAL llBetween, llInverse, llYes, 	;
			ln, lnA, lnAngle, lnAngle1, lnAngle2, lnB, lnCenterX, lnCenterY, lnMouseX, lnMouseY, lnX, lnY1, lnY2
		lnCenterX = tnX + tnWidth/2
		lnCenterY = tnY+ tnHeight/2
		
		lnMouseX = tnMouseX - lnCenterX
		lnMouseY = lnCenterY - tnMouseY
		lnA = tnWidth / 2
		lnB = tnHeight / 2
		
		
		
		lnY2 = ( 1 - lnMouseX^2/ lnA^2) * lnB^2
		
		
		IF lnY2<0
			RETURN .F.
		ENDIF
		llInverse = tlInverse
		lnAngle1 = IIF(tnAngle1<0,360+tnAngle1,tnAngle1)
		lnAngle2 = lnAngle1+tnSwap
		IF lnAngle2<0
			lnAngle2 =360+lnAngle2
			llInverse = NOT llInverse
		ENDIF
		lnAngle2 = IIF(lnAngle2>360,lnAngle2-360,lnAngle2)
		IF lnAngle1 > lnAngle2
			ln=lnAngle1
			lnAngle1 = lnAngle2
			lnAngle2 = ln
			llInverse = NOT llInverse
		ENDIF
		
		llYes = .F.
		
		*
		*	First point
		*
		
		lnY1 = SQRT(lnY2)
		m.lnAngle = IIF(lnMouseX=0, IIF(lnY1 < 0, 270, 90), RTOD(ATAN(m.lnY1/m.lnMouseX)) )
		DO CASE
			CASE lnMouseX < 0
				m.lnAngle = 180 + m.lnAngle
			CASE lnY1 < 0
				m.lnAngle = 360 + m.lnAngle
		ENDCASE
		m.lnAngle = 360 - m.lnAngle
		llBetween=BETWEEN(lnAngle, lnAngle1, lnAngle2) && AND MAX(lnY1/TAN(DTOR(lnAngle1)), lnY1/TAN(DTOR(lnAngle2)))>m.lnMouseX
		IF llInverse
			llBetween = NOT llBetween
		ENDIF
		IF llBetween
			lnX = MAX(lnY1/TAN(DTOR(lnAngle1)), lnY1/TAN(DTOR(lnAngle2))) && + lnCenterX
			IF ABS(lnX) < 1
				llBetween=.F.
			ENDIF
		ENDIF
		IF llBetween AND lnMouseY < lnY1
			llYes = NOT llYes
		ENDIF
		
		*
		*	Second Point
		*
		lnY1 = -lnY1
		m.lnAngle = IIF(lnMouseX=0, IIF(lnY1<0, 270, 90), RTOD(ATAN(m.lnY1/m.lnMouseX)) )
		DO CASE
			CASE lnMouseX < 0
				m.lnAngle = 180 + m.lnAngle
			CASE lnY1 < 0
				m.lnAngle = 360 + m.lnAngle
		ENDCASE
		m.lnAngle = 360 - m.lnAngle
		llBetween=BETWEEN(lnAngle, lnAngle1, lnAngle2) && AND MAX(lnY1/TAN(DTOR(lnAngle1)), lnY1/TAN(DTOR(lnAngle2)))>m.lnMouseX
		IF llBetween
			lnX = MAX(lnY1/TAN(DTOR(lnAngle1)), lnY1/TAN(DTOR(lnAngle2)))	&& + lnCenterX
			IF ABS(lnX) < 1
				llBetween=.F.
			ENDIF
		ENDIF
		
		IF llInverse
			llBetween = NOT llBetween
		ENDIF
		
		IF llBetween  AND lnMouseY < lnY1
			llYes = NOT llYes
		ENDIF
		RETURN llYes
		
	ENDPROC

	PROCEDURE arrows
		LPARAMETERS lnType, lnX0, lnY0, lnArrowHeight, lnArrowWidth, lnEndWidth, lnValue
		LOCAL lcPolygon, lnHalf
		m.lnHalf = lnArrowHeight/2
		lnRad=5
		lcPolygon=''
		DO CASE
			CASE lnType = 1
		This.NewArrowRow( @lcPolygon, lnX0, lnY0+lnHalf-lnRad, lnX0, lnY0-lnHalf+lnRad)
		This.NewArrowRow( @lcPolygon,lnX0,lnY0-lnHalf,lnRad*2,lnRad*2,180,90)
		This.NewArrowRow( @lcPolygon,lnX0+lnRad,lnY0-lnHalf,lnX0 + m.lnArrowWidth -lnEndWidth-lnRad,lnY0 - m.lnHalf)
		This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0 - m.lnHalf-lnRad*2,lnRad*2,lnRad*2,90,-90)
		This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m. lnArrowHeight+lnRad, lnX0 + m.lnArrowWidth - lnEndWidth ,lnY0- m. lnArrowHeight )
		This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m. lnArrowHeight, lnX0 + m.lnArrowWidth ,lnY0 )
		This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth,lnY0 ,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m. lnArrowHeight )
		This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m. lnArrowHeight,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m.lnHalf + lnRad)
		This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0 + m.lnHalf,lnRad*2,lnRad*2,0,-90)
		This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0 + m.lnHalf,lnX0+lnRad ,lnY0 + m.lnHalf)
		This.NewArrowRow( @lcPolygon,lnX0,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2,90,90)
		
			CASE lnType = 2
		This.NewArrowRow( @lcPolygon, lnX0, lnY0-lnHalf,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0 - m.lnHalf )
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0 - m.lnHalf-lnRad*2,lnRad*2,lnRad*2,90,-90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m.lnHalf-lnRad,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m.lnHalf-lnRad)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m. lnArrowHeight,lnX0 + m.lnArrowWidth,lnY0 )
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 ,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m. lnArrowHeight)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m. lnArrowHeight,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m.lnHalf + lnRad)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0 + m.lnHalf,lnRad*2,lnRad*2,0,-90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0 + m.lnHalf,lnX0 ,lnY0 + m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 ,lnY0 + m.lnHalf,lnX0+lnHalf ,lnY0)
		This.NewArrowRow( @lcPolygon, lnX0+lnHalf ,lnY0,lnX0,lnY0-lnHalf)
		lnX0 = lnX0 + lnHalf
			CASE lnType = 3	&& Двойная
		***********************************************
		This.NewArrowRow( @lcPolygon, lnX0,lnY0,lnX0+lnEndWidth,lnY0-lnArrowHeight)
		This.NewArrowRow( @lcPolygon, lnX0+lnEndWidth,lnY0-lnArrowHeight,lnX0+lnEndWidth,lnY0 - lnHalf - lnRad)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth,lnY0-lnHalf-lnRad*2,lnRad*2,lnRad*2,180,-90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth+lnRad,lnY0-lnHalf,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0-lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0-lnHalf-lnRad*2,lnRad*2,lnRad*2,90,-90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0-lnHalf-lnRad,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0-lnHalf*2)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0-lnHalf*2,lnX0 + m.lnArrowWidth,lnY0)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0+lnHalf*2)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0+lnHalf*2,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0+lnHalf+lnRad)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0+lnHalf,lnRad*2,lnRad*2,0,-90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0+lnHalf,lnX0 + lnEndWidth+lnRad,lnY0+lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth,lnY0+lnHalf,lnRad*2,lnRad*2,270,-90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth,lnY0+lnHalf+lnRad,lnX0 + m.lnEndWidth,lnY0+lnHalf*2)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth,lnY0+lnHalf*2,lnX0,lnY0)
		
			CASE lnType = 4
		This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad,lnX0,lnY0-lnHalf+lnRad)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf,lnRad*2,lnRad*2,180,90)
		This.NewArrowRow( @lcPolygon, lnX0+lnRad,lnY0-lnHalf,lnX0 + m.lnArrowWidth - lnHalf,lnY0 - m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 - m.lnHalf,lnX0 + m.lnArrowWidth,lnY0 )
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 ,lnX0 + m.lnArrowWidth - lnHalf,lnY0 + m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 + m.lnHalf,lnX0+lnRad,lnY0 + m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2,90,90)
		
			CASE lnType = 5
		This.NewArrowRow( @lcPolygon, lnX0+lnHalf,lnY0)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 - m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 )
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 + m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0 + m.lnHalf)
		lnX0 = lnX0 + lnHalf
		
			CASE lnType = 6
		This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad,lnX0,lnY0-lnHalf+lnRad)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf,lnRad*2,lnRad*2,180,90)
		This.NewArrowRow( @lcPolygon, lnX0+lnRad,lnY0-lnHalf,lnX0+lnArrowWidth-lnHalf-lnRad,lnY0-lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf-lnRad*2,lnY0-lnHalf,lnRad*2,lnRad*2,270,90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0-lnHalf+lnRad,lnX0 + m.lnArrowWidth - lnHalf,lnY0-lnHalf/3)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 - m.lnHalf/3 ,lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 - m.lnHalf/3 )
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 - m.lnHalf/3 ,lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 - m.lnHalf/1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 - m.lnHalf/1.5,lnX0 + m.lnArrowWidth,lnY0 )
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 ,lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 + m.lnHalf/1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 + m.lnHalf/1.5,lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 + m.lnHalf/3 )
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 + m.lnHalf/3 ,lnX0 + m.lnArrowWidth - lnHalf+lnRad,lnY0 + m.lnHalf/3 )
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 + m.lnHalf/3 ,lnX0 + m.lnArrowWidth - lnHalf,lnY0 + lnHalf-lnRad)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf-lnRad*2,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2,0,90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf-lnRad,lnY0+lnHalf,lnX0 + lnRad,lnY0+lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf - lnRad*2,lnRad*2,lnRad*2,90,90)
		
			CASE lnType = 7
				lnArrowWidth=lnArrowWidth-8
				DO CASE
					CASE lnValue<0
		This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad,lnX0,lnY0-lnHalf+lnRad)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf,lnRad*2,lnRad*2,180,90)
		This.NewArrowRow( @lcPolygon, lnX0+lnRad,lnY0-lnHalf,lnX0 + m.lnArrowWidth -lnRad,lnY0 - m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth-lnRad*2 ,lnY0-lnHalf,lnRad*2,lnRad*2, 270,90)
		
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 - m.lnHalf +lnRad, lnX0 + m.lnArrowWidth,lnY0 + m.lnHalf*1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 + m.lnHalf*1.5,lnX0 + m.lnArrowWidth + 8,lnY0 + m.lnHalf*1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth + 8,lnY0 + m.lnHalf*1.5,lnX0 + m.lnArrowWidth - m.lnHalf,lnY0 + m.lnHalf*2.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf,lnY0 + m.lnHalf*2.5,lnX0 + m.lnArrowWidth -  m.lnHalf*2 - 8,lnY0 + m.lnHalf*1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth -  m.lnHalf*2 - 8,lnY0 + m.lnHalf*1.5,lnX0 + m.lnArrowWidth -  m.lnHalf*2,lnY0 + m.lnHalf * 1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth -  m.lnHalf*2,lnY0 + m.lnHalf * 1.5,lnX0 + m.lnArrowWidth -  m.lnHalf*2,lnY0 + m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth -  m.lnHalf*2,lnY0 + m.lnHalf,lnX0+lnRad,lnY0 + m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2,90,90)
					CASE lnValue>0
		This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2, 180, -90)
		This.NewArrowRow( @lcPolygon, lnX0+lnRad,lnY0 + m.lnHalf,lnX0 + m.lnArrowWidth-lnRad,lnY0 + m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth-lnRad*2,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2, 90, -90)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 + m.lnHalf - lnRad, lnX0 + m.lnArrowWidth,lnY0 - m.lnHalf*1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 - m.lnHalf*1.5,lnX0 + m.lnArrowWidth + 8,lnY0 - m.lnHalf*1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth + 8,lnY0 - m.lnHalf*1.5,lnX0 + m.lnArrowWidth - m.lnHalf,lnY0 - m.lnHalf*2.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf,lnY0 - m.lnHalf*2.5,lnX0 + m.lnArrowWidth -  m.lnHalf*2 - 8,lnY0 - m.lnHalf*1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth -  m.lnHalf*2 - 8,lnY0 - m.lnHalf*1.5,lnX0 + m.lnArrowWidth -  m.lnHalf*2,lnY0 - m.lnHalf * 1.5)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth -  m.lnHalf*2,lnY0 - m.lnHalf * 1.5,lnX0 + m.lnArrowWidth -  m.lnHalf*2,lnY0 - m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth -  m.lnHalf*2,lnY0 - m.lnHalf,lnX0+lnRad,lnY0 - m.lnHalf)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf,lnRad*2,lnRad*2, 270, -90)
		This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad,lnX0,lnY0-lnHalf+lnRad)
					OTHERWISE
						RETURN this.Arrows(1, lnX0, lnY0, lnArrowHeight, lnArrowWidth, lnEndWidth, lnValue)
				ENDCASE
		
		ENDCASE
		RETURN lcPolygon
		
		*!*	LPARAMETERS lcText,tcParam1,tcParam2,tcParam3,tcParam4,tcParam5,tcParam6,tcParam7
		*!*	lnCount = PCOUNT()
		*!*	if lnCount>3 and VARTYPE(tcParam3)#'N'
		*!*	tcParam3=tcParam1
		*!*	endif
		*!*	FOR lnLine=1 TO lnCOUNT-1
		*!*	lcStr = IIF(lnLine=1, '', lcStr+',') + Transform(ROUND(EVALUATE('tcParam'+allt(STR(lnLine))),0))
		*!*	NEXT
		*!*	TEXT TO lcText addi
		*!*	<<lcStr>>
		
		*!*	ENDTEXT
		
		
	ENDPROC

	PROCEDURE drawcontour
			LPARAMETERS loChart, lcLines, tnIndex
			LOCAL lnGradientPosition, loBrush, loObject
			WITH loChart
				IF TYPE('.ContourGraphics.Name') = 'C'
					.ContourGraphics.dispose()
					.ContourGraphics=.F.
				ENDIF
				loForm = this.ObjForm(loChart)
				loForm.CLS()
				lnGradientPosition=MAX(0.05,MIN(0.95,.GradientPosition))
				.Tips.VISIBLE = .F.
				.ContourGraphics = _SCREEN.SYSTEM.Drawing.Graphics.FromHWnd(loForm.HWND)   && Create a Graphics object
				.ContourGraphics.SmoothingMode = 4
				.ContourPen = _SCREEN.SYSTEM.Drawing.PEN.New(_SCREEN.SYSTEM.Drawing.COLOR.White , 2)
				.ContourPen.DASHSTYLE = 3
				IF VARTYPE(lcLines)='O'
					WITH _SCREEN.SYSTEM.Drawing
						loBrush = .Drawing2D.LinearGradientBrush.New(;
							.Rectangle.New(lcLines.LEFT, lcLines.TOP, lcLines.WIDTH , lcLines.HEIGHT), ;
							.COLOR.FromARGB(64,IIF(loChart.GradientInvertColors,.COLOR.Black,.COLOR.White)),	;
							.COLOR.FromARGB(64,IIF(loChart.GradientInvertColors,.COLOR.White,.COLOR.Black)), 	;
							IIF(loChart._Orientation = 1,0,1))
					ENDWITH
					loBrush.SetSigmaBellShape(lnGradientPosition, 1)
					lcLines.DrawContour(.ContourGraphics, .ContourPen, loBrush, OBJ2CLIENT(loChart,2), OBJ2CLIENT(loChart,1) )
					RETURN
				ENDIF
		
				loObject = EVALUATE([loChart.shapes.shape] + ALLTRIM(STR(tnIndex)))
				IF loObject.TYPE = 'Rect' AND .SHOWTIPS AND NOT .ShowValuesonshapes
					WITH loChart.Tips
						.ZORDER(0)
						.BACKSTYLE = 1
						.BACKCOLOR = loChart.ShapeLegend.BACKCOLOR
						.VALUE = .F. &&loObject.Caption
						.CAPTION = loObject.CAPTION
		*			.EvalCaption()
						.TOP = loObject.TOP
						.LEFT = loObject.LEFT
						.WIDTH=200
						.AUTOSIZE = .T.
						.VISIBLE=.T.
					ENDWITH
				ENDIF
		
		
				WITH _SCREEN.SYSTEM.Drawing
					loBrush = .Drawing2D.LinearGradientBrush.New(;
						.Rectangle.New(loObject.LEFT, loObject.TOP, EVL(loObject.WIDTH,1) , EVL(loObject.HEIGHT,1)), ;
						.COLOR.FromARGB(64,IIF(loChart.GradientInvertColors,.COLOR.Black,.COLOR.White)),	;
						.COLOR.FromARGB(64,IIF(loChart.GradientInvertColors,.COLOR.White,.COLOR.Black)), 	;
						IIF(loChart._Orientation = 1,0,1))
				ENDWITH
				loBrush.SetSigmaBellShape(lnGradientPosition, 1)
				this.DrawPath(.ContourGraphics, .ContourPen, loBrush, lcLines, OBJ2CLIENT(loChart,2), OBJ2CLIENT(loChart,1))
			ENDWITH
		
	ENDPROC

	PROCEDURE drawpath
			LPARAMETERS toGraphics, toPen, toPathBrush, tcLines, tnLeft, tnTop
			LOCAL llAfterArc, llWrapMode, lnCount, lnCount2, lnLeft, lnLine, lnLines, lnParams, lnTop, lnX1, lnX2, lnY1, lnY2, 	;
				loColor, loPath, la(1)
			PRIVATE  gnColor1, gnColor2, gnCenterPointX, gnCenterPointY, gnFocusScales
			gnFocusScales=.3
		EXTERNAL array xfcGdipGetPathGradientSurroundColorCount, xfcGdipSetPathGradientSurroundColorsWithCount, xfcGdipGetPathGradientSurroundColorsWithCount
			WITH _SCREEN.SYSTEM.Drawing
				lnLeft  = EVL(tnLeft,0)
				lnTop =  EVL(tnTop,0)
				loPath = .Drawing2D.GraphicsPath.New()
				loPath.FillMode = .Drawing2D.FillMode.ALTERNATE
				loPath.StartFigure()
				tcLines=EVL(tcLines,'')
				lnLines = ALINES(la, tcLines)
				lnY1 = VAL(la2(ALINES(la2,la(1),',')))+lnTop
				lnX1 = VAL(la2(1)) + lnLeft
				llAfterArc = .F.
				FOR lnLine=1 TO lnLines
					lnParams = ALINES(la2,la(lnLine),',')
					IF lnParams<2
						LOOP
					ENDIF
					IF lnParams = 4
						loPath.ADDLINE( VAL(la2(1)) + lnLeft, VAL(la2(2))+lnTop, VAL(la2(3)) + lnLeft, VAL(la2(4)) + lnTop )
						llAfterArc = .T.
						LOOP
					ENDIF
					IF lnParams = 5
						loPath.ADDLINE( VAL(la2(1)) + lnLeft, VAL(la2(2))+lnTop, VAL(la2(1)) + lnLeft, VAL(la2(2)) + lnTop )
						llAfterArc = .T.
						LOOP
					ENDIF
					IF lnParams > 5
						loPath.AddArc(VAL(la2(1))+ lnLeft, VAL(la2(2))+lnTop, VAL(la2(3)), VAL(la2(4)), VAL(la2(5)), VAL(la2(6))	)
						IF lnParams >6 AND NOT EMPTY( VAL(la2(7)) )
							loPath.Reverse()
						ENDIF
		
						llAfterArc = .T.
						LOOP
					ENDIF
					IF llAfterArc
						llAfterArc = .F.
						LOOP
					ENDIF
					lnY2 = VAL(la2(2))+lnTop
					lnX2= VAL(la2(1)) + lnLeft
					IF llAfterArc
						llAfterArc = .F.
						LOOP
					ELSE
						loPath.ADDLINE(lnX1,lnY1, lnX2,lnY2)
					ENDIF
		
					lnX1=lnX2
					lnY1=lnY2
				NEXT
				IF VARTYPE(toPathBrush) = 'C'
					gnColor1 = RGB(212,212,212)
					gnColor2 = RGB(250,250,250)
					gnCenterPointX = -1
					gnCenterPointY = 0
					llWrapMode=.T.
					=EXECSCRIPT(toPathBrush)
					toPathBrush = .Drawing2D.PathGradientBrush.New(loPath)
					lnCount=0
					=xfcGdipGetPathGradientSurroundColorCount(toPathBrush.Handle, @lnCount)
					m.lqColors = REPLICATE(0h00000000,lnCount)
					m.lnCount2 = 0
					=xfcGdipGetPathGradientSurroundColorsWithCount(toPathBrush.Handle, @lqColors, @lnCount2)
					loColor = .COLOR.FromRGB(gnColor1)
					m.lqColors = REPLICATE(BINTOC(loColor.ARGB,"4rs"),m.lnCount)
		
					=xfcGdipSetPathGradientSurroundColorsWithCount(toPathBrush.Handle, @lqColors, @lnCount)
		
					toPathBrush.CenterColor	 = .COLOR.FromRGB(gnColor2)
					toPathBrush.SetBlendTriangularShape(.5,1)
					toPathBrush.FocusScales = gnFocusScales
					IF gnCenterPointX>=0
						toPathBrush.CenterPoint = .POINT.New(gnCenterPointX,gnCenterPointY)
					ENDIF
					toPathBrush.WrapMode = llWrapMode
		
				ENDIF
				IIF(VARTYPE(toPathBrush) ='O', toGraphics.FillPath(toPathBrush, loPath),.F.)
				IIF(VARTYPE(toPen)    ='O', toGraphics.DrawPath(toPen, loPath),.F.)
			ENDWITH
	ENDPROC

	PROCEDURE insidepath
		LPARAMETERS lcPoints, lnMouseX, lnMouseY
		LOCAL llInverse, llMouseInsideShape, 	;
			lnParams, lnPoint, lnPoints, lnX1, lnX2, lnY1, lnY2, la(1), la1(1)
		llMouseInsideShape = .F.
		STORE .F. TO lnX2, lnY2
		FOR lnPoint=1 TO ALINES(la,RTRIM(lcPoints,CHR(13)+CHR(10)))
			lnParams=ALINES(la1,la(lnPoint),',')
			DO CASE
				CASE INLIST(lnParams,4,5)		&& Line
					lnX1 = VAL(la1(1))
					lnY1 = VAL(la1(2))
					lnX2 = VAL(la1(3))
					lnY2 = VAL(la1(4))
		
					IF VARTYPE(lnX2)='N' AND This.LineAndPoint (lnX1, lnY1, lnX2, lnY2, lnMouseX, lnMouseY) && and not lnX1=lnX2
						llMouseInsideShape = NOT llMouseInsideShape
					ENDIF
					lnX2 = lnX1
					lnY2 = lnY1
				CASE lnParams>5		&& Arc
					STORE .F. TO lnX2, lnY2
					llInverse = IIF(lnParams=6,.F., la1(7)='1')
					IF This.ArcAndPoint( VAL(la1(1)), VAL(la1(2)), VAL(la1(3)), VAL(la1(4)), VAL(la1(5)), VAL(la1(6)), llInverse, lnMouseX, lnMouseY )
						llMouseInsideShape = NOT llMouseInsideShape
					ENDIF
		
				CASE lnParams>1		&& Point
					lnX1 = VAL(la1(1))
					lnY1 = VAL(la1(2))
					IF VARTYPE(lnX2)='N' AND This.LineAndPoint (lnX1, lnY1, lnX2, lnY2, lnMouseX, lnMouseY)
						llMouseInsideShape = NOT llMouseInsideShape
					ENDIF
					lnX2 = lnX1
					lnY2 = lnY1
			ENDCASE
		NEXT
		RETURN llMouseInsideShape
		
	ENDPROC

	PROCEDURE lineandpoint
		LPARAMETERS lnX1, lnY1, lnX2, lnY2, lnMouseX, lnMouseY
		
		LOCAL lnA1, lnB1, lnY_of_Meeting
		IF MIN(m.lnY1,m.lnY2)>m.lnMouseY OR NOT BETWEEN(m.lnMouseX, MIN(m.lnX1,m.lnX2), MAX(m.lnX1,m.lnX2)-0.1)
			RETURN .F.
		ENDIF
		m.lnA1 = (m.lnY2-m.lnY1) / (m.lnX2-m.lnX1)
		m.lnB1 = m.lnY1 - m.lnX1*m.lnA1
		m.lnY_of_Meeting = m.lnA1*m.lnMouseX +m.lnB1
		
		RETURN m.lnY_of_Meeting <= m.lnMouseY && and lnX2#lnMouseX
		
	ENDPROC

	PROCEDURE newarrowrow
		LPARAMETERS lcText,tcParam1,tcParam2,tcParam3,tcParam4,tcParam5,tcParam6,tcParam7
		lnCount = PCOUNT()
		IF lnCount>3 AND VARTYPE(tcParam3)#'N'
			tcParam3=tcParam1
		ENDIF
		FOR lnLine=1 TO lnCount-1
			lcStr = IIF(lnLine=1, '', lcStr+',') + TRANSFORM(ROUND(EVALUATE('tcParam'+ALLT(STR(lnLine))),0))
		NEXT
		TEXT TO lcText addi
		<<lcStr>>
		
		ENDTEXT
		
	ENDPROC

	PROCEDURE newrow
		LPARAMETERS lcText,tcParam1,tcParam2,tcParam3,tcParam4,tcParam5,tcParam6,tcParam7
		LOCAL lcStr, lnCount, lnLine
		lnCount = PCOUNT()
		lcStr = ''
		IF lnCount>3 AND VARTYPE(tcParam3)#'N'
			tcParam3=tcParam1
		ENDIF
		FOR lnLine=1 TO lnCount-1
			lcStr = IIF(EMPTY(lcStr), '', lcStr+',') + TRANSF(ROUND(EVALUATE('tcParam'+ALLT(STR(lnLine))),0))
		NEXT
		TEXT TO lcText addi
		<<lcStr>>
		
		ENDTEXT
		
	ENDPROC

	PROCEDURE objform
		LPARAMETERS loObj
		LOCAL lnLine
		IF TYPE('loObj')#'O' OR UPPER(loObj.BASECLASS)='FORM'
			RETURN loObj
		ENDIF
		FOR lnLine=1 TO 20
			loObj=loObj.PARENT
			IF UPPER(loObj.BASECLASS)='FORM'
				EXIT
			ENDIF
		NEXT
		RETURN loObj
		
	ENDPROC

	PROCEDURE pathgradient
		LPARAMETERS toGraphics, toPath, lnColor1, lnColor2, lnCenterPointX, lnCenterPointY, lnXkoef, lnYkoef, lnAlphaChannel
		EXTERNAL array xfcGdipGetPathGradientSurroundColorCount, xfcGdipSetPathGradientSurroundColorsWithCount
		LOCAL llWrapMode, lnB, lnCount, lnCount2, lnFocusScales, lnG, lnGray, lnR, loColor, loPathBrush
		IF lnColor2<0
			STORE 0 TO lnR, lnG, lnB, lnGray
			THIS.UnRGB(lnColor1, @lnR, @lnG, @lnB, @lnGray)
			lnColor2= IIF( lnGray > 127, RGB(114,43,0),RGB(255,249,183))
		ENDIF
		lnAlphaChannel = IIF(VARTYPE( lnAlphaChannel)='N', lnAlphaChannel,255)
		lnFocusScales= 0
		llWrapMode = .F.
		lnXkoef = IIF(VARTYPE(lnXkoef)='N',lnXkoef,1)
		lnYkoef =  IIF(VARTYPE(lnYkoef)='N',lnYkoef,0.7)
		WITH _SCREEN.SYSTEM.Drawing
			loPathBrush = .Drawing2D.PathGradientBrush.New(toPath)
			lnCount=0
			=xfcGdipGetPathGradientSurroundColorCount(loPathBrush.Handle, @lnCount)
			m.lqColors = REPLICATE(0h00000000,lnCount)
			m.lnCount2 = 0
			=xfcGdipGetPathGradientSurroundColorsWithCount(loPathBrush.Handle, @lqColors, @lnCount2)
			loColor = .COLOR.FromRGB(lnColor1)
			m.lqColors = REPLICATE(BINTOC(loColor.ARGB,"4rs"),m.lnCount)
		
			=xfcGdipSetPathGradientSurroundColorsWithCount(loPathBrush.Handle, @lqColors, @lnCount)
		
			loPathBrush.CenterColor	 = .COLOR.FromARGB( lnAlphaChannel,lnColor2)
			loPathBrush.SetBlendTriangularShape(lnXkoef, lnYkoef)
		
			loPathBrush.FocusScales = lnFocusScales
			IF lnCenterPointX>=0
				loPathBrush.CenterPoint = .POINT.New(lnCenterPointX,lnCenterPointY)
			ENDIF
			loPathBrush.WrapMode = llWrapMode
		
		ENDWITH
		IF VARTYPE(toGraphics)='O'
			toGraphics.FillPath(loPathBrush, toPath)
		ENDIF
		RETURN loPathBrush
		
	ENDPROC

	PROCEDURE rotate
		LPARAMETERS lnX0,lnY0, lnX, lnY, lnNewAngle
		LOCAL  lnX1, lnY1
		lnX1=lnX-lnX0
		lnY1=lnY-lnY0
		
		lnX = lnX1*COS(lnNewAngle)-lnY1*SIN(lnNewAngle) +lnX0
		lnY = lnX1*SIN(lnNewAngle)+lnY1*COS(lnNewAngle) +lnY0
		
	ENDPROC

	PROCEDURE rotatepath
		LPARAMETERS lnX0, lnY0, lcPath, lnAngle
		LOCAL lcNewPath, lcNewStr, lnCount, lnLine, lnX1, lnX2, lnY1, lnY2, la(1), la1(1)
		lnAngle = DTOR(lnAngle)
		lcNewPath = ''
		FOR lnLine=1 TO IIF(EMPTY(lcPath),0,ALINE(la1,lcPath))
			lnCount = ALINE(la, la1(lnLine), ',')
			lnX1=VAL(la(1))
			lnY1=VAL(la(2))
			THIS.ROTATE(lnX0, lnY0, @lnX1, @lnY1, lnAngle)
			la(1)=Transform(ROUND(lnX1,0))
			la(2)=Transform(ROUND(lnY1,0))
			IF lnCount=4
				lnX1=VAL(la(3))
				lnY1=VAL(la(4))
				THIS.ROTATE(lnX0, lnY0, @lnX1, @lnY1, lnAngle)
				la(3)=Transform(ROUND(lnX1,0))
				la(4)=Transform(ROUND(lnY1,0))
		
			ENDIF
		
			FOR lnCol=1 TO lnCount
				lcNewStr = IIF(lnCol=1,'',lcNewStr + ',')+la(lnCol)
			NEXT
			TEXT to lcNewPath addi
		<<lcNewStr>>
		
			ENDTEXT
		NEXT
		
		RETURN lcNewPath
		
	ENDPROC

	PROCEDURE shell
		LPARAMETERS lcFileName,tcWorkDir,tcOperation,lcparams, llInVisible
		
		LOCAL lcWorkDir,lcOperation
		
		IF EMPTY(lcFileName)
			RETURN -1
		ENDIF
		lcFileName=ALLTRIM(lcFileName)
		lcWorkDir=IIF(TYPE("tcWorkDir")="C",ALLTRIM(tcWorkDir),"")
		lcOperation=IIF(TYPE("tcOperation")="C" AND ! EMPTY(tcOperation),ALLTRIM(tcOperation),"Open")
		IF PCOUNT()<4
			lcparams=''
		ENDIF
		DECLARE INTEGER ShellExecute ;
			IN SHELL32.DLL ;
			INTEGER nWinHandle,;
			STRING cOperation, STRING cFileName, STRING cParameters,;
			STRING cDirectory, INTEGER nShowWindow
		RETURN ShellExecute(0,lcOperation,lcFileName,lcparams,lcWorkDir,IIF(EMPTY(llInVisible),1,0))
		
	ENDPROC

	PROCEDURE simplifypath
		LPARAMETERS lcPath
		LOCAL lnLine
		IF EMPTY(lcPath)
			RETURN ''
		ENDIF
		
		LOCAL lcLeft, lcNew, lcNext, lcTop, 	lnCount, lnLines
		lcNew=''
		lnLines = ALINE(la1,lcPath)
		IF lnLines = 1
			RETU lcPath
		ENDIF
		
		lnCount= ALINE(la,la1(lnLines), [,])
		IF lnCount>4
			lnCount= ALINE(la,la1(lnLines-1), [,])
		ENDIF
		lcLeft=la(1)
		lcTop=la(2)
		
		
		FOR lnLine=1 TO lnLines
		
			lnCount = ALINE(la, la1(lnLine), [,])
			IF lnCount>4
				lcNext = la1(IIF(lnLine=lnLines,1,lnLine+1))
				ALINE(la2, lcNext,',')
				TEXT to lcNew addi
		<<lcLeft>>,<<lcTop>>,<<la2(1)>>,<<la2(2)>>
		
				ENDTEXT
		
				LOOP
			ENDIF
			TEXT to lcNew addi
		<<la1(lnLine)>>
		
			ENDTEXT
			lcLeft = la(lnCount-1)
			lcTop= la(lnCount)
		
		NEXT
		RETU lcNew
		
	ENDPROC

	PROCEDURE sl
		LPARAMETERS lc,lcName,llLeave, lcType
		LOCAL lcReturn
		lcName=EVL(lcName,SET("Default")+CURDIR()+'\_Help.txt')
		STRTOFILE(IIF(VARTYPE(lc)='C',lc,TRANSFORM(lc)),lcName,0)
		IF EMPTY(lcType) OR VARTYPE(lcType)#'C'
			MODIFY COMMAND &lcName && RANGE 1,1
			lcReturn = FILETOSTR(lcName)
			IF EMPTY(llLeave)
				TRY
					ERASE &lcName
				CATCH
				ENDTRY
			ENDIF
		ELSE
			this.SHELL(lcType,'',,FULLPATH(lcName)	)
			lcReturn = FILETOSTR(lcName)
		ENDIF
		RETURN lcReturn
		
	ENDPROC

	PROCEDURE unaxonometric
			LPARAMETERS tnAngle, tnWidth, tnHeight
			LOCAL lnNewAngle
			IF m.tnAngle > 360
				m.tnAngle = m.tnAngle - 360
			ENDIF
		
			IF m.tnAngle < 0
				m.tnAngle = m.tnAngle + 360
			ENDIF
		
			m.tnAngle = ROUND(m.tnAngle, 4)
		
			lnNewAngle=DTOR(m.tnAngle  - IIF(m.tnAngle>90 AND m.tnAngle<= 270,180,0))
		
			lnNewAngle=RTOD(ATAN(TAN(lnNewAngle)*tnWidth/tnHeight)) + ICASE( BETWEEN(m.tnAngle , 0, 90),0, BETWEEN(m.tnAngle ,90,270),180, .T., 360)
		
			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 unrgb
		LPARAMETERS lnColor, lnRed, lnBlue, lnGreen, lnGrayColor
		lnRed=MOD(lnColor,256)
		lnGreen=ROUND(MOD((lnColor-lnRed)/256,256),0)
		lnBlue=ROUND(MOD((lnColor-lnRed-lnGreen*256)/256/256,256),0)
		lnGrayColor =  ROUND(0.229*lnRed + 0.587*lnGreen + 0.114*lnBlue,0)
		Return TEXTMERGE([RGB(<<lnRed>>,<<lnGreen>>,<<lnBlue>>)])
		
	ENDPROC

ENDDEFINE

DEFINE CLASS pattern AS imgcanvas OF "gdiplusx.vcx" 
 	*< CLASSDATA: Baseclass="image" Timestamp="" Scale="Pixels" Uniqueid="" />

	*<DefinedPropArrayMethod>
		*m: myrenderosb
		*p: brush
		*p: pen
		*p: todraw
	*</DefinedPropArrayMethod>

	*<PropValue>
		brush = .F.
		Name = "pattern"
		pen = .F.
		todraw = .F.
	*</PropValue>
	
	PROCEDURE beforedraw
		WITH THIS
			.CLEAR(_SCREEN.SYSTEM.Drawing.COLOR.Transparent)
			.RenderMode = 4 && Memory PNG
			.BACKSTYLE = 0 && Transparent
			IF NOT EMPTY(.ToDraw)
				RETURN EXECSCRIPT(.ToDraw)
			ENDIF
		ENDWITH
		
	ENDPROC

	PROCEDURE draw
		LPARAMETERS tnWidth, tnHeight, toGfx
		WITH THIS
			.CLEAR(_SCREEN.SYSTEM.Drawing.COLOR.white)
			.RenderMode = 0 && Memory PNG
			.BACKSTYLE = 0 && Transparent
			IF NOT EMPTY(.ToDraw )
				=EXECSCRIPT(.ToDraw)
			ENDIF
		ENDWITH
		DODEFAULT( tnWidth, tnHeight, toGfx )
		
	ENDPROC

	PROCEDURE MouseMove
		LPARAMETERS nButton, nShift, nXCoord, nYCoord
		IF TYPE('this.Parent.ChartCanvas.Name')='C'
			THIS.PARENT.ChartCanvas.MOUSEMOVE(nButton, nShift, nXCoord, nYCoord)
		ENDIF
		
	ENDPROC

	PROCEDURE myrenderosb
		**************************************************************
		* FUNCTION MyRenderOSB
		*
		**************************************************************
		LOCAL llLockScreen
		
		IF This._InForm
			m.llLockScreen = ThisForm.LockScreen
			ThisForm.LockScreen = .T.
		ENDIF
		
		DO CASE
		CASE This.RenderMode = 0	&& Memory BITMAP
			This.PictureVal = This.oBmp.GetPictureValfromHBitmap()
			
		CASE This.RenderMode = 1	&& File BITMAP
			IF EMPTY(This._tempfile)
				This._tempfile = ADDBS(SYS(2023))+SYS(2015)+".bmp"
			ELSE
				This.Picture = ""
				CLEAR RESOURCES (This._tempfile)
				DELETE FILE (This._tempfile)
				This._tempfile = ADDBS(SYS(2023))+SYS(2015)+".bmp"
			ENDIF
		
			This.oBmp.Save(This._tempfile, _Screen.System.Drawing.Imaging.ImageFormat.Bmp)
			This.Picture = (This._tempfile)
		
		CASE This.RenderMode = 4	&& Memory PNG
			** PNG PictureVal is only supported in SP2 and later
			IF VERSION(4) >=  "09.00.0000.5411"   && "09.00.0000.5815"	&& VFP 9.0 SP2
				This.PictureVal = This.oBmp.GetPictureVal(_Screen.System.Drawing.Imaging.ImageFormat.Png)
			ELSE
				** Default to BMP if SP1 or earlier
				This.PictureVal = This.oBmp.GetPictureValfromHBitmap()
			ENDIF
			
		CASE This.RenderMode = 5	&& File PNG
			IF EMPTY(This._tempfile)
				This._tempfile = ADDBS(SYS(2023))+SYS(2015)+".png"
			ELSE
				This.Picture = ""
				CLEAR RESOURCES (This._tempfile)
				DELETE FILE (This._tempfile)
				This._tempfile = ADDBS(SYS(2023))+SYS(2015)+".png"
			ENDIF
		
			This.oBmp.Save(This._tempfile, _Screen.System.Drawing.Imaging.ImageFormat.Png)
			This.Picture = (This._tempfile)
		
		CASE This.RenderMode = 8	&& File EMF
			This.oGfx = NULL
			LOCAL llLocked
			IF This._InForm
				m.llLocked = ThisForm.LockScreen
				ThisForm.LockScreen = .T.
			ENDIF
			This.Picture = (This._tempFile)
			IF This._InForm AND NOT ThisForm.LockScreen = m.llLocked
				ThisForm.LockScreen = m.llLocked
			ENDIF
			
		ENDCASE
		
		IF This._InForm
			ThisForm.LockScreen = m.llLockScreen
		ENDIF
		
		RETURN
		
	ENDPROC

ENDDEFINE

DEFINE CLASS radialgauge AS imgcanvas OF "gdiplusx.vcx" 
 	*< CLASSDATA: Baseclass="image" Timestamp="" Scale="Pixels" Uniqueid="" />

	*<DefinedPropArrayMethod>
		*m: addshape
		*m: editproperies
		*m: interactivechange		&& Occurs when the user changes the value of a control using the keyboard or the mouse.
		*m: readproperties
		*m: saveproperties
		*m: _checkmouseposition
		*p: adjustbrush
		*p: arrowcolor
		*p: arrowdownwidth
		*p: arrowendwidth
		*p: arrowtopwidth
		*p: bigsteps
		*p: centerradius
		*p: centerx
		*p: centery
		*p: color1
		*p: color2
		*p: contourgraphics
		*p: contourpen
		*p: cornerrad
		*p: currindex
		*p: downarcheight
		*p: focusscales
		*p: fontbold		&& Specifies if the text is bold.
		*p: fontname		&& Specifies the name of the font used to display text.
		*p: fontsize		&& Specifies the font size for text displayed with an object.
		*p: fontunderline		&& Specifies if the text is underlined.
		*p: forecolor		&& Specifies the foreground color used to display text and graphics in an object.
		*p: gradientshapedirection
		*p: id
		*p: leftmargin
		*p: legend
		*p: maxvalue
		*p: minvalue
		*p: mode
		*p: nbutton
		*p: newprops
		*p: nshift
		*p: nxcoord
		*p: nycoord
		*p: pen
		*p: props
		*p: savedpicture
		*p: savedpictureval
		*p: scalecolor
		*p: scalemargin
		*p: scalewidth
		*p: shapes		&& An array for accessing the objects in a container object.
		*p: showcontour
		*p: showscale
		*p: smallsteps
		*p: topmargin
		*p: type
		*p: value		&& Specifies the current state of a control.
	*</DefinedPropArrayMethod>

	*<PropValue>
		adjustbrush = 
		arrowcolor = (RGB(128,128,255))
		arrowdownwidth = 10
		arrowendwidth = 4
		arrowtopwidth = 6
		bigsteps = 5
		centerradius = 5
		centerx = 0
		centery = 0
		color1 = (RGB(245,245,245))
		color2 = (RGB(255,255,255))
		contourgraphics = .F.
		contourpen = .F.
		cornerrad = 14
		currindex = 0
		downarcheight = 4
		focusscales = 0
		fontbold = .F.
		fontname = Arial
		fontsize = 8
		fontunderline = .F.
		forecolor = 0
		gradientshapedirection = 0
		Height = 100
		id = 
		leftmargin = 4
		legend = .F.
		maxvalue = 100
		minvalue = 0
		mode = 
		Name = "radialgauge"
		nbutton = 0
		newprops = .F.
		nshift = 0
		nxcoord = 0
		nycoord = 0
		pen = .F.
		props = .F.
		savedpicture = .F.
		savedpictureval = 
		scalecolor = (RGB(165,170,194))
		scalemargin = 0.15
		scalewidth = 0.05
		shapes = .F.
		showcontour = .T.
		showscale = .T.
		smallsteps = 5
		topmargin = 5
		type = 1
		value = 0
		Width = 110
	*</PropValue>
	
	PROCEDURE addshape
		LPARAMETERS tcObjectName, tcType, tcPolyGon, tnX0, tnY0, tnWidth, tnHeight, tcCaption
		IF TYPE('this.Shapes.'+tcObjectName) = 'U'
			THIS.Shapes.ADDOBJECT(tcObjectName , "FoxChartsBeta.Figure")
		ENDIF
		WITH EVALUATE('This.Shapes.'+tcObjectName)
			.TYPE=tcType
			.SetDimensions( 0, 0, this.Width, this.Height)
			.CAPTION = EVL(tcCaption,tcType)
			.PATH = tcPolyGon
			.Contour = tcPolyGon
			.CoordNum = this.Shapes.ControlCount
		ENDWITH
		
	ENDPROC

	PROCEDURE beforedraw
		LPARAMETERS llRedraw
		LOCAL lcContour, llImageReady, 	;
			lnAngle, lnAngle1, lnAngle2, lnAngleDegree, lnArrowAngle, lnBackColor, lnBackColorAlpha, lnBigRadius, lnBigRadius1, lnBigRadius2, lnBottomY, lnDelta, lnDelta1, lnDeltaX, lnDownAngle, lnDownBeta, lnDownLeft, lnDownRad, lnDownTop, lnEndLeft, lnEndTop, lnHeight, lnLine, lnMainRad, lnOuterMargin, lnSmallRadius, lnSmallRadius1, lnSmallRadius2, lnSmallValue, lnStep, lnStep1, lnTopBeta, lnUpLeft, lnUpTop, lnValue, lnValue1, lnWidth, lnX, lnX1, lnX2, lnX3, lnY, lnY1, lnY2, lnY3, 	;
			loArrowBrush, loBlackPen, loCenterBrush, loColor1, loColor2, loCommonBrush, loDarkPen, loGrayPen, loScaleBrush, loWhiteBrush, loWhitePen
		WITH THIS
			lnWidth = FLOOR((.WIDTH - .LeftMargin*2)/2)*2
			lnHeight = .HEIGHT - .TopMargin * 2
			lnMainRad = ROUND( (MIN(lnWidth/2, lnHeight-.DownArcHeight- .CornerRad)),0)
			.CenterX= .LeftMargin + lnMainRad
			.CenterY = ROUND(.HEIGHT - .DownArcHeight- .CornerRad - .TopMargin, 0)
		
			lnSmallRadius = ROUND(lnMainRad * (1-.ScaleMargin - .ScaleWidth),0)
			lnArrowAngle= (.VALUE-.MinValue) / (.MaxValue - .MinValue) * 180 + 180
			lnOuterMargin = 4
		
			WITH .Legend
				.FONTSIZE = THIS.FONTSIZE
				.FONTNAME = THIS.FONTNAME
				.FONTBOLD= THIS.FONTBOLD
				.FORECOLOR = THIS.FORECOLOR
				.oGfx = THIS.oGfx
				._Setup()
			ENDWITH
		* Кисти и ручки
			llImageReady = VARTYPE(THIS.SavedPicture ) = 'O' AND NOT llRedraw
			WITH _SCREEN.SYSTEM.Drawing
				loArrowBrush = .SolidBrush.New(.COLOR.FromARGB(180,IIF(VARTYPE(THIS.ArrowColor)='C', EVAL(THIS.ArrowColor),THIS.ArrowColor)))
				loDarkPen = .PEN.New(.COLOR.FromRGB(RGB(212,212,212)),1)
				loBlackPen = .PEN.New(.COLOR.FromRGB(0),1)
				lnBigRadius = ROUND(lnMainRad * (1-THIS.ScaleMargin),0)
				lnBigRadius1 = lnBigRadius + lnOuterMargin
				lnSmallRadius1= lnSmallRadius - lnOuterMargin
		
				IF NOT llImageReady
					loGrayPen = .PEN.New(.COLOR.FromRGB(RGB(222,222,222)),4)
					lnBackColor = THIS.ScaleColor
					lnBackColorAlpha = 255
					loScalePen = .PEN.New(.COLOR.FromRGB(RGB(212,212,212)),1)
					loScaleBrush = .SolidBrush.New(.COLOR.FromARGB(lnBackColorAlpha,lnBackColor))
					loWhiteBrush = .SolidBrush.New(.COLOR.FromRGB(RGB(128,255,255)))
					loWhitePen = .PEN.New(.COLOR.FromRGB(RGB(255,255,255)))
					loColor1 = .COLOR.FromRGB( RGB(245,245,245))
					loColor2 = .COLOR.FromRGB( RGB(192,192,192))
		*!*				loCommonBrush = .Drawing2D.LinearGradientBrush.New(;
		*!*					.Rectangle.New(THIS.LeftMargin, THIS.TopMargin, lnWidth, lnHeight), ;
		*!*					loColor1, loColor2, THIS.GradientShapeDirection)
		*!*				loCommonBrush.SetSigmaBellShape(1, 1)
					loCenterBrush = .Drawing2D.LinearGradientBrush.New(;
						.Rectangle.New(THIS.CenterX-THIS.CenterRadius, THIS.CenterY-THIS.CenterRadius, THIS.CenterRadius*2, THIS.CenterRadius*2), ;
						loColor1, loColor2, 0)
					loCenterBrush.SetSigmaBellShape(1, 1)
		
				ENDIF
			ENDWITH
			lnDownRad = .DownArcHeight + .CornerRad
			lnDownAngle = RTOD(ASIN(.CornerRad / lnDownRad))
		
			IF llImageReady
				THIS.oGfx.DrawImage(THIS.SavedPicture, 0, 0, THIS.WIDTH, THIS.HEIGHT)
			ELSE
				TEXT TO this.AdjustBrush
		gnColor1 = <<.Color1>>
		gnColor2 = <<.Color2>>
		gnCenterPointX = <<.LeftMargin + lnMainRad>>
		gnCenterPointY = <<ROUND(.HEIGHT - .DownArcHeight- .CornerRad - .TopMargin, 0)>>
		gnFocusScales=<<.FocusScales>>
				ENDTEXT
		
		*
		*	Внешний контур
		*
		
				lcContour=''
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnDownRad,.CenterY - lnDownRad, lnDownRad*2, lnDownRad*2, lnDownAngle, 180 - lnDownAngle*2)	&& 1
				lnDeltaX = lnDownRad * COS(DTOR(lnDownAngle))
				lnX = .CenterX - lnDeltaX
				lnBottomY = .CenterY + .CornerRad
				_Screen.FoxChartsHelper.NewRow( @lcContour, lnX, lnBottomY, .CenterX - lnMainRad + .CornerRad, lnBottomY)	&& 2. Прямая
		
		* Левый угол скруглить
				lnX = .CenterX - lnMainRad
				lnBottomY = .CenterY - .CornerRad
				_Screen.FoxChartsHelper.NewRow( @lcContour, lnX, lnBottomY , .CornerRad*2, .CornerRad*2, 90, 90)	&& 3
		
		* Большая дуга
				lnY = .CenterY -lnMainRad
				lnX = .CenterX - lnMainRad
		
				_Screen.FoxChartsHelper.NewRow( @lcContour, lnX, lnY, lnMainRad*2, lnMainRad*2, 180, 180)	&& 4 - большая дуга
		
		
		* Правый угол скруглить
				lnX = .CenterX + lnMainRad - .CornerRad*2
				_Screen.FoxChartsHelper.NewRow( @lcContour, lnX, lnBottomY, .CornerRad*2, .CornerRad*2, 0, 90)	&& 5
				lnX = .CenterX + lnMainRad - .CornerRad
		
		* Прямая к начальной точке
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnMainRad - .CornerRad, .CenterY + .CornerRad , .CenterX  + lnDeltaX , .CenterY + .CornerRad)
				_Screen.FoxChartsHelper.DrawPath(.oGfx, loGrayPen, loCommonBrush  , lcContour, 2, 2)
				_Screen.FoxChartsHelper.DrawPath(.oGfx, .PEN, .AdjustBrush  , lcContour, 0, 0)
		
		*
		*	Контур шкалы
		*
				IF .ShowScale
		
					lcContour=''
					_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnBigRadius, .CenterY - lnBigRadius, lnBigRadius*2, lnBigRadius*2, 180, 180)	&& 3 - большая дуга
					_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnBigRadius, .CenterY,  .CenterX + lnSmallRadius, .CenterY)
					_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius, .CenterY - lnSmallRadius, lnSmallRadius*2, lnSmallRadius*2, 0, -180)	&& 3 - малая дуга
					_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius, .CenterY,  .CenterX - lnBigRadius, .CenterY)
					_Screen.FoxChartsHelper.DrawPath(.oGfx, .PEN, loScaleBrush , lcContour, 0, 0)
				ENDIF
		
		
		* Крупные засечки
				lnStep = (THIS.MaxValue-THIS.MinValue)/THIS.BigSteps
				lnDelta = 180/(THIS.MaxValue-THIS.MinValue)
		
				lnStep1 = lnStep / THIS.SmallSteps
				lnDelta1 = lnDelta /  THIS.SmallSteps
				lnBigRadius2 = lnBigRadius - 1
				lnSmallRadius2= lnSmallRadius + 1
				lnSmallValue = 1.1
				FOR lnValue = THIS.MinValue TO THIS.MaxValue STEP lnStep
					lcContour=''
					lnAngleDegree = (lnValue - THIS.MinValue)*lnDelta + 180
					lnAngle = DTOR(lnAngleDegree)
					lnAngle1 = DTOR((lnValue - lnSmallValue - THIS.MinValue)*lnDelta + 180)
					lnAngle2 = DTOR((lnValue + lnSmallValue - THIS.MinValue)*lnDelta + 180)
					lnX1 = lnBigRadius1 * COS(lnAngle1) + .CenterX
					lnY1 = lnBigRadius1 *SIN(lnAngle1) + .CenterY
		
					lnX2 = lnBigRadius1 * COS(lnAngle2) + .CenterX
					lnY2 = lnBigRadius1 *SIN(lnAngle2) + .CenterY
		
					lnX3 = lnSmallRadius1 * COS(lnAngle) + .CenterX
					lnY3 = lnSmallRadius1 *SIN(lnAngle) + .CenterY
					_Screen.FoxChartsHelper.NewRow(@lcContour,lnX1, lnY1, lnX2, lnY2)
					_Screen.FoxChartsHelper.NewRow(@lcContour,lnX2, lnY2, lnX3, lnY3)
					_Screen.FoxChartsHelper.NewRow(@lcContour,lnX3, lnY3, lnX1, lnY1)
					_Screen.FoxChartsHelper.DrawPath(.oGfx, loDarkPen, loWhiteBrush , lcContour, 0, 0)
					.Legend.CAPTION = TRANSFORM(lnValue)
					.Legend._UpdateMeasures()
					IF BETWEEN(lnAngleDegree-180,45,135)
						lnX = lnX3-.Legend._Width/2
						lnY = lnY3
						.Legend.ALIGNMENT=2
					ELSE
						lnX = lnX3 - IIF(lnAngleDegree-180>134,.Legend._Width-4,0)
						lnY = lnY3-.Legend._Height/2
						.Legend.ALIGNMENT=1
					ENDIF
					.Legend._DrawString(lnX, lnY, .Legend._Width,.Legend._Height,.F.,.oGfx)
					IF lnValue = THIS.MaxValue
						EXIT
					ENDIF
		
		* Мелкие засечки
					FOR lnLine = 1 TO THIS.SmallSteps-1
						lcContour=''
						lnValue1 = lnValue + lnStep1 * lnLine
						lnAngle = DTOR((lnValue1 - THIS.MinValue)*lnDelta + 180)
						lnX1 = ROUND(lnBigRadius2 * COS(lnAngle) + .CenterX,0)
						lnY1 = ROUND(lnBigRadius2 * SIN(lnAngle) + .CenterY,0)
		
						lnX2 =  ROUND(lnSmallRadius2 * COS(lnAngle) + .CenterX,0)
						lnY2 =  ROUND(lnSmallRadius2 * SIN(lnAngle) + .CenterY,0)
						_Screen.FoxChartsHelper.NewRow(@lcContour,lnX1, lnY1, lnX2, lnY2)
						_Screen.FoxChartsHelper.DrawPath(.oGfx, loScalePen,  , lcContour, 0, 0)
					NEXT
				NEXT
		* Центр
				lcContour=''
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - .CenterRadius, .CenterY - .CenterRadius, .CenterRadius*2, .CenterRadius*2, 0, 360)	&& Круг в центре
				_Screen.FoxChartsHelper.DrawPath(.oGfx, loDarkPen, loCenterBrush , lcContour, 0, 0)
				.renderosb ()
				.SavedPicture = _SCREEN.SYSTEM.Drawing.BITMAP.FromVarbinary(THIS.PICTUREVAL)
				IF NOT EMPTY(.ID)
				.SavedPictureVal = .PictureVal
				ENDIF
			ENDIF
		*
		*	Объект для распознавания шкалы
		*
			IF TYPE('.Scale') = 'U'
				lcContour=''
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnBigRadius1, .CenterY - lnBigRadius1, lnBigRadius1*2, lnBigRadius1*2, 180, 180)	&& 3 - большая дуга
		
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnBigRadius1, .CenterY,  .CenterX + lnBigRadius1, .CenterY+4)
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnBigRadius1, .CenterY+4,  .CenterX + lnSmallRadius1, .CenterY+4)
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnSmallRadius1,.CenterY+4,  .CenterX + lnSmallRadius1, .CenterY)
		
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius1, .CenterY - lnSmallRadius1, lnSmallRadius1*2, lnSmallRadius1*2, 0, -180)	&& 3 - малая дуга
		
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius1, .CenterY,  .CenterX - lnBigRadius1, .CenterY)
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius1, .CenterY,  .CenterX - lnSmallRadius1, .CenterY+4)
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius1, .CenterY+4,  .CenterX - lnBigRadius1, .CenterY+4)
				_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnBigRadius1, .CenterY+4,  .CenterX - lnBigRadius1, .CenterY)
				.AddShape('Scale', 'Scale', lcContour, ;
					.CenterX - lnBigRadius, .CenterY - lnBigRadius, lnBigRadius*2, lnBigRadius)
			ENDIF
		
		*
		* Стрелка
		*
			lcContour=''
			lnArrowEndwidth = MIN(.ArrowEndwidth, lnBigRadius/4)
			lnSmallRadius2 = lnSmallRadius - lnArrowEndwidth
			.ArrowTopWidth = MIN(.ArrowTopWidth, .CenterRadius)
			.ArrowDownWidth = MIN(.ArrowDownWidth, .CenterRadius*2)
			lnTopBeta = ROUND(90 - RTOD(ACOS(.ArrowTopWidth/2/lnSmallRadius2)),0)
			lnDownBeta = ROUND(90 - RTOD(ACOS(.ArrowDownWidth/2/.CenterRadius)),0)
			_Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - .CenterRadius, .CenterY - .CenterRadius, ;
				.CenterRadius*2, .CenterRadius*2, lnArrowAngle-lnDownBeta, lnDownBeta*2)	&& Нижняя дуга
			lnDownLeft = ROUND(.CenterRadius * COS(DTOR(lnArrowAngle+lnDownBeta)) + .CenterX,0)
			lnDownTop  = ROUND(.CenterRadius * SIN(DTOR(lnArrowAngle+lnDownBeta)) + .CenterY,0)
			lnUpLeft = ROUND(lnSmallRadius2 * COS(DTOR(lnArrowAngle+lnTopBeta)) + .CenterX,0)
			lnUpTop  = ROUND(lnSmallRadius2 * SIN(DTOR(lnArrowAngle+lnTopBeta)) + .CenterY,0)
		
			_Screen.FoxChartsHelper.NewRow(@lcContour,lnDownLeft , lnDownTop, lnUpLeft, lnUpTop)
			lnEndLeft = ROUND(lnSmallRadius * COS(DTOR(lnArrowAngle)) + .CenterX,0)
			lnEndTop = ROUND(lnSmallRadius * SIN(DTOR(lnArrowAngle)) + .CenterY,0)
			_Screen.FoxChartsHelper.NewRow(@lcContour,lnUpLeft , lnUpTop, lnEndLeft, lnEndTop)
		
			lnDownLeft = ROUND(.CenterRadius * COS(DTOR(lnArrowAngle-lnDownBeta)) + .CenterX,0)
			lnDownTop  = ROUND(.CenterRadius * SIN(DTOR(lnArrowAngle-lnDownBeta)) + .CenterY,0)
			lnUpLeft = ROUND(lnSmallRadius2 * COS(DTOR(lnArrowAngle-lnTopBeta)) + .CenterX,0)
			lnUpTop  = ROUND(lnSmallRadius2 * SIN(DTOR(lnArrowAngle-lnTopBeta)) + .CenterY,0)
			_Screen.FoxChartsHelper.NewRow(@lcContour,lnEndLeft, lnEndTop,lnUpLeft , lnUpTop)
			_Screen.FoxChartsHelper.NewRow(@lcContour, lnUpLeft, lnUpTop,lnDownLeft , lnDownTop)
			_Screen.FoxChartsHelper.DrawPath(.oGfx, loDarkPen, loArrowBrush , lcContour, 0, 0)
		
		ENDWITH
		
	ENDPROC

	PROCEDURE createosb
		LPARAMETERS tnWidth, tnHeight
		This.DeleteOSB()
		
		LOCAL loRect
		
		IF EMPTY(m.tnWidth)
			m.tnWidth = This.Width
			m.tnHeight = This.Height
		ENDIF
		
		This._BMPWidth = m.tnWidth
		This._BMPHeight = m.tnHeight
		
		m.tnWidth = MAX(m.tnWidth,1)
		m.tnHeight = MAX(m.tnHeight,1)
		
		WITH _Screen.System.Drawing
			This.oBmp = .Bitmap.New(m.tnWidth, m.tnHeight)
			This.oGfx = .Graphics.FromImage(This.oBmp)
			This.oGfx.SmoothingMode = This.SmoothingMode
			This.oGfx.TextRenderingHint = This.TextRenderingHint
			This.oGfx.InterpolationMode = This.InterpolationMode 
		ENDWITH
	ENDPROC

	PROCEDURE Destroy
		this.SaveProperties()
		DODEFAULT()
		
	ENDPROC

	PROCEDURE draw
		LPARAMETERS tnWidth, tnHeight, toGfx, llHide
		n000=SECONDS()
		LOCAL llRedraw
		THISFORM.LOCKSCREEN = .T.
		m.llRedraw = .F.
		
		IF EMPTY(m.tnWidth)
			THIS._WidthOverride = -1
			THIS._HeightOverride = -1
			m.tnWidth =THIS.WIDTH
			m.tnHeight = THIS.HEIGHT
		ELSE
			IF VARTYPE(tnWidth)='L'
				m.llRedraw = .T.
				m.tnWidth = THIS.WIDTH
				m.tnHeight = EVL(m.tnHeight, THIS.HEIGHT)
			ENDIF
			THIS._WidthOverride = m.tnWidth
			THIS._HeightOverride = m.tnHeight
		ENDIF
		
		THIS._cSize = BINTOC(EVL(m.tnWidth,THIS.WIDTH),"4rs") + BINTOC(EVL(m.tnHeight,THIS.HEIGHT),"4rs")
		IF THIS._BMPWidth <> m.tnWidth OR THIS._BMPHeight <> m.tnHeight OR THIS.RenderMode = 7
			THIS.CreateOSB(m.tnWidth, m.tnHeight)
		ENDIF
		nn1=SECONDS()-n000
		n000=SECONDS()
		THIS.BeforeDraw(llRedraw)
		nn2=SECONDS()-n000
		n000=SECONDS()
		THIS.RenderOSB()
		nn3=SECONDS()-n000
		n000=SECONDS()
		THIS.AfterDraw()
		nn4=SECONDS()-n000
		n000=SECONDS()
		THISFORM.LOCKSCREEN = .F.
		TEXT TO lc
		<<nn1>>, <<nn2>>, <<nn3>>, <<nn4>>
		endtext
		*sl(lc)
	ENDPROC

	PROCEDURE editproperies
		LOCAL lcMode
		lcMode = THIS.Mode
		lcMode = _Screen.FoxChartsHelper.sl(THIS.Mode)
		IF NOT THIS.Mode == lcMode
			THIS.NewProps = .T.
			THIS.ReadProperties (lcMode)
			this.Draw(.t.)
		ENDIF
		
	ENDPROC

	PROCEDURE Init
		SET CLASSLIB TO foxchartsBeta.vcx ADDI
		IF TYPE('_Screen.FoxChartsHelper') = 'U'
			_Screen.ADDOBJECT('FoxChartsHelper', 'FoxChartsBeta.FoxChartsHelper')
		ENDIF
		
		WITH THIS
			TEXT TO .Props
		Arrowcolor
		Arrowdownwidth
		ArrowEndWidth
		ArrowTopWidth
		Bigsteps
		Centerradius
		Color1
		Color2
		Cornerrad
		DownArcHeight
		FocusScales
		Fontbold
		Fontname
		Fontsize
		Fontunderline
		Forecolor
		Gradientshapedirection
		Height
		Interpolationmode
		Left
		Leftmargin
		Maxvalue
		Minvalue
		Scalecolor
		Scalemargin
		Scalewidth
		Showcontour
		Showscale
		Smallsteps
		Topmargin
		Type
		Width
			ENDTEXT
		
			.RenderMode = 4 && Memory PNG
			.oGfx.SmoothingMode = _SCREEN.SYSTEM.Drawing.Drawing2D.SmoothingMode.AntiAlias
			.PEN = _SCREEN.SYSTEM.Drawing.PEN.New(_SCREEN.SYSTEM.Drawing.COLOR.FromRGB(RGB(150,150,155)) , 3)
			.Legend = CREATEOBJECT("_Legend")
			.Legend.oGfx = .oGfx
			.Shapes = CREATEOBJECT('Container')
			.ReadProperties()
			.DRAW
		ENDWITH
		
	ENDPROC

	PROCEDURE interactivechange		&& Occurs when the user changes the value of a control using the keyboard or the mouse.
	ENDPROC

	PROCEDURE MouseMove
		LPARAMETERS nButton, nShift, nXCoord, nYCoord
		LOCAL lnCoordIndex, loObject
		WITH THIS
			IF nXCoord=THIS.nXCoord AND nYCoord=.nYCoord AND nButton=.nButton AND nShift = .nShift
				RETURN
			ENDIF
			.nButton = nButton
			.nShift  = nShift
			.nXCoord = nXCoord
			.nYCoord = nYCoord
			m.lnCoordIndex = 0
			lnX = nXCoord - obj2Client(THIS, 2)
			lnY = nYCoord - obj2Client(THIS, 1)
			loObject = .F.
			loShape = .Shapes.SCALE
			IF .ShowContour AND loShape.CheckMousePosition(lnX, lnY)
				IF VARTYPE(.ContourGraphics) # 'O'
					.ContourGraphics = _SCREEN.SYSTEM.Drawing.Graphics.FromHWnd(THISFORM.HWND)   && Create a Graphics object
					.ContourGraphics.SmoothingMode = 4
					.ContourPen = _SCREEN.SYSTEM.Drawing.PEN.New(_SCREEN.SYSTEM.Drawing.COLOR.FromARGB(212, RGB(255,255,255)) , 2)
					.ContourPen.DASHSTYLE = 0
				ENDIF
				IF  loShape.CoordNum # .Currindex
				THISFORM.CLS()
				loShape.DrawContour(.ContourGraphics, .ContourPen,, obj2Client(THIS, 2), obj2Client(THIS, 1))
				ENDIF
				lnCoordIndex = loShape.CoordNum
			ENDIF
		IF .Currindex # lnCoordIndex AND lnCoordIndex=0
		THISFORM.CLS()
		ENDIF
		
			.Currindex = lnCoordIndex
		
		ENDWITH
		
	ENDPROC

	PROCEDURE MouseUp
		LPARAMETERS nButton, nShift, tnMouseX, tnMouseY
		IF nButton=2 AND nShift=3
			THIS.EditProperies()
			RETURN
		ENDIF
		
		LOCAL lnA, lnAngle, lnB, lnMouseX, lnMouseY, lnOldValue, lnStart, loShape
		tnMouseX = tnMouseX	-Obj2Client(THIS,2)
		tnMouseY = tnMouseY - Obj2Client(THIS,1)
		WITH THIS
			FOR EACH loShape IN THIS.Shapes.OBJECTS
				IF loShape.TYPE = 'Scale' AND loShape.CheckMousePosition(tnMouseX, tnMouseY)
					lnMouseX = tnMouseX - .CenterX
					lnMouseY = tnMouseY - .CenterY
					lnA = 1
					lnB = 1
		
					lnAngle = MOD(RTOD(ATAN( lnMouseY / lnMouseX * lnA/lnB ))- 90, 360)
					IF lnMouseX < 0
						m.lnAngle = 180 + m.lnAngle
					ENDIF
		
					lnAngle=MOD(360+lnAngle,360)
					lnStart = 90
					lnOldValue = .VALUE
					IF NOT BETWEEN(lnAngle, lnStart, 360-lnStart)
						.VALUE = IIF(lnAngle<lnStart,0,.Maxvalue )
					ELSE
						.VALUE = ROUND( (lnAngle-lnStart) /(360-lnStart*2) * .Maxvalue - .MinValue, 0)
					ENDIF
					.VALUE = MIN(.Maxvalue , MAX(.MinValue , .VALUE ))
					IF lnOldValue = .VALUE
						RETURN
					ENDIF
					.DRAW
					.CurrIndex = 0
					.INTERACTIVECHANGE
				ENDIF
			NEXT
		ENDWITH
		
	ENDPROC

	PROCEDURE readproperties
		LPARAMETERS lcMode
		WITH THIS
			IF VARTYPE(lcMode) = 'C' AND NOT EMPTY(lcMode)
				.Mode = lcMode
				=EXECSCRIPT(.Mode)
				RETURN
			ENDIF
			.SaveProperties (.T.)
			IF EMPTY(.ID)
				RETURN
			ENDIF
		
			lcFile = ADDBS( SET("Default")+CURDIR() ) + 'gauges.dbf'
			IF NOT FILE(lcFile)
				CREATE TABLE (lcFile) (ID C(10), Mode M, PICTUREVAL W)
				APPEND BLANK
				REPLACE ID WITH .ID
			ELSE
				IF USED('Gauges')
					SELECT Gauges
				ELSE
					SELECT 0
					USE (lcFile) ALIAS Gauges
				ENDIF
				LOCATE FOR ALLTRIM(ID) == .ID
				IF NOT FOUND()
					APPEND BLANK
					REPLACE ID WITH .ID
				ENDIF
			ENDIF
			IF NOT EMPTY( Gauges.Mode)
			.Mode = Gauges.Mode
			endif
			.SavedPicture = _SCREEN.SYSTEM.Drawing.BITMAP.FromVarbinary(Gauges.PICTUREVAL)
			IF NOT EMPTY(.Mode)
				=EXECSCRIPT(.Mode)
			ENDIF
		ENDWITH
		
	ENDPROC

	PROCEDURE saveproperties
		LPARAMETERS llStoreMode
		LOCAL lcProps, lcSave, lnLine, la(1)
		WITH THIS
			IF NOT llStoreMode AND ( EMPTY(.ID) OR NOT .NewProps )
				RETURN
			ENDIF
		
			lcSave =''
			FOR lnLine=1 TO ALINES(la,.Props)
				luVal = EVALUATE('.'+la(lnLine))
				TEXT TO lcSave addi
		.<<la(lnLine)>>=<<IIF( VARTYPE(luVal) = 'C', '['+ALLTRIM(luVal)+']', TRANSFORM(luVal))>>
		
				ENDTEXT
			NEXT
			IF llStoreMode
				.Mode = lcSave
				RETURN
			ENDIF
			SELECT Gauges
			IF NOT ID == .ID
				LOCATE FOR ALLTRIM(ID) == .ID
			ENDIF
			REPLACE Mode WITH lcSave, PICTUREVAL WITH .SavedPictureVal
		ENDWITH
		
	ENDPROC

	PROCEDURE _checkmouseposition
	ENDPROC

ENDDEFINE

DEFINE CLASS shapes AS container 
 	*< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" />

	*<DefinedPropArrayMethod>
		*m: clear		&& Clears the contents of a ComboBox or ListBox control.
	*</DefinedPropArrayMethod>

	*<PropValue>
		Height = 43
		Name = "shapes"
		Visible = .F.
		Width = 113
	*</PropValue>
	
	PROCEDURE clear		&& Clears the contents of a ComboBox or ListBox control.
		LOCAL lnLine
		FOR lnLine=THIS.OBJECTS.COUNT TO 1 STEP -1
			THIS.REMOVEOBJECT (THIS.OBJECTS(lnLine).NAME)
		NEXT
		
	ENDPROC

ENDDEFINE

DEFINE CLASS tips AS label 
 	*< CLASSDATA: Baseclass="label" Timestamp="" Scale="Pixels" Uniqueid="" />

	*<DefinedPropArrayMethod>
		*m: evalcaption
		*p: caption1
		*p: caption2
		*p: stringformat
		*p: value		&& Specifies the current state of a control.
	*</DefinedPropArrayMethod>

	*<PropValue>
		AutoSize = .T.
		BackColor = 255,255,228
		Caption = ""
		caption1 = .F.
		caption2 = .F.
		Height = 17
		Name = "tips"
		stringformat = 999 999 999 999.99
		value = .F.
		Width = 0
		WordWrap = .T.
	*</PropValue>
	
	PROCEDURE evalcaption
		WITH THIS
			DO CASE
				CASE VARTYPE(.VALUE) = 'N'
					.CAPTION = IIF(EMPTY(.StringFormat), TRANSFORM(.VALUE), CHRTRAN(ALLTRIM(TRANSFORM( .VALUE, .StringFormat)),[ ],[_]))
				CASE VARTYPE(.VALUE) $ 'CM'
					.CAPTION = .VALUE
				OTHERWISE
					.CAPTION=''
			ENDCASE
			IF NOT EMPTY(.Caption1)
				.CAPTION = IIF(EMPTY(.CAPTION),'' , .CAPTION + CHR(13)+CHR(10)) + TRANSFORM(.Caption1)
			ENDI
			IF NOT EMPTY(.Caption2)
				.CAPTION = IIF(EMPTY(.CAPTION),'' , .CAPTION + CHR(13)+CHR(10)) + TRANSFORM(.Caption2)
			ENDIF
			.WordWrap = CHR(13) $ .Caption
			.Width = 2000
			.AutoSize=.T.
		*	.CAPTION = CHRTRAN(.CAPTION,'_',' ')
		ENDWITH
		
	ENDPROC

ENDDEFINE
