*--------------------------------------------------------------------------------------------------------------------------------------------------------
* (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="" />
*
*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
*
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
*
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 =
_obrush =
_ofont =
_orectangle =
_ostringformat =
_transfcaption =
_value =
_vartype =
_width = 0
*
HIDDEN PROCEDURE caption_assign
LPARAMETERS tuCaption
LOCAL lcType
m.lcType = VARTYPE(m.tuCaption)
IF m.lcType $ "DLTN" && Logical, Date, DateTime, Numeric
m.tuCaption = TRANSFORM(m.tuCaption)
ENDIF
This.Caption = m.tuCaption
This._UpdateMeasures(.F.) && Character passed
*!* C Character, Memo, Varchar, Varchar (Binary)
*!* D Date
*!* G General
*!* L Logical
*!* N Numeric, Float, Double, or Integer
*!* O Object
*!* Q Blob, Varbinary
*!* T DateTime
*!* U Unknown or variable does not exist
*!* X Null
*!* Y Currency
ENDPROC
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="" />
*
*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
*
*
desc =
Height = 23
Name = "fields"
packexpr = .F.
Width = 23
*
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+'^') + [<>]
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="" />
*
*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.
*
*
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.
*
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="" />
*
*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
*
*
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"
*
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
<>
<>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
<>
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([<>])+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
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
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
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
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
<>,<>,<>,<>
<>,<>,<>,<>
<>,<>,<>,<>
<>,<>,<>,<>
<>,<>,<>,<>
<>,<>,<>,<>
ENDTEXT
TEXT TO m.lcFront
<>,<>
<>,<>
<>,<>
<>,<>
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аспознавания конуса
<>,<>,<>,<>,0
<>,<>,<>,<>,<<-lnAngle>>,<<180+lnAngle+lnAngle>>
<>,<>,<>,<>,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
<>, <>, <>, <>
<>,<>,<>,<>,<<90-lnAngle>>,<<180 +lnAngle+lnAngle>>
<>,<>,<>,<>
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
<>,<>,<>,<>,<<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
<>,<>,<>,<>
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
<>,<>,<>,<>,180,180,1
ENDTEXT
TEXT TO lcTopEllipse1
<>,<>,<>,<>,180,-180,1
ENDTEXT
ENDIF
lnHorDelta = (tnWidth - lnTopWidth) / 2
TEXT TO lcFront
<>
<>,<>,<>,<>,0
<>
<>,<>,<>,<>,0
ENDTEXT
TEXT TO lcPoints ADDITIVE
<>,<>,<>,<>,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
<>,<>,<>,<>
ENDTEXT
ELSE
TEXT TO lcLeftEllipsePoint
<>,<>,<>,<>,<<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
<>,<>,<>,<>
<>,<>,<>,<>,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
<>,<>,<>,<>,<<270+lnAngle>>,<<180-lnAngle*2>>,1
<>,<>,<>,<>,0
<>
<>,<>,<>,<>
ENDTEXT
TEXT TO lcFront && points of the front surface
<>,<>,<>,<>,<<270+lnAngle>>,<<-180+lnAngle*2>>,0
<>,<>,<>,<>,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
<>,<>,<>,<>,0, 180
<>,<>,<>,<>
<>,<>,<>,<>,-180,180,1
<>,<>,<>,<>
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
<>,<>,<>,<>
<>,<>,<>,<>, 90, 180
<>,<>,<>,<>
<>,<>,<>,<>, 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
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
ENDTEXT
TEXT TO lcFront
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
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
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
ENDTEXT
TEXT TO lcFront
<>,<>
<>,<>
<>,<>
<>,<>
<>,<>
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>>) : <>, <>, <> <>
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
<>,<>
<>,<>
<>,<>
<>,<