diff --git a/components/jvcllaz/design/JvCustomControls/images/images.txt b/components/jvcllaz/design/JvCustomControls/images/images.txt
index 227b8afdb..88a99214b 100644
--- a/components/jvcllaz/design/JvCustomControls/images/images.txt
+++ b/components/jvcllaz/design/JvCustomControls/images/images.txt
@@ -1,7 +1,6 @@
tjvtabbar.bmp
tjvmoderntabbarpainter.bmp
tjvtabbarxppainter.bmp
-tjvchart.bmp
tjvgammapanel.png
tjvgammapanel_150.png
tjvgammapanel_200.png
diff --git a/components/jvcllaz/design/JvCustomControls/images/tjvchart.bmp b/components/jvcllaz/design/JvCustomControls/images/tjvchart.bmp
deleted file mode 100644
index dadad9636..000000000
Binary files a/components/jvcllaz/design/JvCustomControls/images/tjvchart.bmp and /dev/null differ
diff --git a/components/jvcllaz/design/JvCustomControls/jvcustomreg.pas b/components/jvcllaz/design/JvCustomControls/jvcustomreg.pas
index 728dcb011..a1fe21a5a 100644
--- a/components/jvcllaz/design/JvCustomControls/jvcustomreg.pas
+++ b/components/jvcllaz/design/JvCustomControls/jvcustomreg.pas
@@ -22,8 +22,7 @@ uses
// JvTabBar, JvTabBarXPPainter,
JvThumbImage, JvThumbnails, JvThumbViews,
JvTimeLine, JvTMTimeLine, JvTimeLineEditor,
- JvImagesViewer, JvImageListViewer, JvOwnerDrawViewer,
- JvChart;
+ JvImagesViewer, JvImageListViewer, JvOwnerDrawViewer;
procedure Register;
begin
@@ -34,8 +33,7 @@ begin
TJvThumbView, TJvThumbnail, TJvThumbImage,
TJvTimeLine, TJvTMTimeLine,
TJvGammaPanel,
- TJvImagesViewer, TJvImageListViewer, TJvOwnerDrawViewer,
- TJvChart
+ TJvImagesViewer, TJvImageListViewer, TJvOwnerDrawViewer
]);
// Timeline
diff --git a/components/jvcllaz/examples/JvChartDemo/JvChartDemo.lpi b/components/jvcllaz/examples/JvChartDemo/JvChartDemo.lpi
deleted file mode 100644
index eac80a3b3..000000000
--- a/components/jvcllaz/examples/JvChartDemo/JvChartDemo.lpi
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/components/jvcllaz/examples/JvChartDemo/JvChartDemo.lpr b/components/jvcllaz/examples/JvChartDemo/JvChartDemo.lpr
deleted file mode 100644
index 188fba0f3..000000000
--- a/components/jvcllaz/examples/JvChartDemo/JvChartDemo.lpr
+++ /dev/null
@@ -1,20 +0,0 @@
-program JvChartDemo;
-
-{$MODE OBJFPC}{$H+}
-
-uses
- Interfaces,
- Forms, printer4lazarus,
- JvChartDemoFm in 'JvChartDemoFm.pas' {JvChartDemoForm},
- StatsClasses in 'StatsClasses.pas', jvPenEditor;
-
-{$R *.res}
-
-
-begin
- Application.Initialize;
- Application.Title:='JvChartDemo';
- Application.Scaled := true;
- Application.CreateForm(TJvChartDemoForm, JvChartDemoForm);
- Application.Run;
-end.
diff --git a/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.lfm b/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.lfm
deleted file mode 100644
index 768f31efb..000000000
--- a/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.lfm
+++ /dev/null
@@ -1,621 +0,0 @@
-object JvChartDemoForm: TJvChartDemoForm
- Left = 436
- Height = 453
- Top = 278
- Width = 785
- Caption = 'JEDI JvChart Demo'
- ClientHeight = 433
- ClientWidth = 785
- Color = clWindow
- Menu = MainMenu1
- OnCreate = FormCreate
- OnDestroy = FormDestroy
- OnResize = FormResize
- Position = poScreenCenter
- LCLVersion = '2.1.0.0'
- object Chart: TJvChart
- Left = 164
- Height = 398
- Top = 35
- Width = 621
- Align = alClient
- Options.XAxisValuesPerDivision = 10
- Options.XAxisLabelAlignment = taLeftJustify
- Options.XAxisDateTimeMode = False
- Options.XAxisDateTimeDivision = 0
- Options.XAxisLegendSkipBy = 2
- Options.PenCount = 3
- Options.XGap = 0
- Options.XOrigin = 0
- Options.YOrigin = 0
- Options.XStartOffset = 60
- Options.PrimaryYAxis.YMax = 20
- Options.PrimaryYAxis.YMin = 0
- Options.PrimaryYAxis.YLegendDecimalPlaces = 1
- Options.SecondaryYAxis.YMax = 140
- Options.SecondaryYAxis.YMin = 0
- Options.SecondaryYAxis.YLegendDecimalPlaces = 0
- Options.SecondaryYAxis.DefaultYLegends = 60
- Options.MouseDragObjects = False
- Options.Legend = clChartLegendBelow
- Options.LegendRowCount = 1
- Options.XValueCount = 20
- Options.HeaderFont.Color = clWindowText
- Options.LegendFont.Color = clWindowText
- Options.AxisFont.Color = clWindowText
- Options.AxisTitleFont.Height = -16
- Options.AxisTitleFont.Orientation = 900
- Options.AxisTitleFont.Style = [fsBold]
- Options.CursorColor = clBlack
- Options.CursorStyle = psDot
- OnBeginFloatingMarkerDrag = ChartBeginFloatingMarkerDrag
- OnEndFloatingMarkerDrag = ChartEndFloatingMarkerDrag
- end
- object Splitter1: TSplitter
- Left = 159
- Height = 398
- Top = 35
- Width = 5
- end
- object PanelTop: TPanel
- Left = 0
- Height = 35
- Top = 0
- Width = 785
- Align = alTop
- ClientHeight = 35
- ClientWidth = 785
- Font.CharSet = ANSI_CHARSET
- Font.Color = clWindowText
- Font.Height = -13
- Font.Name = 'Verdana'
- ParentFont = False
- TabOrder = 0
- object ButtonBarChart: TSpeedButton
- Left = 5
- Height = 25
- Hint = 'Bar Chart'
- Top = 5
- Width = 25
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 04000000000000010000120B0000120B00001000000000000000000000000000
- 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333300030003
- 0003333377737773777333333333333333333FFFFFFFFFFFFFFF770000000000
- 0000777777777777777733039993BBB3CCC3337F737F737F737F37039993BBB3
- CCC3377F737F737F737F33039993BBB3CCC33F7F737F737F737F77079997BBB7
- CCC77777737773777377330399930003CCC3337F737F7773737F370399933333
- CCC3377F737F3333737F330399933333CCC33F7F737FFFFF737F770700077777
- CCC77777777777777377330333333333CCC3337F33333333737F370333333333
- 0003377F33333333777333033333333333333F7FFFFFFFFFFFFF770777777777
- 7777777777777777777733333333333333333333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonBarChartClick
- ShowHint = True
- ParentShowHint = False
- end
- object ButtonLine: TSpeedButton
- Left = 58
- Height = 25
- Hint = 'Line Chart'
- Top = 5
- Width = 25
- Down = True
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 04000000000000010000120B0000120B00001000000000000000000000000000
- 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00337333733373
- 3373337F3F7F3F7F3F7F33737373737373733F7F7F7F7F7F7F7F770000000000
- 000077777777777777773303333333333333337FF333333F33333709333333C3
- 333337773F3FF373F333330393993C3C33333F7F7F77F7F7FFFF77079797977C
- 77777777777777777777330339339333C333337FF73373F37F33370C333C3933
- 933337773F3737F37FF33303C3C33939C9333F7F7F7FF7F777FF7707C7C77797
- 7C97777777777777777733033C3333333C33337F37F33333373F37033C333333
- 33C3377F37333333337333033333333333333F7FFFFFFFFFFFFF770777777777
- 7777777777777777777733333333333333333333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonLineClick
- ShowHint = True
- ParentShowHint = False
- end
- object ButtonStackedBarAve: TSpeedButton
- Left = 345
- Height = 25
- Hint = 'Stacked Bars with Average'
- Top = 7
- Width = 25
- Enabled = False
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 0400000000000001000000000000000000001000000000000000000000000000
- 80000080000000808000800000008000800080800000C0C0C000808080000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333300030003
- 0003333388838883888333333333333333333FFFFFFFFFFFFFFF880000000000
- 000088888888888888883303999399939993338F838F838F838F38039993BBB3
- 9993388F838F838F838F3303BBB3BBB399933F8F838F838F838F8808BBB8AAA8
- 999888888388838883883303AAA300039993338F838F8883838F3803AAA30003
- BBB3388F838F3333838F3303AAA30003BBB33F8F838FFFFF838F880800080008
- BBB88888888888888388330300030003AAA3338F33333333838F380300030003
- 0003388F33333333888333030003000300033F8FFFFFFFFFFFFF880888888888
- 8888888888888888888833333333333333333333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonStackedBarAveClick
- ShowHint = True
- ParentShowHint = False
- end
- object ButtonStackedBar: TSpeedButton
- Left = 111
- Height = 25
- Hint = 'Stacked Bars'
- Top = 5
- Width = 26
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 0400000000000001000000000000000000001000000000000000000000000000
- 80000080000000808000800000008000800080800000C0C0C000808080000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333300030003
- 0003333388838883888333333333333333333FFFFFFFFFFFFFFF880000000000
- 000088888888888888883303999399939993338F838F838F838F38039993BBB3
- BBB3388F838F838F838F3303BBB3BBB3BBB33F8F838F838F838F8808BBB8AAA8
- BBB888888388838883883303AAA30003BBB3338F838F8883838F3803AAA33333
- BBB3388F838F3333838F3303AAA33333BBB33F8F838FFFFF838F880800088888
- BBB88888888888888388330333333333AAA3338F33333333838F380333333333
- 0003388F33333333888333033333333333333F8FFFFFFFFFFFFF880888888888
- 8888888888888888888833333333333333333333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonStackedBarClick
- ShowHint = True
- ParentShowHint = False
- end
- object ButtonBarAve: TSpeedButton
- Left = 32
- Height = 25
- Hint = 'Bar Chart with Average Line'
- Top = 5
- Width = 25
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 0400000000000001000000000000000000001000000000000000000000000000
- 80000080000000808000800000008000800080800000C0C0C000808080000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333300030003
- 0003333388838883888333333333333333333FFFFFFFFFFFFFFF880000000000
- 0000888888888888888833039BA39BA39BA3338F838F838F838F38039BA39BA3
- 9BA3388F838F838F838F33039BA39BA39BA33F8F838F838F838F88089BA89BA8
- 9BA8888883888388838833039BA390A39BA3338F838F8883838F38039BA30B03
- 9BA3388F838F3333838F33039BA03B309BA33F8F838FFFFF838F88089B088B88
- 0BA8888888888888838833039033333390A3338F33333333838F380393333333
- 9BA3388F3333333388833303333333333B333F8FFFFFFFFFFFFF880888888888
- 8B88888888888888888833333333333333333333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonBarAveClick
- ShowHint = True
- ParentShowHint = False
- end
- object ButtonPie: TSpeedButton
- Left = 371
- Height = 25
- Hint = 'Show Pie Chart (one series only)'
- Top = 7
- Width = 25
- Enabled = False
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 04000000000000010000120B0000120B00001000000000000000000000000000
- 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
- 3333333333FFFFF3333333333700073333333FFF3777773F3FFF00030990BB03
- 000077737337F373777733309990BBB0333333373337F3373F3333099990BBBB
- 033333733337F33373F337999990BBBBB73337F33337F33337F330999990BBBB
- B03337F33337FFFFF7F3309999900000003337F33337777777F33099990A0CCC
- C03337F3337373F337F3379990AAA0CCC733373F3733373F373333090AAAAA0C
- 033333737333337373333330AAAAAAA033333FF73F33333733FF00330AAAAA03
- 3000773373FFFF73377733333700073333333333377777333333333333333333
- 3333333333333333333333333333333333333333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonPieClick
- ShowHint = True
- ParentShowHint = False
- end
- object ButtonMarkers: TSpeedButton
- Left = 291
- Height = 25
- Hint = 'Show Markers'
- Top = 7
- Width = 25
- Enabled = False
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 0400000000000001000000000000000000001000000000000000000000000000
- 80000080000000808000800000008000800080800000C0C0C000808080000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00338333833383
- 3383338F3F8F3F8F3F8F33838383838383833F8F8F8F8F8F8F8F880000000000
- 000088888888888888883303333333333333338F33333333333338033393A333
- 333A388833333333333333033C333C3333333F8FFFFFFFFFFFFF88088888988C
- 888A88888888888888883303333333333333338F333333333333380A33A33333
- 3333388833333333333333033333333A33333F8FFFFFFFFFFFFF880888888898
- 889888888888888888883303933C33333333338F333333333333380333333333
- 3A33388F3333333333333303C333333333333F8FFFFFFFFFFFFF880888888888
- 8888888888888888888833333333333333333333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonMarkersClick
- ShowHint = True
- ParentShowHint = False
- end
- object ButtonDeltaAverage: TSpeedButton
- Left = 319
- Height = 25
- Hint = 'Delta Average'
- Top = 7
- Width = 25
- Enabled = False
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 0400000000000001000000000000000000001000000000000000000000000000
- 80000080000000808000800000008000800080800000C0C0C000808080000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333300030003
- 0003333388838883888333333333333333333FFFFFFFFFFFFFFF888000000000
- 0000888888888888888833333333033333333333333F33333333333333330333
- 33333333333F3333333333CCCCCC033333333333333F3333333388CCCCCC0333
- 33333333333F3333333333333333033333333333333F33333333333333330AAA
- A3333333333F33333333333333330AAAA3333333333F33333333833333330333
- 33333333333F3333333333333333099999993333333F33333333333333330999
- 99993333333F3333333333333333033333333FFFFFFFFFFFFFFF888000000000
- 0000888888888888888833333333333333333333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonDeltaAverageClick
- ShowHint = True
- ParentShowHint = False
- end
- object ButtonLineMarker: TSpeedButton
- Left = 84
- Height = 25
- Hint = 'Line with Markers'
- Top = 5
- Width = 25
- Flat = True
- Glyph.Data = {
- 76010000424D7601000000000000760000002800000020000000100000000100
- 04000000000000010000120B0000120B00001000000000000000000000000000
- 800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00337333733373
- 3373337F3F7F3F7F3F7F33737373737373733F7F7F7F7F7F7F7F770000000000
- 000077777777777777773303333333333333337FF333333F33333709333333C3
- 333337773F3FF373F333330393993C3C33333F7F7F77F7F7FFFF77079797977C
- 77777777777777777777330339339333C333337FF73373F37F33370C333C3933
- 933337773F3737F37FF33303C3C33939C9333F7F7F7FF7F777FF7707C7C79797
- 7C97777777777777777733033C3393933C33337F37F33333373F37033C333933
- 33C3377F3733333333733303CCC3393333C33F7FFFFFFFFFFFFF77077C777777
- 7CCC777777777777777733333333333333C33333333333333333
- }
- GroupIndex = 1
- NumGlyphs = 2
- OnClick = ButtonLineMarkerClick
- ShowHint = True
- ParentShowHint = False
- end
- object Label1: TLabel
- Left = 398
- Height = 16
- Top = 10
- Width = 210
- Caption = '(TODO: Fix broken chart types)'
- Enabled = False
- ParentColor = False
- end
- object SpeedButtonTestMouseOver: TSpeedButton
- Left = 139
- Height = 25
- Hint = 'Floating Markers Demo (new JAN 2005!)'
- Top = 5
- Width = 26
- Flat = True
- Glyph.Data = {
- F6000000424DF600000000000000760000002800000010000000100000000100
- 0400000000008000000000000000000000001000000000000000000000000000
- 8000008000000080800080000000800080008080000080808000C0C0C0000000
- FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00D88888888888
- 888D79FFFFFFFFFFFF98999FFFFFFFFFF99979CFFFFFFFFFCF987FFCFFFFFFFF
- CFF87FFCFFFFFFFCFFF87FFCFFFFFFFCFFF87FFFCFFFFFCFFFF87FFFCFFFFFCF
- FFF87FFFCFFFFFCFFFF87FFFFCFFFCFFFFF87FFFFCFFFCFFFFF87FFFFFCFFCFF
- FFF87FFFFFC9CFFFFFF87FFFFF999FFFFFF8D77777797777777D
- }
- GroupIndex = 1
- OnClick = SpeedButtonTestMouseOverClick
- ShowHint = True
- ParentShowHint = False
- end
- object SpinEdit1: TSpinEdit
- Left = 656
- Height = 24
- Top = 6
- Width = 66
- MaxValue = 1000
- OnChange = SpinEdit1Change
- TabOrder = 0
- end
- end
- object ListBox1: TListBox
- Left = 0
- Height = 398
- Top = 35
- Width = 159
- Align = alLeft
- Color = clBtnFace
- Font.Color = clWindowText
- Font.Height = -11
- Font.Name = 'Courier New'
- Items.Strings = (
- ''
- )
- ItemHeight = 14
- OnClick = ListBox1Click
- OnDblClick = ListBox1DblClick
- ParentFont = False
- TabOrder = 1
- Visible = False
- end
- object ColorDialog1: TColorDialog
- Color = clBlack
- CustomColors.Strings = (
- 'ColorA=000000'
- 'ColorB=000080'
- 'ColorC=008000'
- 'ColorD=008080'
- 'ColorE=800000'
- 'ColorF=800080'
- 'ColorG=808000'
- 'ColorH=808080'
- 'ColorI=C0C0C0'
- 'ColorJ=0000FF'
- 'ColorK=00FF00'
- 'ColorL=00FFFF'
- 'ColorM=FF0000'
- 'ColorN=FF00FF'
- 'ColorO=FFFF00'
- 'ColorP=FFFFFF'
- 'ColorQ=C0DCC0'
- 'ColorR=F0CAA6'
- 'ColorS=F0FBFF'
- 'ColorT=A4A0A0'
- )
- left = 504
- top = 160
- end
- object FontDialog1: TFontDialog
- Font.Color = clWindowText
- Font.Height = -13
- Font.Name = 'System'
- MinFontSize = 0
- MaxFontSize = 0
- Options = []
- left = 592
- top = 160
- end
- object MainMenu1: TMainMenu
- left = 464
- top = 48
- object Demo1: TMenuItem
- Caption = '&Demo'
- object MenuItem2: TMenuItem
- Caption = '-'
- end
- object mnuSetTitle: TMenuItem
- Caption = 'Set Title...'
- OnClick = mnuSetTitleClick
- end
- object mnuSetXAxisHeader: TMenuItem
- Caption = 'Set X Axis Header...'
- OnClick = mnuSetXAxisHeaderClick
- end
- object mnuSetYAxisHeader: TMenuItem
- Caption = 'Set Y Axis Header...'
- OnClick = mnuSetYAxisHeaderClick
- end
- object MenuItem3: TMenuItem
- Caption = '-'
- end
- object mnuFonts: TMenuItem
- Caption = 'Fonts'
- object mnuSetHeaderFont: TMenuItem
- Caption = 'Set Header Font...'
- OnClick = mnuSetHeaderFontClick
- end
- object mnuSetAxisTitlefont: TMenuItem
- Caption = 'Set Axis Title Font...'
- OnClick = mnuSetAxisTitlefontClick
- end
- object mnuSetAxisFont: TMenuItem
- Caption = 'Set Axis Label Font...'
- OnClick = mnuSetAxisFontClick
- end
- object mnuSetLegendFont: TMenuItem
- Caption = 'Set Legend Font...'
- OnClick = mnuSetLegendFontClick
- end
- end
- object mnuColors: TMenuItem
- Caption = 'Colors'
- object mnuSetPaperColor: TMenuItem
- Caption = 'Set Paper Color...'
- OnClick = mnuSetPaperColorClick
- end
- object mnuSetDivisionLineColor: TMenuItem
- Caption = 'Set Division Line Color...'
- OnClick = mnuSetDivisionLineColorClick
- end
- object mnuSetShadowColor: TMenuItem
- Caption = 'Set Shadow Color..'
- OnClick = mnuSetShadowColorClick
- end
- object mnuSetCursorColor: TMenuItem
- Caption = 'Set Cursor Color...'
- OnClick = mnuSetCursorColorClick
- end
- object mnuSetHintColor: TMenuItem
- Caption = 'Set Hint Color...'
- OnClick = mnuSetHintColorClick
- end
- end
- object mnuSetLineWidths: TMenuItem
- Caption = 'Line Widths'
- object mnuSetAxisLineWidth: TMenuItem
- Caption = 'Set Axis Line Width...'
- OnClick = mnuSetAxisLineWidthClick
- end
- object mnuSetPenLineWidth: TMenuItem
- Caption = 'Set Pen Line Width...'
- OnClick = mnuSetPenLineWidthClick
- end
- end
- object mnuPens: TMenuItem
- Caption = 'Pens...'
- OnClick = mnuPensClick
- end
- object mnuSetMarkerSize: TMenuItem
- Caption = 'Marker Size...'
- OnClick = mnuSetMarkerSizeClick
- end
- object mnuFillUnderLine: TMenuItem
- Caption = 'Fill under line'
- OnClick = mnuFillUnderLineClick
- end
- object mnuLegend: TMenuItem
- Caption = 'Legend'
- object mnuLegendNone: TMenuItem
- Caption = 'None'
- GroupIndex = 113
- OnClick = mnuLegenClick
- end
- object mnuLegendRight: TMenuItem
- Caption = 'Right'
- GroupIndex = 113
- OnClick = mnuLegenClick
- end
- object mnuLegendBelow: TMenuItem
- Caption = 'Below'
- Checked = True
- GroupIndex = 113
- OnClick = mnuLegenClick
- end
- end
- object mnuSetXStartOffset: TMenuItem
- Caption = 'X Start Offset...'
- OnClick = mnuSetXStartOffsetClick
- end
- object N2: TMenuItem
- Caption = '-'
- end
- object mnuScrolling: TMenuItem
- Caption = 'Scrolling'
- ShortCut = 16467
- OnClick = mnuScrollingClick
- end
- object CopyToClipboard1: TMenuItem
- Caption = 'Copy To Clipboard'
- ShortCut = 16451
- OnClick = CopyToClipboard1Click
- end
- object Print1: TMenuItem
- Caption = 'Print Chart to Printer'
- ShortCut = 16464
- OnClick = Print1Click
- end
- object PrintOptions1: TMenuItem
- Caption = '&Print Options'
- OnClick = PrintOptions1Click
- end
- object N1: TMenuItem
- Caption = '-'
- end
- object Generatenewrandomvalues1: TMenuItem
- Caption = '&Generate new random values'
- ShortCut = 16466
- OnClick = Generatenewrandomvalues1Click
- end
- object ShowgapinLineChart1: TMenuItem
- Caption = '&Show gap in Line Chart'
- ShortCut = 16455
- OnClick = ShowgapinLineChart1Click
- end
- object mnuDateTimeAxisMode: TMenuItem
- Caption = 'Date/Time Axis Mode'
- OnClick = mnuDateTimeAxisModeClick
- end
- object MenuNegValueTest: TMenuItem
- AutoCheck = True
- Caption = 'Use Positive and Negative Demo Values (-20..+20)'
- OnClick = MenuNegValueTestClick
- end
- object mnuSecondaryAxisMode: TMenuItem
- Caption = '&Plot Markers+Values using Alternate Scale (0-120%)'
- OnClick = mnuSecondaryAxisModeClick
- end
- object N4: TMenuItem
- Caption = '-'
- end
- object ShowDataInListbox1: TMenuItem
- Caption = '&Show Data in listbox'
- ShortCut = 16452
- OnClick = ShowDataInListbox1Click
- end
- object LargeDataset576samples1: TMenuItem
- Caption = '&Large Dataset (576 samples)'
- ShortCut = 16460
- OnClick = LargeDataset576samples1Click
- end
- object NewFeaturesfor20071: TMenuItem
- Caption = 'New Features for 2007'
- OnClick = NewFeaturesfor20071Click
- end
- end
- object Help1: TMenuItem
- Caption = '&Help'
- object About1: TMenuItem
- Caption = '&About JvChart Component'
- ShortCut = 16449
- OnClick = About1Click
- end
- end
- end
- object Timer1: TTimer
- Enabled = False
- Interval = 100
- OnTimer = Timer1Timer
- left = 344
- top = 48
- end
- object PrinterSetupDialog1: TPrinterSetupDialog
- left = 264
- top = 160
- end
- object PrintDialog1: TPrintDialog
- left = 392
- top = 160
- end
-end
diff --git a/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.pas b/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.pas
deleted file mode 100644
index 65e95e6fa..000000000
--- a/components/jvcllaz/examples/JvChartDemo/jvchartdemofm.pas
+++ /dev/null
@@ -1,1046 +0,0 @@
-{-----------------------------------------------------------------------------
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/MPL-1.1.html
-
-Software distributed under the License is distributed on an "AS IS" basis,
-WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
-the specific language governing rights and limitations under the License.
-
-The Original Code is: JvChartDemoFm.Pas, released on 2002-10-04.
-
-The Initial Developer of the Original Code is AABsoft and MÃ¥rten Henrichson.
-(C) 1996 AABsoft and MÃ¥rten Henrichson.
-All Rights Reserved.
-
-Contributor(s): -
-
-Last Modified: 2005-01-14
-
- Modified March 2007 by Warren Postma - Show new JvChart 2007 Features.
-
-
-You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
-located at http://jvcl.delphi-jedi.org
-
-Description:
- BAR/LINE Charting Component for JEDI [Updated March 2007]
-
-Known Issues:
------------------------------------------------------------------------------}
-
-{$MODE OBJFPC}{$H+}
-
-unit JvChartDemoFm;
-
-interface
-
-uses
- SysUtils, Classes, Graphics, Controls, Menus,
- Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, Spin, PrintersDlgs,
- JvChart, StatsClasses;
-
-type
-
- { TJvChartDemoForm }
-
- TJvChartDemoForm = class(TForm)
- mnuSetTitle: TMenuItem;
- mnuFillUnderLine: TMenuItem;
- mnuLegendNone: TMenuItem;
- mnuLegendRight: TMenuItem;
- mnuLegendBelow: TMenuItem;
- mnuLegend: TMenuItem;
- mnuSetXStartOffset: TMenuItem;
- mnuSetPenLineWidth: TMenuItem;
- mnuSetAxisLineWidth: TMenuItem;
- mnuSetLineWidths: TMenuItem;
- mnuSetHintColor: TMenuItem;
- mnuSetCursorColor: TMenuItem;
- mnuPens: TMenuItem;
- mnuSetPaperColor: TMenuItem;
- mnuSetShadowColor: TMenuItem;
- mnuFonts: TMenuItem;
- mnuSetDivisionLineColor: TMenuItem;
- mnuColors: TMenuItem;
- MenuItem3: TMenuItem;
- mnuSetMarkerSize: TMenuItem;
- mnuSetYAxisHeader: TMenuItem;
- mnuSetXAxisHeader: TMenuItem;
- MenuItem2: TMenuItem;
- mnuSetAxisTitlefont: TMenuItem;
- mnuSetLegendFont: TMenuItem;
- mnuSetHeaderFont: TMenuItem;
- PanelTop: TPanel;
- ButtonBarChart: TSpeedButton;
- ButtonLine: TSpeedButton;
- ButtonStackedBarAve: TSpeedButton;
- ButtonStackedBar: TSpeedButton;
- ButtonBarAve: TSpeedButton;
- ColorDialog1: TColorDialog;
- ButtonPie: TSpeedButton;
- FontDialog1: TFontDialog;
- ButtonMarkers: TSpeedButton;
- ButtonDeltaAverage: TSpeedButton;
- Chart: TJvChart;
- ButtonLineMarker: TSpeedButton;
- Label1: TLabel;
- MainMenu1: TMainMenu;
- Demo1: TMenuItem;
- Help1: TMenuItem;
- About1: TMenuItem;
- ShowgapinLineChart1: TMenuItem;
- N1: TMenuItem;
- Print1: TMenuItem;
- Generatenewrandomvalues1: TMenuItem;
- CopyToClipboard1: TMenuItem;
- N2: TMenuItem;
- mnuSetAxisFont: TMenuItem;
- mnuScrolling: TMenuItem;
- ListBox1: TListBox;
- SpinEdit1: TSpinEdit;
- Splitter1: TSplitter;
- Timer1: TTimer;
- ShowDataInListbox1: TMenuItem;
- N4: TMenuItem;
- LargeDataset576samples1: TMenuItem;
- mnuDateTimeAxisMode: TMenuItem;
- PrintOptions1: TMenuItem;
- PrinterSetupDialog1: TPrinterSetupDialog;
- PrintDialog1: TPrintDialog;
- mnuSecondaryAxisMode: TMenuItem;
- MenuNegValueTest: TMenuItem;
- SpeedButtonTestMouseOver: TSpeedButton;
- NewFeaturesfor20071: TMenuItem;
- procedure FormResize(Sender: TObject);
- procedure ButtonLineClick(Sender: TObject);
- procedure ButtonBarChartClick(Sender: TObject);
- procedure ButtonStackedBarAveClick(Sender: TObject);
- procedure ButtonStackedBarClick(Sender: TObject);
- procedure mnuFillUnderLineClick(Sender: TObject);
- procedure mnuLegenClick(Sender: TObject);
- procedure mnuSetAxisLineWidthClick(Sender: TObject);
- procedure mnuSetCursorColorClick(Sender: TObject);
- procedure mnuSetHintColorClick(Sender: TObject);
- procedure mnuSetPenLineWidthClick(Sender: TObject);
- procedure mnuSetTitleClick(Sender: TObject);
- procedure mnuSetXStartOffsetClick(Sender: TObject);
- procedure SpeedButton7Click(Sender: TObject);
- procedure ButtonBarAveClick(Sender: TObject);
- procedure SpinEdit1Change(Sender: TObject);
- procedure Button2Click(Sender: TObject);
- procedure ButtonPieClick(Sender: TObject);
- procedure Button4Click(Sender: TObject);
- procedure ButtonMarkersClick(Sender: TObject);
- procedure ButtonDeltaAverageClick(Sender: TObject);
- procedure ButtonLineMarkerClick(Sender: TObject);
- procedure Panel2DblClick(Sender: TObject);
- procedure ShowgapinLineChart1Click(Sender: TObject);
- procedure Print1Click(Sender: TObject);
- procedure Generatenewrandomvalues1Click(Sender: TObject);
- procedure CopyToClipboard1Click(Sender: TObject);
- procedure About1Click(Sender: TObject);
- procedure mnuScrollingClick(Sender: TObject);
- procedure Timer1Timer(Sender: TObject);
- procedure ShowDataInListbox1Click(Sender: TObject);
- procedure LargeDataset576samples1Click(Sender: TObject);
- procedure mnuDateTimeAxisModeClick(Sender: TObject);
-
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
-
- procedure PrintOptions1Click(Sender: TObject);
- procedure mnuSecondaryAxisModeClick(Sender: TObject);
-
- procedure ListBox1Click(Sender: TObject);
- procedure ListBox1DblClick(Sender: TObject);
-
- procedure mnuSetAxisFontClick(Sender: TObject);
- procedure mnuSetAxisTitlefontClick(Sender: TObject);
- procedure mnuSetHeaderFontClick(Sender: TObject);
- procedure mnuSetLegendFontClick(Sender: TObject);
- procedure mnuSetMarkerSizeClick(Sender: TObject);
- procedure mnuSetPaperColorClick(Sender: TObject);
- procedure mnuPensClick(Sender: TObject);
- procedure mnuSetShadowColorClick(Sender: TObject);
- procedure mnuSetXAxisHeaderClick(Sender: TObject);
- procedure mnuSetYAxisHeaderClick(Sender: TObject);
-
- procedure mnuSetDivisionLineColorClick(Sender: TObject);
- procedure mnuSetPenCountClick(Sender: TObject);
-
- procedure MenuNegValueTestClick(Sender: TObject);
- procedure SpeedButtonTestMouseOverClick(Sender: TObject);
- procedure ChartEndFloatingMarkerDrag(Sender: TJvChart;
- FloatingMarker: TJvChartFloatingMarker);
- procedure ChartBeginFloatingMarkerDrag(Sender: TJvChart;
- FloatingMarker: TJvChartFloatingMarker);
- procedure NewFeaturesfor20071Click(Sender: TObject);
- private
-
- // Our waveform generator uses the following as state-variables:
- FGenerationIndex: Integer;
- Foo, Foo1, Foo2: Integer;
- Fhgt, Fhg0, Fhg2p: Double;
- FStatHgt, FStatHg0: TStatArray;
- Fdt, Fds: Double;
- FNegValueFlag: Boolean;
-
- protected
- procedure _Generate;
- procedure _StoreValue(I: integer);
- function _QAProblemScatter: Integer;
- procedure MakePensMenu;
-
- public
- procedure NewValues;
- end;
-
-var
- JvChartDemoForm: TJvChartDemoForm;
-
-implementation
-
-uses
- LCLIntf, // OpenURL
- LCLType, // MB_OK
- Math, // Math:NaN handling, function isNan in D6 and higher.
- JvPenEditor;
-
-{$R *.lfm}
-
-const
- TAG_PENCOLORS = 991;
- MAX_PEN = 100;
-
-
-{ Bogus vageuly sinusoidal signal generator }
-
-procedure TJvChartDemoForm._Generate;
-begin
- FHgt := Abs(Random(80) + (Random(((FGenerationIndex div foo) mod foo1) * 250) * 5 + 9500));
- FHg0 := Abs(Random(280) + Random(((FGenerationIndex div foo) mod foo2) * 650) * 5 + 1003);
- if FNegValueFlag then
- begin
- if (Random(80) > 75) or (FGenerationIndex = 2) then
- begin
- FHg0 := -1 * FHg0; // Generate a negative value! (just to show what it looks like)
- end;
- end;
- Inc(FGenerationIndex);
-end;
-
-{ Bogus random spiky-looking function to simulate a QA value,
- which hovers within +/- 10% of perfect (100%), but
- with relatively infrequent spiky errors }
-
-function TJvChartDemoForm._QAProblemScatter: Integer;
-var
- n, m: Double;
-begin
- n := Log10(Random(10000) + 1); // Random is my favourite function. How about you? -WP
- n := n * Log10(Random(10000) + 1);
- m := Log10(Random(10000) + 1);
- m := m * Log10(Random(10000) + 1);
- n := Abs(100 + n - m);
- if (n < 0) then
- n := 0;
- if (n > 150) then
- n := 150;
-
- Result := Round(n);
-end;
-
-procedure TJvChartDemoForm._StoreValue(I: integer);
-begin
- FStatHgt.AddValue(Fhgt);
- FStatHg0.AddValue(Fhg0);
-
- // PAY ATTENTION HERE, this is where we set the Chart.Data.Value[ index,pen] :=
- // stuff which is the MOST IMPORTANT THING, unless you like blank charts:
-
- // Set Data.Value[Pen, Series] := dataValue ...
- Chart.Data.Value[0, I] := FStatHgt.Average / 1000;
-
- if FHg0 < 0 then
- begin
- Chart.Data.Value[1, I] := FHg0 / 1000;
- // Don't show average with negative samples or my negative demo ability goes away (averaged out!)
- end
- else
- begin
- // Test blanks on big chart, show missing data:
- Chart.Data.Value[1, I] := FStatHg0.Average / 1000;
- end;
-
- Fhg2p := (FStatHgt.Average - FStatHg0.Average) / 1000;
- if Fhg2p < 0.0 then
- Fhg2p := 0.0;
- Chart.Data.Value[2, I] := Fhg2p;
-
- Fds := Fdt + (FGenerationIndex / 576);
-
- // There are TWO ways to get an X Axis label plotted:
- if mnuDateTimeAxisMode.Checked then
- Chart.Data.Timestamp[I] := Fds // X legends generated by timestamps
- else
- // X Legends generated by user are used by default.
- // This would be redundant, and would be a waste of memory
- // if Chart.Options.XAxisDateTimeMode was also set.
- Chart.Options.XLegends.Add(FormatDateTime('hh:nn:ss', Fds));
-
- if mnuSecondaryAxisMode.Checked then
- begin
- if I = 1 then
- Chart.Data.Value[3, I] := 100
- else
- if (I mod 4) = 3 then
- begin
- //Chart.Data.Value[3,I] := 1+ ((I mod 12) * 10) // stairstep
- //random:
- Chart.Data.Value[3, I] := _QAProblemScatter;
- end
- else
- Chart.Data.Value[3, I] := NaN; // leave some blanks.
- end;
-end;
-
-procedure TJvChartDemoForm.NewFeaturesfor20071Click(Sender: TObject);
-var
- vbar:TJvChartVerticalBar;
- hbar:TJvChartHorizontalBar;
-begin
- // Try out new features for 2007:
-
- // Gradients.
- Chart.Options.GradientColor := $00FDEEDB; // powder blue (baby blue) mostly white.
- Chart.Options.GradientDirection :=grDown;
-
-
-
- // Vertical Bar.
- vbar := Chart.AddVerticalBar;
- vbar.Color := $00FDDDC7;
- vbar.Visible := true;
- vbar.XLeft := 6;
- vbar.XRight := 7;
-
- // Horizontal Bar.
- hbar := Chart.AddHorizontalBar;
- hbar.Color := $007CCAC7;
- hbar.Visible := true;
- hbar.YTop := 3;
- hbar.YBottom := 2;
-
-
-
-
-
- // Lots of things not shown here are new in 2007:
- // Floating Marker Count, Delete a floating marker, etc,
- // search for 'NEW 2007' in JvChart.pas for a complete
- // look at new things.
-
- // last thing, always update graph:
- Chart.PlotGraph;
- //Chart.Refresh;
-
-
-end;
-
-procedure TJvChartDemoForm.NewValues;
-var
- I: Integer;
- nValueCount: Integer;
-begin
-//Chart.Options.Title := 'Click on the Chart Title to change it!';
- Chart.Options.PenCount := 3;
-
- Chart.ClearFloatingMarkers; // remove any previous markers.
-
-
- ListBox1.Clear;
- Chart.Data.Clear;
-
- Chart.Options.PrimaryYAxis.YMax := 20;
-
- Randomize;
-
- Chart.Options.XAxisDateTimeMode := mnuDateTimeAxisMode.Checked; // Use datetime timestamp labels, just Fer Instance.
-
- if not Chart.Options.XAxisDateTimeMode then
- Chart.Options.XAxisLegendSkipBy := 5;
-
- if LargeDataset576samples1.Checked then
- begin
- // A larger bogus data set for demonstration purposes.
- nValueCount := 576; // 2.5 minute sample period, 576 samples = 1 day.
- foo := 5; // Used in generating our bogus data below, not really important.
- Chart.Options.XAxisValuesPerDivision := 24;
- // 24 samples * 150 seconds = 1 hour time divisions ( Chart.Options.XAxisValuesPerDivision := 4;
- end
- else
- begin
- // A smaller bogus data set for demonstration purposes.
- nValueCount := 24; // 2.5 minute sample period, 24 samples =1 hour.
- foo := 1; // Used in generating our bogus data below, not really important.
- Chart.Options.XAxisValuesPerDivision := 4; // five divisions, 4 values per division
- end;
-
- //Chart.ResetGraphModule; // Clears YMax.
- Fdt := Trunc(now - 1.0); // yesterday, midnight.
- Foo1 := Random(5) + 2; // more randomness
- Foo2 := Random(3) + 5; // more randomness
- FGenerationIndex := 1;
- for I := 0 to nValueCount - 1 do
- begin
- if i > 0 then
- begin // generate random data that appears to show a sawtooth-frequency-pattern plus a lot of random noise:
- _Generate;
- end
- else
- begin
- Fhgt := 7000; // First sample always known value, helps me troubleshoot.
- Fhg0 := 1000;
- end;
-
- _StoreValue(I);
-
- // Override stored value in special cases:
-
- { How to make a gap in the data! }
- if (nValueCount > 100) and ShowgapinLineChart1.Checked then
- begin
- if (I > 100) and (I < 130) then
- begin
- Chart.Data.Value[0, I] := NaN; // Use special Math.NaN const
- Chart.Data.Value[1, I] := NaN; // Use special Math.NaN const
- Chart.Data.Value[2, I] := NaN; // Use special Math.NaN const
- end;
- end;
-
- // Just so that the last two values are visibly different, to make sure
- // the chart handles the final vaulues correctly, we set all the final
- // values to known amounts also:
- if I = nValueCount - 2 then
- begin
- Chart.Data.Value[0, I] := 6.0; // Use special Math.NaN const
- Chart.Data.Value[1, I] := 4.0; // Use special Math.NaN const
- Chart.Data.Value[2, I] := 2.0; // Use special Math.NaN const
- end
- else
- if I = nValueCount - 1 then
- begin
- Chart.Data.Value[0, I] := 3.0; // Use special Math.NaN const
- Chart.Data.Value[1, I] := 2.0; // Use special Math.NaN const
- Chart.Data.Value[2, I] := 1.0; // Use special Math.NaN const
-
- end;
-
- ListBox1.Items.Append(Chart.Data.DebugStr(I));
- end;
-
- with Chart.Options do
- begin
- Title := 'Chart Title';
- XAxisHeader := 'Date/Time';
- YAxisHeader := 'Readings (ng/m3)';
-
- if FNegValueFlag then
- begin
- PrimaryYAxis.YMin := -20;
- PrimaryYAxis.YMax := 20;
- end
- else
- PrimaryYAxis.YMin := 0;
- // Try out the pen styles:
- if ChartKind = ckChartStackedBar then
- PenStyle[0] := psClear // THIS IS HOW YOU TEMPORARILY HIDE ONE PEN!
- else
- PenStyle[0] := psSolid;
- PenStyle[1] := psDash;
- PenStyle[2] := psDot;
-
- if mnuSecondaryAxisMode.Checked then
- begin
- PenCount := 4; // Add a pen for right side demo.
- SecondaryYAxis.YMax := 140; // Example shows Q/A percentage. Experimental results
- // results are compared to expected results, and the
- // response percentage, is plotted from 0% to 140%
- // of expected value.
-
- SecondaryYAxis.YLegendDecimalPlaces := 2;
-
- PenSecondaryAxisFlag[3] := True; // Move pen index 3 (Fourth pen) to secondary axis.
- PenMarkerKind[3] := pmkDiamond;
- PenValueLabels[3] := true; // Label with text.
- PenStyle[3] := psClear; // Markers only, no lines.
- PenColor[3] := clGray;
- MarkerSize := 5; // Make 'em bigger.
- end
- else
- begin
- PenCount := 3;
- MarkerSize := 3; // Make 'em little
- end;
-
- PenLegends.Clear;
- PenLegends.Add('HgT');
- PenLegends.Add('Hg0');
- PenLegends.Add('Hg2+');
- if mnuSecondaryAxisMode.Checked then
- PenLegends.Add('Quality%');
-
- PenUnit.Clear;
- PenUnit.Add('ug/m3');
- PenUnit.Add('ug/m3');
- PenUnit.Add('ug/m3');
- if mnuSecondaryAxisMode.Checked then
- PenUnit.Add('%'); // Optional Pen in percentage scale.
-
- //ShowLegend := TRUE;
-// Legend := clChartLegendBelow;
-
- //ChartKind := ckChartLine;
- end;
-// Chart.AutoFormatGraph;
- Chart.PlotGraph;
-
- //Chart.ResizeChartCanvas;
-end;
-
-procedure TJvChartDemoForm.FormResize(Sender: TObject);
-begin
- if Assigned(Chart) then
- Chart.ResizeChartCanvas;
-end;
-
-procedure TJvChartDemoForm.ButtonBarChartClick(Sender: TObject);
-begin
- Chart.Options.ChartKind := ckChartBar;
- NewValues;
-end;
-
-procedure TJvChartDemoForm.ButtonLineClick(Sender: TObject);
-var
- I: Integer;
-begin
- Chart.Options.ChartKind := ckChartLine;
- for I := 0 to Chart.Options.PenCount - 1 do
- begin
- Chart.Options.PenMarkerKind[I] := pmkNone;
- end;
-
- NewValues;
-end;
-
-procedure TJvChartDemoForm.ButtonLineMarkerClick(Sender: TObject);
-//var
-// I:Integer;
-begin
- Chart.Options.ChartKind := ckChartLine;
- Chart.Options.PenMarkerKind[0] := pmkDiamond; // demonstrate both Diamond and Circle Marks.
- Chart.Options.PenMarkerKind[1] := pmkDiamond;
- Chart.Options.PenMarkerKind[2] := pmkCircle;
-
- NewValues;
-end;
-
-procedure TJvChartDemoForm.ButtonStackedBarAveClick(Sender: TObject);
-begin
- Chart.Options.ChartKind := ckChartStackedBarAverage;
- NewValues;
-end;
-
-procedure TJvChartDemoForm.ButtonStackedBarClick(Sender: TObject);
-begin
- Chart.Options.ChartKind := ckChartStackedBar;
- NewValues;
-end;
-
-procedure TJvChartDemoForm.SpeedButton7Click(Sender: TObject);
-begin
-// Chart.PivotData; // TODO: This causes exceptions. not sure why we want this.
-end;
-
-procedure TJvChartDemoForm.ButtonBarAveClick(Sender: TObject);
-begin
- //Chart.ShowAsBarWithAve;
- Chart.Options.ChartKind := ckChartBarAverage;
-
- NewValues;
-end;
-
-procedure TJvChartDemoForm.ButtonPieClick(Sender: TObject);
-begin
- // Chart.ShowAsPie;
- Chart.Options.ChartKind := ckChartPieChart;
-end;
-
-procedure TJvChartDemoForm.ButtonMarkersClick(Sender: TObject);
-begin
- //Chart.ShowAsMark;
- Chart.Options.ChartKind := ckChartMarkers;
-end;
-
-procedure TJvChartDemoForm.SpinEdit1Change(Sender: TObject);
-begin
-// Chart.Options.PrimaryYAxis.YPixelGap := SpinEdit1.Value;
- Chart.Options.YStartOffset := SpinEdit1.Value;
-// Chart.Options.XStartOffset := SpinEdit1.Value;
-// Chart.Options.ColorScheme := SpinEdit1.Value;
-// Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.Button2Click(Sender: TObject);
-begin
- Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.Button4Click(Sender: TObject);
-begin
-// Chart.AutoFormatGraph; WAP Removed. BAD CODE.
- Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.ButtonDeltaAverageClick(Sender: TObject);
-begin
- Chart.Options.ChartKind := ckChartDeltaAverage;
-end;
-
-procedure TJvChartDemoForm.FormCreate(Sender: TObject);
-begin
- MakePensMenu;
-
- FStatHgt := TStatArray.Create(10); // Initialize for rolling average of last 10 samples.
- FStatHg0 := TStatArray.Create(10);
-
- if Assigned(Chart) then
- // Chart.ShowAsLineWithMark;
- NewValues;
-end;
-
-procedure TJvChartDemoForm.Panel2DblClick(Sender: TObject);
-begin
- OpenURL('http://jvcl.delphi-jedi.org/');
-// ShellExecute(HWND(nil), 'show', 'http://jvcl.delphi-jedi.org/', nil, nil, SW_SHOW);
-end;
-
-procedure TJvChartDemoForm.ShowgapinLineChart1Click(Sender: TObject);
-begin
- ShowgapinLineChart1.Checked := not ShowgapinLineChart1.Checked;
- ButtonLine.Down := true;
- NewValues;
-end;
-
-procedure TJvChartDemoForm.Print1Click(Sender: TObject);
-begin
- if PrintDialog1.Execute then
- Chart.PrintGraph;
-end;
-
-procedure TJvChartDemoForm.Generatenewrandomvalues1Click(Sender: TObject);
-begin
- if SpeedButtonTestMouseOver.Down then exit;
-
- NewValues;
-end;
-
-procedure TJvChartDemoForm.CopyToClipboard1Click(Sender: TObject);
-begin
- Chart.GraphToClipboard;
-end;
-
-procedure TJvChartDemoForm.MakePensMenu;
-var
- i: Integer;
- mnu: TMenuItem;
-begin
- for i := mnuPens.Count-1 downto 0 do begin
- mnu := mnuPens.Items[i];
- if (mnu <> nil) and (mnu.Tag >= TAG_PENCOLORS) and (mnu.tag < TAG_PENCOLORS + MAX_PEN) then
- mnuPens.Delete(i);
- end;
-end;
-
-procedure TJvChartDemoForm.mnuSetAxisFontClick(Sender: TObject);
-begin
- {Get the current font for the axis label texts...}
- FontDialog1.Font.Assign(Chart.Options.AxisFont);
-
- if FontDialog1.Execute then
- {Set the font for the Header text...}
- Chart.Options.AxisFont := FontDialog1.Font;
- Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.mnuSetAxisLineWidthClick(Sender: TObject);
-var
- s: String;
- w: Integer;
-begin
- s := InputBox('Set Axis Linewidth', 'Value:', IntToStr(Chart.Options.AxisLineWidth));
- if TryStrToInt(s, w) and (w >= 0) then
- Chart.Options.AxisLineWidth := w
- else
- MessageDlg('No valid number for axis linewidth', mtError, [mbOk], 0);
-end;
-
-procedure TJvChartDemoForm.mnuSetAxisTitleFontClick(Sender: TObject);
-begin
- {Get the current font for the axis titles...}
- FontDialog1.Font.Assign(Chart.Options.AxisTitleFont);
-
- if FontDialog1.Execute then
- {Set the font for the Header text...}
- Chart.Options.AxisTitleFont := FontDialog1.Font;
- Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.mnuSetCursorColorClick(Sender: TObject);
-begin
- ColorDialog1.Color := Chart.Options.CursorColor;
- if ColorDialog1.Execute then
- Chart.Options.CursorColor := ColorDialog1.Color;
-end;
-
-procedure TJvChartDemoForm.mnuSetDivisionLineColorClick(Sender: TObject);
-begin
- ColorDialog1.Color := Chart.Options.DivisionLineColor;
- if ColorDialog1.Execute then
- Chart.Options.DivisionLineColor := ColorDialog1.Color;
-end;
-
-procedure TJvChartDemoForm.mnuSetHeaderFontClick(Sender: TObject);
-begin
- {Get the current font for the header (title) text...}
- FontDialog1.Font.Assign(Chart.Options.HeaderFont);
-
- if FontDialog1.Execute then
- {Set the font for the Header text...}
- Chart.Options.HeaderFont := FontDialog1.Font;
- Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.mnuSetHintColorClick(Sender: TObject);
-begin
- ColorDialog1.Color := Chart.Options.HintColor;
- if ColorDialog1.Execute then
- Chart.Options.HintColor := ColorDialog1.Color;
-end;
-
-procedure TJvChartDemoForm.mnuSetLegendFontClick(Sender: TObject);
-begin
- {Get the current font for the header (title) text...}
- FontDialog1.Font.Assign(Chart.Options.LegendFont);
-
- if FontDialog1.Execute then
- {Set the font for the Header text...}
- Chart.Options.LegendFont := FontDialog1.Font;
- Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.mnuSetMarkerSizeClick(Sender: TObject);
-var
- s: String;
-begin
- s := InputBox('Set Marker Size', 'Value:', IntToStr(Chart.Options.MarkerSize));
- Chart.Options.MarkerSize := StrToInt(s);
-end;
-
-procedure TJvChartDemoForm.mnuSetPaperColorClick(Sender: TObject);
-begin
- ColorDialog1.Color := Chart.Options.PaperColor;
- if ColorDialog1.Execute then
- Chart.Options.PaperColor := ColorDialog1.Color;
-end;
-
-
-procedure TJvChartDemoForm.mnuSetPenCountClick(Sender: TObject);
-var
- s: String;
- n: Integer;
-begin
- s := InputBox('Set pen count', 'Value:', IntToStr(Chart.Options.PenCount));
- if TryStrToInt(s, n) then
- begin
- Chart.Options.PenCount := n;
- //MakePenColorMenu;
- end else
- MessageDlg('No valid number of pens.', mtError, [mbOK], 0);
-
-end;
-
-procedure TJvChartDemoForm.mnuSetPenLineWidthClick(Sender: TObject);
-var
- s: String;
- w: Integer;
-begin
- s := InputBox('Set Pen Linewidth', 'Value:', IntToStr(Chart.Options.PenLineWidth));
- if TryStrToInt(s, w) and (w > 0) then
- Chart.Options.PenLineWidth := w
- else
- MessageDlg('No valid number for pen linewidth', mtError, [mbOk], 0);
-end;
-
-procedure TJvChartDemoForm.mnuSetShadowColorClick(Sender: TObject);
-begin
- ColorDialog1.Color := Chart.Options.ShadowColor;
- if ColorDialog1.Execute then
- Chart.Options.ShadowColor := ColorDialog1.Color;
-end;
-
-procedure TJvChartDemoForm.mnuSetTitleClick(Sender: TObject);
-var
- s: String;
-begin
- s := InputBox('Set Chart Title', 'Text:', Chart.Options.Title);
- Chart.Options.Title := s;
-end;
-
-procedure TJvChartDemoForm.mnuSetXAxisHeaderClick(Sender: TObject);
-var
- s: String;
-begin
- s := InputBox('Set X Axis Title', 'Text:', Chart.Options.XAxisHeader);
- Chart.Options.XAxisHeader := s;
-end;
-
-procedure TJvChartDemoForm.mnuSetXStartOffsetClick(Sender: TObject);
-var
- s: String;
- x: Integer;
-begin
- s := InputBox('Set X Axis Start Offset', 'Value:', IntToStr(Chart.Options.XStartOffset));
- if TryStrToInt(s, x) and (x >= 0) then
- Chart.Options.XStartOffset := x
- else
- MessageDlg('No valid number for X Start Offset.', mtError, [mbOK], 0);
-end;
-
-procedure TJvChartDemoForm.mnuSetYAxisHeaderClick(Sender: TObject);
-var
- s: String;
-begin
- s := InputBox('Set Y Axis Title', 'Text:', Chart.Options.YAxisHeader);
- Chart.Options.YAxisHeader := s;
-end;
-
-procedure TJvChartDemoForm.About1Click(Sender: TObject);
-begin
- Application.MessageBox(PChar(
- 'JvChart comes from AABSoft Graph written by MÃ¥rten Henrichson, JVCL 3.0 ' +
- 'version by Warren Postma. '), 'About JvChart', MB_OK);
-end;
-
-procedure TJvChartDemoForm.mnuScrollingClick(Sender: TObject);
-begin
- if SpeedButtonTestMouseOver.Down then exit;
-
- mnuScrolling.Checked := not mnuScrolling.Checked;
- Timer1.Enabled := mnuScrolling.Checked;
-end;
-
-procedure TJvChartDemoForm.Timer1Timer(Sender: TObject);
-begin
- if SpeedButtonTestMouseOver.Down then exit;
-
- Chart.Data.Scroll;
- _Generate;
- _StoreValue(Chart.Data.ValueCount - 1);
- Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.ShowDataInListbox1Click(Sender: TObject);
-begin
- ShowDataInListbox1.Checked := not ShowDataInListbox1.Checked;
- ListBox1.Visible := ShowDataInListbox1.Checked;
-
- if not ShowDataInListbox1.Checked then
- begin
- Chart.CursorPosition := -1; // Invisible.
- end;
-end;
-
-procedure TJvChartDemoForm.LargeDataset576samples1Click(Sender: TObject);
-begin
- if SpeedButtonTestMouseOver.Down then exit;
-
- LargeDataset576samples1.Checked := not LargeDataset576samples1.Checked;
- NewValues;
-end;
-
-procedure TJvChartDemoForm.mnuDateTimeAxisModeClick(Sender: TObject);
-begin
- mnuDateTimeAxisMode.Checked := not mnuDateTimeAxisMode.Checked;
- if SpeedButtonTestMouseOver.Down then begin
- Chart.Options.XLegends.Clear;
- end else
- NewValues;
-end;
-
-procedure TJvChartDemoForm.FormDestroy(Sender: TObject);
-begin
- FreeAndNil(FStatHgt);
- FreeAndNil(FStatHg0);
-end;
-
-procedure TJvChartDemoForm.PrintOptions1Click(Sender: TObject);
-begin
- PrinterSetupDialog1.Execute;
-end;
-
-procedure TJvChartDemoForm.mnuSecondaryAxisModeClick(Sender: TObject);
-begin
- mnuSecondaryAxisMode.Checked := not mnuSecondaryAxisMode.Checked;
-
- if mnuSecondaryAxisMode.Checked then
- begin
- ButtonLine.Down := true;
- ButtonLineClick(Sender);
- end
- else
- NewValues;
-end;
-
-procedure TJvChartDemoForm.mnuFillUnderLineClick(Sender: TObject);
-begin
- mnuFillUnderLine.Checked := not mnuFillUnderLine.Checked;
- Chart.Options.FillUnderLine := mnuFillUnderLine.Checked;
-end;
-
-procedure TJvChartDemoForm.mnuLegenClick(Sender: TObject);
-begin
- mnuLegendNone.Checked := (Sender = mnuLegendNone);
- mnuLegendBelow.Checked := (Sender = mnuLegendBelow);
- mnuLegendRight.Checked := (Sender = mnuLegendRight);
- if mnuLegendNone.Checked then
- Chart.Options.Legend := clChartLegendNone
- else if mnuLegendRight.Checked then
- Chart.Options.Legend := clChartLegendRight
- else if mnuLegendBelow.Checked then
- Chart.Options.Legend := clChartLegendBelow;
-end;
-
-procedure TJvChartDemoForm.mnuPensClick(Sender: TObject);
-var
- F: TPenEditorForm;
-begin
- F := TPenEditorForm.Create(nil);
- try
- F.UseChart(Chart);
- if F.ShowModal = mrOK then
- F.ApplyToChart(Chart);
- finally
- F.Free;
- end;
-end;
-
-procedure TJvChartDemoForm.ListBox1DblClick(Sender: TObject);
-begin
- Chart.CursorPosition := ListBox1.ItemIndex; // Highlight one sample.
-end;
-
-procedure TJvChartDemoForm.ListBox1Click(Sender: TObject);
-begin
- Chart.CursorPosition := ListBox1.ItemIndex; // Highlight one sample.
-end;
-
-procedure TJvChartDemoForm.MenuNegValueTestClick(Sender: TObject);
-begin
- FNegValueFlag := MenuNegValueTest.Checked;
- NewValues;
-end;
-
-{ Simple Chart Tests for finding bug }
-procedure TJvChartDemoForm.SpeedButtonTestMouseOverClick(Sender: TObject);
-var
- i:Integer;
- n:Double;
- marker1,marker2,draggableCursor:TJvChartFloatingMarker;
-begin
- ListBox1.Clear;
- mnuScrolling.Checked := false;
-
- Chart.Options.Title := 'Click on the Red Diamonds or the vertical gray line and Drag them!';
- Chart.Options.ChartKind := ckChartLine;
- Chart.Options.XLegends.Clear;
- Chart.Options.XAxisHeader := '';
-
- Chart.Options.MouseDragObjects := true; // NEW: MOUSE DRAG FLOATING OBJECTS!
-
- for i := 0 to Chart.Options.PenCount - 1 do
- begin
- Chart.Options.PenMarkerKind[I] := pmkNone;
- end;
- Chart.Data.Clear;
- Chart.Options.XValueCount := 80;
- Chart.Data.ValueCount := 6;
- Chart.Options.PenCount := 1;
- for i := 0 to Chart.Options.XValueCount-1 do begin
- n := 30-(25*((1-((i-25)/15))*(1-((i-25)/15))));
- if n<5 then
- n := 5 -(Sqrt((Abs(n))/15));
- ListBox1.Items.Add( FloatToStrF(n,ffFixed,6,4));
- Chart.Data.Value[0,i] := n;
- end;
- Chart.Options.PrimaryYAxis.YMax := 50;
-
- Chart.Options.PenStyle[0] := psSolid;
-
- // NEW: Add a floating marker:
- marker1 := Chart.AddFloatingMarker;
- marker1.XPosition := 13;
- marker1.YPosition := Chart.Data.Value[0,marker1.XPosition]; // Snap to Pen 1
- marker1.XDraggable := true; // make it mouse-moveable.
- marker1.YDraggable := true;
- marker1.Caption :='Start';
- marker1.Visible := true;
-
- marker2 := Chart.AddFloatingMarker;
- marker2.XPosition := 66;
- marker2.YPosition := Chart.Data.Value[0,marker2.XPosition]; // Snap to Pen 1
- marker2.LineToMarker := marker1.index; // Connect with a line to marker1
- marker2.XDraggable := true; // make it mouse-moveable.
- marker2.YDraggable := true;
- marker2.Caption := 'End';
- marker2.Visible := true;
-
- // NOTE: Do not Free marker1 or marker2.
- // Marker objects are freed automatically
- // by the Chart.
-
- // a draggable cursor object:
- draggableCursor := Chart.AddFloatingMarker;
- draggableCursor.LineVertical := true; // Make a vertical Line
- draggableCursor.Marker := pmkNone; // No marker. So it is a line only.
- draggableCursor.XDraggable := true; // make it draggable.
- draggableCursor.XPosition := 40;
- draggableCursor.LineColor := clDkGray;
- draggableCursor.LineStyle := psSolid;
- draggableCursor.LineWidth := 2;
- draggableCursor.Caption := FloatToStrF( Chart.Data.Value[0,draggableCursor.XPosition], ffFixed, 6,4 );
- draggableCursor.Visible := true;
-
- Chart.PlotGraph;
-end;
-
-procedure TJvChartDemoForm.ChartEndFloatingMarkerDrag(Sender: TJvChart;
- FloatingMarker: TJvChartFloatingMarker);
-begin
- // Snap to line:
- if (FloatingMarker.Index<2) then // One of the first two markers?
- FloatingMarker.YPosition := Chart.Data.Value[0, FloatingMarker.XPosition]
- else // update caption
- FloatingMarker.Caption := FloatToStrF( Chart.Data.Value[0,FloatingMarker.XPosition],ffFixed,6,4 );
-end;
-
-procedure TJvChartDemoForm.ChartBeginFloatingMarkerDrag(Sender: TJvChart;
- FloatingMarker: TJvChartFloatingMarker);
-begin
- if FloatingMarker.Index = 2 then
- FloatingMarker.Caption := '?';
-end;
-
-end.
diff --git a/components/jvcllaz/examples/JvChartDemo/jvpeneditor.lfm b/components/jvcllaz/examples/JvChartDemo/jvpeneditor.lfm
deleted file mode 100644
index 8e882e78d..000000000
--- a/components/jvcllaz/examples/JvChartDemo/jvpeneditor.lfm
+++ /dev/null
@@ -1,206 +0,0 @@
-object PenEditorForm: TPenEditorForm
- Left = 347
- Height = 302
- Top = 128
- Width = 505
- BorderStyle = bsDialog
- Caption = 'PenEditorForm'
- ClientHeight = 302
- ClientWidth = 505
- OnCreate = FormCreate
- OnDestroy = FormDestroy
- Position = poScreenCenter
- LCLVersion = '2.1.0.0'
- object btnPenColor: TButton
- Left = 232
- Height = 25
- Top = 232
- Width = 64
- AutoSize = True
- Caption = 'Color...'
- OnClick = btnPenColorClick
- TabOrder = 0
- end
- object rgPenStyle: TRadioGroup
- Left = 224
- Height = 168
- Top = 40
- Width = 121
- AutoFill = True
- Caption = 'Style'
- ChildSizing.LeftRightSpacing = 6
- ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
- ChildSizing.EnlargeVertical = crsHomogenousChildResize
- ChildSizing.ShrinkHorizontal = crsScaleChilds
- ChildSizing.ShrinkVertical = crsScaleChilds
- ChildSizing.Layout = cclLeftToRightThenTopToBottom
- ChildSizing.ControlsPerLine = 1
- ClientHeight = 148
- ClientWidth = 117
- Items.Strings = (
- 'Solid'
- 'Dash'
- 'Dot'
- 'Dash-dot'
- 'Dash-dot-dot'
- 'Clear'
- )
- OnClick = rgPenStyleClick
- TabOrder = 1
- end
- object ButtonPanel1: TButtonPanel
- Left = 6
- Height = 34
- Top = 262
- Width = 493
- OKButton.Name = 'OKButton'
- OKButton.DefaultCaption = True
- HelpButton.Name = 'HelpButton'
- HelpButton.DefaultCaption = True
- CloseButton.Name = 'CloseButton'
- CloseButton.DefaultCaption = True
- CancelButton.Name = 'CancelButton'
- CancelButton.DefaultCaption = True
- TabOrder = 2
- ShowButtons = [pbOK, pbCancel]
- end
- object lbPens: TListBox
- Left = 8
- Height = 216
- Top = 8
- Width = 200
- ItemHeight = 0
- OnDrawItem = lbPensDrawItem
- OnSelectionChange = lbPensSelectionChange
- Style = lbOwnerDrawFixed
- TabOrder = 3
- end
- object btnAdd: TButton
- Left = 11
- Height = 25
- Top = 232
- Width = 48
- AutoSize = True
- Caption = 'Add'
- OnClick = btnAddClick
- TabOrder = 4
- end
- object btnDelete: TButton
- Left = 64
- Height = 25
- Top = 232
- Width = 59
- AutoSize = True
- Caption = 'Delete'
- OnClick = btnDeleteClick
- TabOrder = 5
- end
- object edPenLegend: TEdit
- Left = 304
- Height = 23
- Top = 8
- Width = 185
- OnEditingDone = edPenLegendEditingDone
- TabOrder = 6
- end
- object btnClear: TButton
- Left = 128
- Height = 25
- Top = 232
- Width = 53
- AutoSize = True
- Caption = 'Clear'
- OnClick = btnClearClick
- TabOrder = 7
- end
- object lblLegend: TLabel
- Left = 224
- Height = 15
- Top = 8
- Width = 39
- Caption = 'Legend'
- ParentColor = False
- end
- object ColorSample: TShape
- Left = 304
- Height = 25
- Top = 232
- Width = 25
- end
- object rgMarker: TRadioGroup
- Left = 376
- Height = 136
- Top = 40
- Width = 112
- AutoFill = True
- Caption = 'Marker'
- ChildSizing.LeftRightSpacing = 6
- ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
- ChildSizing.EnlargeVertical = crsHomogenousChildResize
- ChildSizing.ShrinkHorizontal = crsScaleChilds
- ChildSizing.ShrinkVertical = crsScaleChilds
- ChildSizing.Layout = cclLeftToRightThenTopToBottom
- ChildSizing.ControlsPerLine = 1
- ClientHeight = 116
- ClientWidth = 108
- Items.Strings = (
- 'None'
- 'Diamond'
- 'Circle'
- 'Square'
- 'Cross'
- )
- OnClick = rgMarkerClick
- TabOrder = 8
- end
- object rgAxis: TRadioGroup
- Left = 376
- Height = 64
- Top = 192
- Width = 113
- AutoFill = True
- Caption = 'y Axis'
- ChildSizing.LeftRightSpacing = 6
- ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
- ChildSizing.EnlargeVertical = crsHomogenousChildResize
- ChildSizing.ShrinkHorizontal = crsScaleChilds
- ChildSizing.ShrinkVertical = crsScaleChilds
- ChildSizing.Layout = cclLeftToRightThenTopToBottom
- ChildSizing.ControlsPerLine = 1
- ClientHeight = 44
- ClientWidth = 109
- Items.Strings = (
- 'Primary'
- 'Secondary'
- )
- OnClick = rgAxisClick
- TabOrder = 9
- end
- object ColorDialog: TColorDialog
- Color = clBlack
- CustomColors.Strings = (
- 'ColorA=000000'
- 'ColorB=000080'
- 'ColorC=008000'
- 'ColorD=008080'
- 'ColorE=800000'
- 'ColorF=800080'
- 'ColorG=808000'
- 'ColorH=808080'
- 'ColorI=C0C0C0'
- 'ColorJ=0000FF'
- 'ColorK=00FF00'
- 'ColorL=00FFFF'
- 'ColorM=FF0000'
- 'ColorN=FF00FF'
- 'ColorO=FFFF00'
- 'ColorP=FFFFFF'
- 'ColorQ=C0DCC0'
- 'ColorR=F0CAA6'
- 'ColorS=F0FBFF'
- 'ColorT=A4A0A0'
- )
- left = 144
- top = 88
- end
-end
diff --git a/components/jvcllaz/examples/JvChartDemo/jvpeneditor.pas b/components/jvcllaz/examples/JvChartDemo/jvpeneditor.pas
deleted file mode 100644
index cbb6823bc..000000000
--- a/components/jvcllaz/examples/JvChartDemo/jvpeneditor.pas
+++ /dev/null
@@ -1,349 +0,0 @@
-unit jvPenEditor;
-
-{$mode objfpc}{$H+}
-
-interface
-
-uses
- Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
- ButtonPanel, Contnrs, Types,
- JvChart;
-
-type
- TPenObj = class
- Legend: String;
- Color: TColor;
- Style: TPenStyle;
- Marker: TJvChartPenMarkerKind;
- SecondaryAxis: Boolean;
- end;
-
- { TPenEditorForm }
-
- TPenEditorForm = class(TForm)
- btnPenColor: TButton;
- btnAdd: TButton;
- btnDelete: TButton;
- btnClear: TButton;
- ButtonPanel1: TButtonPanel;
- ColorDialog: TColorDialog;
- edPenLegend: TEdit;
- lblLegend: TLabel;
- lbPens: TListBox;
- rgAxis: TRadioGroup;
- rgMarker: TRadioGroup;
- rgPenStyle: TRadioGroup;
- ColorSample: TShape;
- procedure btnAddClick(Sender: TObject);
- procedure btnClearClick(Sender: TObject);
- procedure btnDeleteClick(Sender: TObject);
- procedure btnPenColorClick(Sender: TObject);
- procedure edPenLegendEditingDone(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure lbPensDrawItem(Control: TWinControl; Index: Integer;
- ARect: TRect; State: TOwnerDrawState);
- procedure lbPensSelectionChange(Sender: TObject; User: boolean);
- procedure rgAxisClick(Sender: TObject);
- procedure rgMarkerClick(Sender: TObject);
- procedure rgPenStyleClick(Sender: TObject);
- private
- FPens: TObjectList;
- procedure ControlsToPen(AIndex: Integer);
- procedure PenToControls(AIndex: Integer);
- function GetCurrentPen: TPenObj;
-
- public
- procedure ApplyToChart(AChart: TJvChart);
- procedure UseChart(AChart: TJvChart);
-
- end;
-
-
-implementation
-
-{$R *.lfm}
-
-uses
- Math, LCLType;
-
-
-{ TPenEditorForm }
-
-procedure TPenEditorForm.ApplyToChart(AChart: TJvChart);
-var
- i: Integer;
- pen: TPenObj;
-begin
- Assert(AChart <> nil);
- AChart.Options.PenCount := FPens.Count;
- AChart.Options.PenLegends.Clear;
- for i := 0 to FPens.Count - 1 do
- begin
- pen := TPenObj(FPens[i]);
- AChart.Options.PenLegends.Add(pen.Legend);
- AChart.Options.PenColor[i] := pen.Color;
- AChart.Options.PenStyle[i] := pen.Style;
- AChart.Options.PenMarkerKind[i] := pen.Marker;
- end;
-end;
-
-procedure TPenEditorForm.btnAddClick(Sender: TObject);
-var
- pen: TPenObj;
-begin
- pen := TPenObj.Create;
- pen.Legend := '';
- pen.Style := psSolid;
- pen.Color := clBlack;
- pen.Marker := pmkNone;
- pen.SecondaryAxis := false;
- FPens.Add(pen);
- lbPens.Items.Add('');
-end;
-
-procedure TPenEditorForm.btnClearClick(Sender: TObject);
-begin
- FPens.Clear;
- lbPens.Items.Clear;
-end;
-
-procedure TPenEditorForm.btnDeleteClick(Sender: TObject);
-begin
- if lbPens.ItemIndex = -1 then
- exit;
- FPens.Delete(lbPens.ItemIndex);
- lbPens.Items.Delete(lbPens.ItemIndex);
-end;
-
-procedure TPenEditorForm.btnPenColorClick(Sender: TObject);
-var
- pen: TPenObj;
-begin
- pen := GetCurrentPen;
- if pen = nil then
- exit;
-
- ColorDialog.Color := pen.Color;
- if ColorDialog.Execute then begin
- pen.Color := ColorDialog.Color;
- lbPens.Invalidate;
- end;
-end;
-
-procedure TPenEditorForm.ControlsToPen(AIndex: Integer);
-var
- pen: TPenObj;
-begin
- if AIndex = -1 then
- exit;
- pen := TPenObj(FPens[AIndex]);
- pen.Legend := edPenLegend.Text;
- if rgPenStyle.ItemIndex = rgPenStyle.Items.Count-1 then
- pen.Style := psClear
- else
- pen.Style := TPenStyle(rgPenStyle.ItemIndex);
- pen.Marker := TJvChartPenMarkerKind(rgMarker.ItemIndex);
- pen.Color := ColorSample.Brush.Color;
- pen.SecondaryAxis := rgAxis.ItemIndex = 1;
-end;
-
-procedure TPenEditorForm.edPenLegendEditingDone(Sender: TObject);
-var
- pen: TPenObj;
-begin
- pen := GetCurrentPen;
- if pen = nil then
- exit;
- pen.Legend := edPenLegend.Text;
- lbPens.Invalidate;
-end;
-
-procedure TPenEditorForm.FormCreate(Sender: TObject);
-begin
- FPens := TObjectList.Create;
-end;
-
-procedure TPenEditorForm.FormDestroy(Sender: TObject);
-begin
- FPens.Free;
-end;
-
-function TPenEditorForm.GetCurrentPen: TPenObj;
-begin
- if lbPens.ItemIndex = -1 then
- Result := nil
- else
- Result := TPenObj(FPens[lbPens.ItemIndex]);
-end;
-
-procedure TPenEditorForm.lbPensDrawItem(Control: TWinControl; Index: Integer;
- ARect: TRect; State: TOwnerDrawState);
-var
- R: TRect;
- pen: TPenObj;
- x, y, dx, dy: Integer;
-begin
- pen := TPenObj(FPens[Index]);
- lbPens.Canvas.Font.Assign(lbPens.Font);
-
- // Background
- if [odSelected, odFocused] * State <> [] then
- begin
- lbPens.Canvas.Brush.Color := clHighlight;
- lbPens.Canvas.Font.Color := clHighlightText;
- end else
- begin
- lbPens.Canvas.Brush.Color := lbPens.Color;
- lbPens.Canvas.Font.Color := lbPens.Font.Color;
- end;
- lbPens.Canvas.FillRect(ARect);
-
- // Line
- R := ARect;
- R.Right := R.Left + 50;
- InflateRect(R, -2, -2);
- lbPens.Canvas.Pen.Style := pen.Style;
- lbPens.Canvas.Pen.Color := pen.Color;
- lbPens.Canvas.Line(R.Left, (R.Top + R.Bottom) div 2, R.Right, (R.Top + R.Bottom) div 2);
-
- // Marker
- x := (R.Left + R.Right) div 2;
- y := (R.Top + R.Bottom) div 2;
- dx := (R.Bottom - R.Top) div 2;
- dy := dx;
- lbPens.Canvas.Pen.Style := psSolid;
- case pen.Marker of
- pmkNone: ;
- pmkDiamond:
- begin
- lbPens.Canvas.Brush.Color := pen.Color;
- lbPens.Canvas.Brush.Style := bsSolid;
- lbPens.Canvas.Polygon([Point(x, y-dy), Point(x-dx, y), Point(x, y+dy), Point(x+dx, y)]);
- end;
- pmkCircle:
- begin
- lbPens.Canvas.Brush.Style := bsClear;
- lbPens.Canvas.Ellipse(x-dx, y-dy, x+dx, y+dy);
- end;
- pmkSquare:
- begin
- lbPens.Canvas.Brush.Style := bsClear;
- lbPens.Canvas.Rectangle(x-dx, y-dy, x+dx, y+dy);
- end;
- pmkCross:
- begin
- lbPens.Canvas.Line(x-dx, y, x+dx, y);
- lbPens.Canvas.Line(x, y-dy, x, y+dy);
- end;
- else
- raise Exception.Create('Marker style not supported.');
- end;
-
- // Text
- lbPens.Canvas.Brush.Style := bsClear;
- lbPens.Canvas.TextOut(R.Right + 2, (R.Top + R.Bottom - lbPens.Canvas.TextHeight('Rg')) div 2, pen.Legend);
-
- // Focus rect
- if odFocused in State then
- lbPens.Canvas.DrawFocusRect(ARect);
-end;
-
-procedure TPenEditorForm.lbPensSelectionChange(Sender: TObject; User: boolean);
-begin
- PenToControls(lbPens.ItemIndex);
-end;
-
-procedure TPenEditorForm.PenToControls(AIndex: Integer);
-var
- pen: TPenObj;
-begin
- if AIndex = -1 then
- exit;
-
- pen := TPenObj(FPens[AIndex]);
-
- edPenLegend.Text := pen.Legend;
- if pen.Style = psClear then
- rgPenStyle.ItemIndex := rgPenStyle.Items.Count-1
- else
- rgPenStyle.ItemIndex := ord(pen.Style);
- rgMarker.ItemIndex := ord(pen.Marker);
- rgAxis.ItemIndex := IfThen(pen.SecondaryAxis, 1, 0);
- ColorSample.Brush.Color := pen.Color;
-
- edPenLegend.Enabled := true;
- rgPenStyle.Enabled := true;
- rgMarker.Enabled := true;
- rgAxis.Enabled := true;
- btnPenColor.Enabled := true;
- ColorSample.Visible := true;
-end;
-
-procedure TPenEditorForm.rgAxisClick(Sender: TObject);
-var
- pen: TPenObj;
-begin
- pen := GetCurrentPen;
- if pen = nil then
- exit;
- pen.SecondaryAxis := rgAxis.ItemIndex = 1;
-end;
-
-procedure TPenEditorForm.rgMarkerClick(Sender: TObject);
-var
- pen: TPenObj;
-begin
- pen := GetCurrentPen;
- if pen = nil then
- exit;
- pen.Marker := TJvChartPenMarkerKind(rgMarker.ItemIndex);
- lbPens.Invalidate;
-end;
-
-procedure TPenEditorForm.rgPenStyleClick(Sender: TObject);
-var
- pen: TPenObj;
-begin
- pen := GetCurrentPen;
- if pen = nil then
- exit;
-
- if rgPenStyle.itemIndex = rgPenStyle.Items.Count -1 then
- pen.Style := psClear
- else
- pen.Style := TPenStyle(rgPenStyle.ItemIndex);
- lbPens.Invalidate;
-end;
-
-procedure TPenEditorForm.UseChart(AChart: TJvChart);
-var
- i: Integer;
- pen: TPenObj;
-begin
- Assert(AChart <> nil);
-
- FPens.Clear;
- lbPens.Items.Clear;
- for i := 0 to AChart.Options.PenLegends.Count - 1 do
- begin
- pen := TPenObj.Create;
- pen.Legend := AChart.Options.PenLegends[i];
- pen.Color := AChart.Options.PenColor[i];
- pen.Style := AChart.Options.PenStyle[i];
- pen.Marker := AChart.Options.PenMarkerKind[i];
- pen.SecondaryAxis := AChart.Options.PenSecondaryAxisFlag[i];;
- FPens.Add(pen);
- lbPens.Items.Add('');
- end;
-
- edPenLegend.Enabled := false;
- rgPenStyle.Enabled := false;
- rgMarker.Enabled := false;
- rgAxis.Enabled := false;
- btnPenColor.Enabled := false;
- ColorSample.Visible := false;
-end;
-
-end.
-
diff --git a/components/jvcllaz/examples/JvChartDemo/statsclasses.pas b/components/jvcllaz/examples/JvChartDemo/statsclasses.pas
deleted file mode 100644
index 82e832f79..000000000
--- a/components/jvcllaz/examples/JvChartDemo/statsclasses.pas
+++ /dev/null
@@ -1,258 +0,0 @@
-{-----------------------------------------------------------------------------
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/MPL-1.1.html
-
-Software distributed under the License is distributed on an "AS IS" basis,
-WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
-the specific language governing rights and limitations under the License.
-
-The Original Code is: JvChartDemoFm.Pas, released on 2002-10-04.
-
-The Initial Developer of the Original Code is AABsoft and MÃ¥rten Henrichson.
-(C) 1996 AABsoft and MÃ¥rten Henrichson.
-All Rights Reserved.
-
-Contributor(s): -
-
-Last Modified: 2004-01-07
- Modified 2003 Warren Postma
-
-You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
-located at http://jvcl.delphi-jedi.org
-
-Description:
- TStatArray - Statistics, Rolling average helper class.
-
-Known Issues:
- This version is part of JvChartDemo.
------------------------------------------------------------------------------}
-
-{$MODE OBJFPC}{$H+}
-
-unit StatsClasses;
-
-interface
-
-type
-
- TStatArray = class
- protected
- //FFirst:Boolean;
- FGrows: Boolean; // false=rolling average (circular buffer mode), true=average or sd of any number of samples (array grows without limit)
- FValues: Array of Double;
- FLength: Integer; // Array absolute size (may still be no data even if this is >0)
- FIndex: Integer; // Where will the next sample be stored into the array?
- FCount: Integer; // How many valid samples are in the array right now?
- procedure SetLen(aLength:Integer);
- public
- constructor Create; overload;
- constructor Create(initialLength:Integer); overload;
- destructor Destroy; override;
-
- procedure AddValue(aValue:Double);
- function Average:Double;
- function StandardDeviation:Double;
-
- property Grows:Boolean read FGrows write FGrows; // false=rolling average, true=average ALL samples (grows to fit)
- property Length:Integer read FLength write SetLen;
- property Count:Integer read FCount;
- //property First:Boolean read FFirst;
- procedure Reset; // Clear everything!
-end;
-
-
-implementation
-
-uses
- SysUtils, // FloatToStr
- Math; // VCL's statistics routines. StdDev, etc.
-
-// Begin Rolling Average
-
-constructor TStatArray.Create; // overload;
-begin
- //FFirst := true;
- FLength := 0;
- FIndex := 0;
- FCount:= 0;
- FGrows := true;
- SetLength(FValues,0);
-end;
-
-procedure TStatArray.Reset;
-var
- i:Integer;
-begin
- FIndex := 0;
- FCount := 0;
- for i := 0 to FLength-1 do begin
- FValues[i] := -999.0; // debug helper.
- end;
- //FFirst := true;
-end;
-
-constructor TStatArray.Create(initialLength:Integer); // overload;
-begin
-// FFirst := true;
- SetLength(FValues,initialLength);
- if (initialLength>0) then
- FGrows := false
- else
- FGrows := true;
- FLength := initialLength;
- FIndex := 0;
- FCount:= 0;
-end;
-
-
-destructor TStatArray.Destroy;
-begin
- SetLength(FValues,0);
-end;
-
-
-function TStatArray.Average:Double;
-var
- last,i:Integer;
- sum:Double;
-begin
- if FCount <= 0 then begin
- result := 0;
- end else begin
- sum := 0;
- if (FCount>FLength) then
- last :=FLength-1
- else
- last :=FCount-1;
- for i := 0 to last do begin
- sum := sum + FValues[i];
- end;
- result := sum / (last+1);
- end;
-end;
-
-function TStatArray.StandardDeviation:Double;
-var
- i:Integer;
-// sum:Double;
- TempArray:Array of Double;
-begin
- if (FCount <= 0) then
- result := 0
- else if (FCount >= FLength) then begin
- result := Math.StdDev( FValues )
- end else begin
- SetLength(TempArray,FCount);
- for i := 0 to FCount-1 do begin
- TempArray[i] := FValues[i];
- end;
- result := Math.StdDev( TempArray );
- SetLength(TempArray,0);
- end;
-end;
-
-procedure TStatArray.AddValue(aValue:Double);
-//var
-// i:Integer;
-begin
- (*if FFirst then begin
- FFirst := false;
- FIndex := 0;
- FValues[0] := aValue;
- FCount := 1;
- end else begin*)
-
- // First time in we might need to create an array:
- if FIndex>=Length then begin
- Assert(FGrows); // Illegal condition.
- FLength := FIndex+1;
- SetLength( FValues,FLength); // uninitialized, as of yet.
- end;
-
- FValues[FIndex] := aValue;
- Inc(FIndex);
- Inc(FCount);
- if (not FGrows) then begin // circular?
- if (FIndex>=FLength) then begin
- FIndex := 0;
- //FCount := FLength;//FCount does not exceed FLength in wraparounds.
- end;
- end else begin // grow after, in doublings of size, scales better!
- if (FIndex>=FLength) then begin
- FLength := FLength * 2;
- SetLength( FValues,FLength); // uninitialized, as of yet.
-{$ifdef DEBUG_ASSERTIONS}
- Assert(FLength<20000); // Debug limit
-{$endif}
- end;
- end;
-
-end;
-
-procedure TStatArray.SetLen(aLength:Integer);
-begin
- if(aLength<1) then
- aLength := 1;
- FLength := aLength;
- SetLength(FValues, FLength);
-
-end;
-
-
-// End Stats
-
-
-{$ifdef UNIT_TESTS}
-procedure StatsUnitTests;
-var
- diff:Double;
- a1:TStatArray;
- procedure _outs(s:String);
- begin
- OutputDebugString(PChar(s));
- end;
- procedure _outd(d:Double);
- begin
- OutputDebugString(PChar(FloatToStr(d)));
- end;
-
-begin
- _outs('StatsUnitTests begins');
-
- a1 := TStatArray.Create(0); // Growing array.
- a1.AddValue( 3.5 );
- a1.AddValue( 1.5 );
- a1.AddValue( 25.5 );
- a1.AddValue( 100.5 );
- _outd( a1.Average );
-
- diff := Abs(((3.5+1.5+25.5+100.5)/4.0)-a1.Average);
- Assert(diff<0.001);
-
- a1.Reset;
- Assert(Abs(a1.Average)<0.0001);
-
- a1.AddValue( 3.5 );
- a1.AddValue( 1.5 );
- a1.AddValue( 25.5 );
- a1.AddValue( 100.5 );
- _outd( a1.Average );
-
- diff := Abs(((3.5+1.5+25.5+100.5)/4.0)-a1.Average);
- Assert(diff<0.001);
-
- _outd( a1.StandardDeviation );
- Assert(trunc(a1.StandardDeviation)=46);
-
- _outs('StatsUnitTests ends');
-end;
-
-initialization
- StatsUnitTests;
-
-{$endif}
-
-
-end.
diff --git a/components/jvcllaz/packages/jvcustomlazr.lpk b/components/jvcllaz/packages/jvcustomlazr.lpk
index dee0e68ad..0d0ca45e9 100644
--- a/components/jvcllaz/packages/jvcustomlazr.lpk
+++ b/components/jvcllaz/packages/jvcustomlazr.lpk
@@ -16,7 +16,7 @@
TimeLine, OutlookBar, Thumbnail viewer, ImageViewer, ImageListViewer, OwnerDrawViewer"/>
-
+
@@ -69,10 +69,6 @@ TimeLine, OutlookBar, Thumbnail viewer, ImageViewer, ImageListViewer, OwnerDrawV
-
-
-
-
diff --git a/components/jvcllaz/resource/jvcustomreg.res b/components/jvcllaz/resource/jvcustomreg.res
index b04dbee13..18f1a287c 100644
Binary files a/components/jvcllaz/resource/jvcustomreg.res and b/components/jvcllaz/resource/jvcustomreg.res differ
diff --git a/components/jvcllaz/run/JvCustomControls/jvchart.pas b/components/jvcllaz/run/JvCustomControls/jvchart.pas
deleted file mode 100644
index 962d0d981..000000000
--- a/components/jvcllaz/run/JvCustomControls/jvchart.pas
+++ /dev/null
@@ -1,6247 +0,0 @@
-{-----------------------------------------------------------------------------
-JvChart - TJvChart Component - 2009 Public
-
-The contents of this file are subject to the Mozilla Public License
-Version 1.1 (the "License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/MPL-1.1.html
-
-Software distributed under the License is distributed on an "AS IS" basis,
-WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
-the specific language governing rights and limitations under the License.
-
-The Original Code is: JvChart.PAS, released on 2003-09-30.
-
-The Initial Developers of the Original Code are
- Warren Postma (TJvChart which was originally based on TAABGraph)
- Mårten Henrichson (TAABGraph)
-
-Contributor(s):
- Warren Postma (warrenpstma att hotmail dott com)
- Mårten Henrichson/AABSoft (no email known)
-
- Contains some code which is
- (C) 1996-1998 AABsoft and Mårten Henrichson
-
- The rest is
- (C) 2003-2009 Warren Postma
- warren.postma att sympatico dott ca
- warrenpstma att hotmail dott com
-
-Last Modified:
-
- 2003-09-30 - (WP) - Alpha-Initial checkin of new component, into JVCL3 CVS tree.
- 2004-02-26 - (WP) - Pre-JVCL3.0-Has been substantially jedified, also new
- properties/events, and some renaming has occurred. See
- cvs logs. NEW: OnChartClick event.
- RENAME: Options.ThickLineWidth -> Options.PenLineWidth
- RENAME: Values -> ValueIndex
- 2004-04-10 - (WP) - Much improved Charting! Beta-Quality in most places.
- Significant property reorganization and renaming.
- Primary and Secondary Y (vertical) Axis support.
- 2004-07-06 - (WP)- Added events OnYAxisClick (Left margin click),
- OnXAxisClick (Bottom margin), OnAltYAxisClick (Right margin)
- and OnTitleClick (Top Margin).
-
- 2005-01-14 - (WP) - Floating Chart Markers added. Major changes to painting
- code to allow canvas as a parameter. This is in preparation
- for fixing up the printing code to allow printing to work
- once again, and because the floating objects require us to
- draw the chart into a bitmap, and then decorate the bitmap
- dynamically with the floating objects, different
- canvases are used to paint the bitmap, and to paint the
- floating layer on top, thus the need for the changes.
-
- 2005-04-15 - (WP) - Changed internal Data storage from Array of Array to
- simple single-dimension array. This has many benefits,
- and at least one drawback. The benefit is that much
- larger sets of pens/data values can be accomodated.
- The drawback is that you can't add a pen to an already displayed
- chart without regenerating all the data points in it.
- If you change the pen count you now MUST clear the data,
- and re-plot the chart. Any attempt to add a pen,
- write the new pen, and then plot without rewriting the other
- values will cause data to be displayed in a corrupt fashion.
- I think this obscure limitation is better to live with than
- the many alternatives. The problem I have is that the chart
- supports extremely large data sets, and clearing the data
- MULTIPLE times would be a huge performance penalty in
- any application. You can enable the OLD mode, with it's
- limitations, by defining TJVCHART_ARRAY_OF_ARRAY.
-
- 2007-04-26 - (WP) - Merged upstream changes.
- - Added gradients (TJvChartGradientBar)
- - Added new way of doing date/time markers (Options.XAxisDateTimeMode),
- GraphXAxisLegend, and JvChart.Data properties StartDateTime, EndDateTime.
- - Added vertical markers (AddVerticalBar)
- - Added horizontal bars (TJvChartHorizontalBar) ClearHorizontalBars
- - Added FloatingMarkerCount.
- - New property in jvfloatingMarker: CaptionColor
- - Added DeleteFloatingMarkerObj
- - Graphical glitches/chart-display-bug-fixes.
- 2007-04-27 - (WP) - Fixes
- - Calls only JclMath.IsNaN, not Math.IsNaN, which doesn't
- exist on older Delphi/BCB versions.
- - Added CopyFloatingMarkers (thought I did that yesterday but missed it)
-
-You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
-located at http://jvcl.delphi-jedi.org
-
-To do:
-- Drawing of legend at right (clChartLegendRight) not implemented
-- Printing uses screen coordinates.
-- Update to changes made in the object inspector.
-
------------------------------------------------------------------------------}
-// $Id$
-
-unit JvChart;
-
-{$MODE OBJFPC}{$H+}
-{$DEFINE TJVCHART_ARRAY_OF_ARRAY}
-{.$DEFINE TEXT_BOX}
-
-interface
-
-uses
- LCLType, LCLIntf,
- Classes, Types, Graphics, Controls, Contnrs,
- JvComponent;
-
-const
- JvChartVersion = 300; // ie, version 3.00
-
- JvDefaultHintColor = TColor($00DDFBFA);
- JvDefaultAvgLineColor = TColor($00EEDDDD);
- JvDefaultDivisionLineColor = clLtGray;
- JvDefaultShadowColor = clDkGray;
- JvDefaultPaperColor = clWhite;
-
- JvDefaultYLegends = 20;
- MaxShowXValueInLegends = 10;
-
- // Special indices to GetPenColor(Index)
- jvChartAverageLineColorIndex = -6;
- jvChartDivisionLineColorIndex = -5;
- jvChartShadowColorIndex = -4;
- jvChartAxisColorIndex = -3;
- jvChartHintColorIndex = -2;
- jvChartPaperColorIndex = -1;
-
- JvChartDefaultMarkerSize = 3;
-
-type
- { CHART TYPES }
- TJvChartKind =
- (
- ckChartNone, // Blank graph.
- ckChartLine, // default type. Line and Marker plots.
- ckChartBar,
- ckChartStackedBar,
- ckChartBarAverage,
- ckChartStackedBarAverage,
- ckChartPieChart,
- //ckChartLineWithMarkers, // obsolete. use ckChartLine, and set PenMarkerKind to cmDiamond.
- ckChartMarkers,
- ckChartDeltaAverage
- );
-
- // ckChartLine can have a different pen type for each pen:
-
- TJvChartPenMarkerKind = (pmkNone, pmkDiamond, pmkCircle, pmkSquare, pmkCross);
-
- TJvChartGradientDirection = (grNone, grUp, grDown, grLeft, grRight); // WP
-
- TJvChartLegend = (clChartLegendNone, clChartLegendRight, clChartLegendBelow);
-
- {$IFDEF TJVCHART_ARRAY_OF_ARRAY}
- TJvChartDataArray = array of array of Double;
- {$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
- TJvChart = class;
-
- // TJvChartFloatingMarker.Caption position enumerator:
- TJvChartCaptionPosition =
- (
- cpMarker, // put right where the marker is
- cpXAxisBottom, // put below the symbol marker, in the bottom margin
- cpXAxisTop, // put above the symbol marker, in the top margin
- cpTitleArea
- );
-
- TJvChartFloatingMarker = class(TPersistent) // was from TObject
- private
- FOwner: TJvChart;
- procedure SetCaptionColor(const Value: TColor); // Which chart does it belong to?
- protected
- FRawXPosition: Integer; // raw pixel-based X position.
- FRawYPosition: Integer; // raw pixel-based Y position.
- FDragging: Boolean; // drag in progress!
- FVisible: Boolean; // Make chart marker object visible or invisible.
- FIndex: Integer; // Which marker is this?
- FTag: Integer; // User assignable Integer like TComponent.Tag
- FMarker: TJvChartPenMarkerKind; // What symbol to plot at this position?
- FMarkerColor: TColor; // Marker color.
- FXPosition: Integer; // Plot at same X co-ordinates as Data Sample X.
- FYPosition: Double; // Plot at Y height as data
- FXDraggable: Boolean; // Can marker be dragged horizontally?
- FXDragMin: Integer; // Minimum X Position that we can drag to.
- FXDragMax: Integer; // Maximum X Position that we can drag to.
- FYDraggable: Boolean; // Can marker be dragged vertically?
- //FYPositionToPen:Integer; // YPosition copied from Pen Values. (-1=disable feature, 0=first pen,1=second pen,...)
- FLineToMarker: Integer; // If -1 then none. Otherwise, index of another marker object
- FLineVertical: Boolean; // If true, then this object plots a vertical divider line.
- FLineStyle: TPenStyle; // Line style (solid,dashed,etc)
- FLineColor: TColor; // Line color.
- FLineWidth: Integer;
- FCaption: string; // Caption to print above the marker, or if no marker, then just this text is plotted.
- FCaptionColor: TColor; // New 2007 - WP - Color of floating marker caption
- FCaptionPosition: TJvChartCaptionPosition;
- FCaptionBoxed: Boolean; // Marker caption can have a box around it to make it more readable for some uses.
-
- //FCaptionBorderStyle:TPenStyle; // Style of border around caption, or psClear if no border.
- //FCaptionBorderColor:TColor; //
-
- //PROTECTED CONSTRUCTOR: Only TJvChart should create a new marker object:
- constructor Create(Owner: TJvChart);
-
- procedure SetCaption(ACaption: string);
- procedure SetXPosition(XPos: Integer); // should invalidate the chart (FOwner) if changed.
- procedure SetYPosition(YPos: Double); // should invalidate the chart (FOwner) if changed.
-
- procedure SetVisible(AVisible: Boolean);
- public
- property Index: Integer read FIndex;
-
- procedure Assign(Source: TPersistent); override; // Should be able to copy from one floating marker to another
-
- property Marker: TJvChartPenMarkerKind read FMarker write FMarker;
- property MarkerColor: TColor read FMarkerColor write FMarkerColor; // Marker color.
- property Visible: Boolean read FVisible write FVisible; // Make chart marker object visible or invisible.
- property XPosition: Integer read FXPosition write SetXPosition;
- property YPosition: Double read FYPosition write SetYPosition;
- property XDraggable: Boolean read FXDraggable write FXDraggable;
- property XDragMin: Integer read FXDragMin write FXDragMin;
- property XDragMax: Integer read FXDragMax write FXDragMax;
- property YDraggable: Boolean read FYDraggable write FYDraggable;
- //property YPositionToPen :Integer read FYPositionToPen write FYPositionToPen;
- property LineToMarker: Integer read FLineToMarker write FLineToMarker;
- property LineVertical: Boolean read FLineVertical write FLineVertical;
- property LineStyle: TPenStyle read FLineStyle write FLineStyle;
- property LineColor: TColor read FLineColor write FLineColor;
- property LineWidth: Integer read FLineWidth write FLineWidth;
- property Caption: string read FCaption write FCaption;
- property CaptionColor: TColor read FCaptionColor write SetCaptionColor;
- property CaptionPosition: TJvChartCaptionPosition read FCaptionPosition write FCaptionPosition;
- property CaptionBoxed: Boolean read FCaptionBoxed write FCaptionBoxed;
-
- property Tag: Integer read FTag write FTag; // User assignable Integer like TComponent.Tag
-
- //property CaptionBorderStyle :TPenStyle read FCaptionBorderStyle write FCaptionBorderStyle;
- //property CaptionBorderColor :TColor read FCaptionBorderColor write FCaptionBorderColor;
- end;
-
- TJvChartGradientBar = class(TObject) // NEW 2007
- private
- FOwner: TJvChart; // Which chart does it belongs to?
- FVisible: Boolean;
- //FRawRect: TRect; // raw pixel-based X position.
- FColor: TColor;
- FIndex: Integer;
- FGradDirection: TJvChartGradientDirection;
- FGradColor: TColor;
- FPenStyle:TPenStyle; // april 2009
- FPenColor:TColor; // april 2009
- protected
- FYTop, FYBottom: Double;
- constructor Create(Owner: TJvChart);
- procedure SetVisible(AVisible: Boolean);
- procedure SetColor(AColor: TColor);
- procedure SetGradientColor(AColor: TColor);
- procedure SetGradientType(AType: TJvChartGradientDirection);
- public
- property Visible: boolean read FVisible write SetVisible;
- property YTop: Double read FYTop write FYTop;
- property YBottom: Double read FYBottom write FYBottom;
- property Color: TColor read FColor write SetColor;
- property GradDirection: TJvChartGradientDirection read FGradDirection write FGradDirection;
- property GradColor: TColor read FGradColor write FGradColor;
- property PenStyle:TPenStyle read FPenStyle write FPenStyle; // april 2009
- property PenColor:TColor read FPenCOlor write FPenColor; // april 2009
- end;
-
- TJvChartHorizontalBar = class(TJvChartGradientBar) // NEW 2007
- {
- private
- FYTop: Double;
- FYBottom: Double;
- }
- protected
- constructor Create(Owner: TJvChart);
- public
- property YTop: Double read FYTop write FYTop;
- property YBottom: Double read FYBottom write FYBottom;
- end;
-
- TJvChartVerticalBar = class(TJvChartGradientBar) // NEW 2007
- private
- FXLeft: Integer;
- FXRight: Integer;
- protected
- constructor Create(Owner: TJvChart);
- public
- property XLeft: Integer read FXLeft write FXLeft;
- property XRight: Integer read FXRight write FXRight;
- end;
-
- { TJvChartData : Holds NxN array of Reals, Resizes automatically within preset
- limits. Provides a functionality mix of dynamic memory use, but with
- a memory cap, so we don't thrash the system or leak forever. -WAP.}
- TJvChartData = class(TObject)
- private
- {$IFDEF TJVCHART_ARRAY_OF_ARRAY}
- FData: TJvChartDataArray;
- {$ELSE}
- FData: array of Double;
- {$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
- FClearToValue: Double; // Typically either 0.0 or NaN
- FTimeStamp: array of TDateTime; // Time-series as a TDateTime
- // Dynamic array of dynamic array of Double.
- // is empty until data is stored in them.
- // *** Order of indexing: FData[ValueIndex,Pen] ***
- FDataAlloc: Integer; // Last Allocated Value.
- FValueCount: Integer; // Number of sample indices used
- FPenCount: Integer; // can't be changed without erasing all data!
-
- FStartDateTime: TDateTime; // needed for DateTime mode, and datetime axis labels! NEW 2007
- FEndDateTime: TDateTime;
- procedure SetEndDateTime(const Value: TDateTime);
- procedure SetStartDateTime(const Value: TDateTime);
- // needed for DateTime mode, and datetime axis labels! NEW 2007
- protected
- procedure Grow(Pen, ValueIndex: Integer);
- //GetValue/SetValue resizer, also throws exception if Pen,ValueIndex is negative or just way too big.
- function GetValue(Pen, ValueIndex: Integer): Double;
- procedure SetValue(Pen, ValueIndex: Integer; NewValue: Double);
- function GetTimestamp(ValueIndex: Integer): TDateTime;
- procedure SetTimestamp(ValueIndex: Integer; AValue: TDateTime);
- public
- constructor Create;
- destructor Destroy; override;
-
- procedure PreGrow(Pen, ValueIndex: Integer); // Advanced users. Allocate a large batch of memory in advance.
-
- function DebugStr(ValueIndex: Integer): string; // dump all pens for particular valueindex, as string.
-
- procedure Clear; // Resets All Data to zero.
- procedure ClearPenValues; // Clears all pen values to NaN but does not reset pen definitions etc.
- procedure Scroll;
- property Value[Pen, ValueIndex: Integer]: Double read GetValue write SetValue; default;
- property Timestamp[ValueIndex: Integer]: TDateTime read GetTimestamp write SetTimestamp;
- property ValueCount: Integer read FValueCount write FValueCount;
- property ClearToValue: Double read FClearToValue write FClearToValue; // Typically either 0.0 or NaN. default 0.0
-
- // NEW 2007 [for DateTimeMode XAxis Labels]
- property StartDateTime: TDateTime read FStartDateTime write SetStartDateTime;
- // needed for DateTime mode, and datetime axis labels! NEW 2007
- property EndDateTime: TDateTime read FEndDateTime write SetEndDateTime;
- // needed for DateTime mode, and datetime axis labels! NEW 2007
- end;
-
- TJvChartPaintEvent = procedure(Sender: TJvChart; ACanvas: TCanvas) of object;
- TJvChartEvent = procedure(Sender: TJvChart) of object;
- TJvChartFloatingMarkerDragEvent = procedure(Sender: TJvChart; FloatingMarker: TJvChartFloatingMarker) of object; {NEW}
-
- TJvChartClickEvent = procedure(Sender: TJvChart;
- Button: TMouseButton; { left/right mouse click?}
- Shift: TShiftState; { keyboard shift state?}
- X, Y: Integer; { mouse position}
- ChartValueIndex: Integer; { what value in the chart? }
- ChartPenIndex: Integer; { what pen was clicked? }
- { User modifiable return values for custom hinting! }
- var ShowHint, HintFirstLineBold: Boolean; HintStrs: TStrings) of object; {NEW}
-
- TJvChartOptions = class;
-
- { There are TWO Y Axis per graph, optionally:
- Chart.Options.PenAxis[I] -and-
- Chart.Options.SecondaryYAxisOne
- The primary one is displayed along the left side, and the one
- for the right side is only displayed if you need it.
- Properties for each side are grouped by the
- TJvChartYAxisOptions persistent-properties-object.
- }
- TJvChartYAxisOptions = class(TPersistent)
- private
- FOwner: TJvChartOptions;
- FActive: Boolean; // One or more pens use this Y Axis.
- protected
- FYMax: Double; // Y Scale value at the top left hand side of chart.
- FYMin: Double; // Y Scale value at the bottom left hand side of the chart (default 0)
- FYGap: Double; // Number of values per Y scale division
- FYGap1: Double; // Gap multiplication factor for value scaling.
- FMarkerValueDecimals: Integer; // Decimal places on marker-values (only applies to Marker Pens with Values)
- FYDivisions: Integer; // Number of vertical divisions in the chart. (default 10)
- FMaxYDivisions: Integer;
- FMinYDivisions: Integer;
- FYLegendDecimalPlaces: Integer;
- FYLegends: TStringList;
- FDefaultYLegends: Integer; // Number of default Y legends.
- FYPixelGap: Double;
- procedure SetYMax(NewYMax: Double);
- procedure SetYMin(NewYMin: Double);
- // procedure SetYGap(newYgap: Double);
- function GetYLegends: TStrings;
- procedure SetYLegends(Value: TStrings);
- procedure SetYDivisions(AValue: Integer);
- procedure SetYPixelGap(AValue: Double);
- public
- constructor Create(Owner: TJvChartOptions); virtual;
- destructor Destroy; override;
- procedure Assign(Source:TPersistent); override;// Added Sept 2009
- procedure Normalize;
- procedure Clear;
- // runtime only properties
- property YPixelGap: Double read FYPixelGap write SetYPixelGap;
- property Active: Boolean read FActive;
- property YGap: Double read FYGap;
- property YGap1: Double read FYGap1; // Gap multiplication factor for value scaling.
- property YLegends: TStrings read GetYLegends write SetYLegends; { Y Axis Legends as Strings }
- published
- property YMax: Double read FYMax write SetYMax;
- property YMin: Double read FYMin write SetYMin;
- property YDivisions: Integer read FYDivisions write SetYDivisions default 10;
- // Number of vertical divisions in the chart
- // YDivisions->YDivisions
- property MaxYDivisions: Integer read FMaxYDivisions write FMaxYDivisions default 20;
- property MinYDivisions: Integer read FMinYDivisions write FMinYDivisions default 5;
- property MarkerValueDecimals: Integer read FMarkerValueDecimals write FMarkerValueDecimals default -1;
- // Decimal places on marker-values (only applies to Marker Pens with Values)
- property YLegendDecimalPlaces: Integer read FYLegendDecimalPlaces write FYLegendDecimalPlaces;
- property DefaultYLegends: Integer read FDefaultYLegends write FDefaultYLegends default JvDefaultYLegends;
- end;
-
- TJvChartOptions = class(TPersistent)
- private
- FOwner: TJvChart;
- {accessors}
- function GetAverageValue(Index: Integer): Double;
- procedure SetAverageValue(Index: Integer; AValue: Double);
- function GetPenColor(Index: Integer): TColor;
- function GetPenStyle(Index: Integer): TPenStyle;
- function GetPenMarkerKind(Index: Integer): TJvChartPenMarkerKind;
- function GetPenSecondaryAxisFlag(Index: Integer): Boolean;
- procedure SetPenSecondaryAxisFlag(Index: Integer; NewValue: Boolean);
- function GetPenValueLabels(Index: Integer): Boolean;
- procedure SetPenValueLabels(Index: Integer; NewValue: Boolean);
- // TStrings<->TStringList transmogrifiers
- function GetPenLegends: TStrings;
- function GetPenUnit: TStrings;
- procedure SetPenUnit(Value: TStrings);
- function GetXLegends: TStrings;
- procedure SetXLegends(Value: TStrings);
- procedure SetHeaderFont(AFont: TFont);
- procedure SetLegendFont(AFont: TFont);
- procedure SetAxisFont(AFont: TFont);
- procedure SetPrimaryYAxis(AssignFrom: TJvChartYAxisOptions);
- procedure SetSecondaryYAxis(AssignFrom: TJvChartYAxisOptions);
- // Each pen can be associated with either the primary or secondary axis,
- // this function decides which axis to return depending on the pen configuration:
- function GetPenAxis(Index: Integer): TJvChartYAxisOptions;
-
- procedure SetAxisLineWidth(const Value: Integer);
- procedure SetAxisTitleFont(const Value: TFont);
- procedure SetChartKind(AKind: TJvChartKind);
- procedure SetDivisionLineColor(const AColor: TColor);
- procedure SetFillUnderline(const AValue: Boolean);
- procedure SetLegend(const ALegend: TJvChartLegend);
- procedure SetMarkerSize(const Value: Integer);
- procedure SetPaperColor(const AColor: TColor);
- procedure SetPenColor(Index: Integer; AColor: TColor);
- procedure SetPenCount(Count: Integer);
- procedure SetPenLegends(Value: TStrings);
- procedure SetPenLineWidth(const Value: Integer);
- procedure SetPenMarkerKind(Index: Integer; AMarkKind: TJvChartPenMarkerKind);
- procedure SetPenStyle(Index: Integer; APenStyle: TPenStyle);
- procedure SetShadowColor(const AColor: TColor);
- procedure SetTitle(const Value: String);
- procedure SetXAxisDateTimeDivision(const Value: Double);
- procedure SetXAxisHeader(const Value: String);
- procedure SetXStartOffset(Offset: Integer);
- procedure SetYAxisHeader(const Value: String);
- procedure SetYStartOffset(Offset: Integer);
- protected
- FChartKind: TJvChartKind; // default JvChartLine
- {runtime pixel spacing multipliers}
- FXPixelGap: Double;
- {Fonts}
- FHeaderFont: TFont;
- FLegendFont: TFont;
- FAxisFont: TFont;
- FAxisTitleFont: TFont;
- FTitle: string;
- FNoDataMessage: string;
- FYAxisHeader: string;
- FYAxisDivisionMarkers: Boolean; // Do you want grid-paper look?
- FXAxisDivisionMarkers: Boolean; // Do you want grid-paper look?
- FXAxisHeader: string;
- FMarkerSize:Integer;
- FFillUnderLine : Boolean;
- FXLegends: TStringList; // Text labels.
- FXLegendMaxTextWidth: Integer; // runtime: display width (pixels) of widest string in FXLegends[1:X].
- FXAxisValuesPerDivision: Integer;
- // Number of Values (aka samples) in each vertical dotted lines that are divisision marker.
- FXAxisLegendSkipBy: Integer; //1=print every X axis label, 2=every other, and so on. default=1
- FXLegendHoriz: Integer; // Horizontally oriented GraphXAxisLegend ends at this X Point.
- FXAxisLabelAlignment: TAlignment; // New: Text alignment for X axis labels. Default is left alignment.
- FXAxisDateTimeMode: Boolean;
- // False=use custom text labels, True=Use Date/Time Stamps as X axis labels. [REWORKED LOGIC IN 2007!]
- FXAxisDateTimeDivision: Double; // NEW 2007 : What is the nominal date/time division (1.0=day, 1.0/24=1 hour)
- FXAxisDateTimeFormat: string; // Usually a short date-time label, hh:nn:ss is good.
- FDateTimeFormat: string;
- // Usually a long date-time label, ISO standard yyyy-mm-dd hh:nn:ss is fine, as is Windows locale defaults.
- FXValueCount: Integer;
- // Number of pens:
- FPenCount: Integer;
- // Per-pen array/list properties
- FPenColors: array of TColor;
- FPenStyles: array of TPenStyle; // solid, dotted
- FPenMarkerKind: array of TJvChartPenMarkerKind;
- FPenSecondaryAxisFlag: array of Boolean; // False=Primary Y Axis, True=Secondary Y Axis.
- FPenValueLabels: array of Boolean;
- FPenLegends: TStringList;
- FPenUnit: TStringList;
- FAverageValue: array of Double; // Used in averaging chart types only.
- FPrimaryYAxis: TJvChartYAxisOptions;
- FSecondaryYAxis: TJvChartYAxisOptions;
- FXGap: Double; // Number of pixels per X scale unit.
- FXOrigin: Integer; {which value corresponds to Origin}
- FYOrigin: Integer; // Vertical (Y) Position of the Origin point, and X axis.
- FXStartOffset: Longint; {margin} // Horizontal (X) Position of the Origin point, and Y Axis
- FYStartOffset: Longint; // height of the top margin above the charting area.
- FXEnd: Longint; { From top left of control, add XEnd to find where the right margin starts }
- FYEnd: Longint; { from top left of control, add YEnd to find where the below-the bottom margin starts }
- { more design time }
- FLegendWidth: Integer;
- FLegendRowCount: Integer; // Number of lines of text in legend.
- FAutoUpdateGraph: Boolean;
- FMouseEdit: Boolean;
- FMouseDragObjects: Boolean; // Can mouse drag floating objects?
- FMouseInfo: Boolean;
- FLegend: TJvChartLegend; // was FShowLegend, now Legend=clChartLegendRight
- FPenLineWidth: Integer;
- FAxisLineWidth: Integer;
-
- //COLORS:
- FPaperColor: TColor;
- FDivisionLineColor: TColor; // NEW! Division line
- FShadowColor: TColor; // NEW! Shadow color
- FAxisLineColor: TColor; // Color of box around chart plot area.
- FHintColor: TColor; // Hint box color
- FAverageLineColor: TColor; // Pen color for Charts with auto-average lines.
- FCursorColor: TColor; // Sample indicator Cursor color
-
- FCursorStyle: TPenStyle; // Cursor style.
- FGradientColor: TColor; // new 2007
- FGradientDirection: TJvChartGradientDirection; // new 2007
-
- // INTERNALS :NEW STUFF IN 2007
- FXAxisDateTimeFirstMarker: Integer; // at XValue initial offset NEW 2007
- FXAxisDateTimeSkipBy: Integer; // an XValue indexing multiplier NEW 2007
- FXAxisDateTimeLines: Integer; // number of lines we're displaying NEW 2007
-
- { event interface }
- procedure NotifyOptionsChange;
- public
- constructor Create(Owner: TJvChart); virtual;
- destructor Destroy; override;
- procedure Assign(Source:TPersistent); override;// Warren Added Sept 2009.
-
- { runtime properties }
- property AverageValue[Index: Integer]: Double read GetAverageValue write SetAverageValue;
- property PenAxis[Index: Integer]: TJvChartYAxisOptions read GetPenAxis;
- property XLegends: TStrings read GetXLegends write SetXLegends; { X Axis Legends as Strings }
- { plot-canvas size, depends on size of control }
- property XEnd: Longint read FXEnd write FXEnd;
- property YEnd: Longint read FYEnd write FYEnd;
- {Gradient NEW 2007 }
- property GradientColor: TColor read FGradientColor write FGradientColor; // new 2007
- property GradientDirection: TJvChartGradientDirection read FGradientDirection write FGradientDirection; // new 2007
-
- { pixel spacing : multipliers to scale real values into X/Y pixel amounts before plotting. CRITICALLY important. }
- property XPixelGap: Double read FXPixelGap write FXPixelGap;
- property XLegendMaxTextWidth: Integer read FXLegendMaxTextWidth write FXLegendMaxTextWidth;
- { Per Pen Array/List Properties -- settable at RUNTIME only. }
- property PenColor[Index: Integer]: TColor read GetPenColor write SetPenColor;
- property PenStyle[Index: Integer]: TPenStyle read GetPenStyle write SetPenStyle;
- property PenMarkerKind[Index: Integer]: TJvChartPenMarkerKind read GetPenMarkerKind write SetPenMarkerKind;
- property PenSecondaryAxisFlag[Index: Integer]: Boolean read GetPenSecondaryAxisFlag write SetPenSecondaryAxisFlag;
- property PenValueLabels[Index: Integer]: Boolean read GetPenValueLabels write SetPenValueLabels;
- published
- { design time}
- { Per Pen Array/List Properties - settable at DESIGNTIME. Others (color/style, marker) are runtime only. }
- property PenLegends: TStrings read GetPenLegends write SetPenLegends;
- property PenUnit: TStrings read GetPenUnit write SetPenUnit;
- property ChartKind: TJvChartKind read FChartKind write SetChartKind default ckChartLine;
- property Title: string read FTitle write SetTitle;
- property NoDataMessage: string read FNoDataMessage write FNoDataMessage;
- //NEW! NOV 2004. Optionally display this instead of fixed resource string rsNoData
-
- { X Axis Properties }
- // Do you want grid-paper look?
- { X Axis Properties }
- property XAxisDivisionMarkers: Boolean read FXAxisDivisionMarkers write FXAxisDivisionMarkers default True;
- // Do you want grid-paper look?
- property XAxisValuesPerDivision: Integer read FXAxisValuesPerDivision write FXAxisValuesPerDivision;
- // Number of Values (aka samples) in each vertical dotted lines that are divisision marker.
- property XAxisLabelAlignment: TAlignment read FXAxisLabelAlignment write FXAxisLabelAlignment;
- // New: Text alignment for X axis labels. Default is left alignment.
- property XAxisDateTimeMode: Boolean read FXAxisDateTimeMode write FXAxisDateTimeMode;
- // REWORKED LOGIC NEW IN 2007! See GraphXAxisDivisionMarkers
- property XAxisDateTimeDivision: Double read FXAxisDateTimeDivision write SetXAxisDateTimeDivision;
- // NEW 2007 : What is the nominal date/time division (1.0=day, 1.0/24=1 hour)
- property XAxisDateTimeFormat: string read FXAxisDateTimeFormat write FXAxisDateTimeFormat;
- property XAxisHeader: string read FXAxisHeader write SetXAxisHeader;
- property XAxisLegendSkipBy: Integer read FXAxisLegendSkipBy write FXAxisLegendSkipBy default 1;
-
- property DateTimeFormat: string read FDateTimeFormat write FDateTimeFormat;
- // Usually a long date-time label, ISO standard yyyy-mm-dd hh:nn:ss is fine, as is Windows locale defaults.
- property PenCount: Integer read FPenCount write SetPenCount default 1;
- property XGap: Double read FXGap write FXGap;
- property XOrigin: Integer read FXOrigin write FXOrigin;
- property YOrigin: Integer read FYOrigin write FYOrigin; // Position of bottom of chart (not always the zero origin)
- property XStartOffset: Longint read FXStartOffset write SetXStartOffset default 45;
- property YStartOffset: Longint read FYStartOffset write SetYStartOffset default 10;
-
- { Y Axis Properties }
- property YAxisHeader: string read FYAxisHeader write SetYAxisHeader;
- property YAxisDivisionMarkers: Boolean read FYAxisDivisionMarkers write FYAxisDivisionMarkers default True;
-
- { Y Range }
- { plotting markers }
- property MarkerSize: Integer read FMarkerSize write SetMarkerSize default JvChartDefaultMarkerSize;
- property FillUnderLine : Boolean read FFillUnderLine write SetFillUnderLine default False;
- { !! New: Primary (left side) Y axis, and Secondary (right side) Y Axis !!}
- property PrimaryYAxis: TJvChartYAxisOptions read FPrimaryYAxis write SetPrimaryYAxis;
- property SecondaryYAxis: TJvChartYAxisOptions read FSecondaryYAxis write SetSecondaryYAxis;
- //1=print every X axis label, 2=every other, and so on. default=1
- { vertical numeric decimal places }
- { more design time }
- property AutoUpdateGraph: Boolean read FAutoUpdateGraph write FAutoUpdateGraph default True;
- property MouseEdit: Boolean read FMouseEdit write FMouseEdit default True;
- property MouseDragObjects: Boolean read FMouseDragObjects write FMouseDragObjects;
- // Can mouse drag floating objects?
- property MouseInfo: Boolean read FMouseInfo write FMouseInfo default True;
- //OLD:property ShowLegend: Boolean read FShowLegend write FShowLegend default True;
- //CHANGEDTO:
- property Legend: TJvChartLegend read FLegend write SetLegend default clChartLegendNone;
- property LegendRowCount: Integer read FLegendRowCount write FLegendRowCount;
- property LegendWidth: Integer read FLegendWidth write FLegendWidth default 150;
- property PenLineWidth: Integer read FPenLineWidth write SetPenLineWidth default 1;
- property AxisLineWidth: Integer read FAxisLineWidth write SetAxisLineWidth default 2;
- { more and more design time. these ones not sure about whether they are designtime or not.}
- property XValueCount: Integer read FXValueCount write FXValueCount default 10;
- {Font properties}
- property HeaderFont: TFont read FHeaderFont write SetHeaderFont;
- property LegendFont: TFont read FLegendFont write SetLegendFont;
- property AxisFont: TFont read FAxisFont write SetAxisFont;
- property AxisTitleFont: TFont read FAxisTitleFont write SetAxisTitleFont;
- { Color properties}
- property DivisionLineColor: TColor read FDivisionLineColor write SetDivisionLineColor default
- JvDefaultDivisionLineColor; // NEW! Division line
- property ShadowColor: TColor read FShadowColor write SetShadowColor default JvDefaultShadowColor; // NEW! Shadow color
-
- property PaperColor: TColor read FPaperColor write SetPaperColor default clWhite;
- property AxisLineColor: TColor read FAxisLineColor write FAxisLineColor;
- property HintColor: TColor read FHintColor write FHintColor default JvDefaultHintColor;
- property AverageLineColor: TColor read FAverageLineColor write FAverageLineColor default JvDefaultAvgLineColor;
- property CursorColor: TColor read FCursorColor write FCursorColor;
- property CursorStyle: TPenStyle read FCursorStyle write FCursorStyle;
- end;
-
- TJvChart = class(TJvGraphicControl)
- private
- FUpdating: Boolean; // PREVENT ENDLESS EVENT LOOPING.
- FAutoPlotDone: Boolean; // If Options.AutoUpdateGraph is set, then has paint method called PlotGraph already?
- FPlotGraphCalled: Boolean; // Has bitmap ever been painted?
- FInPlotGraph: Boolean; // recursion blocker.
-
- // NEW: The component has always had a feature when you click on margin areas
- // that the user can enter a value (Y Axis Scale, title, and X header)
- // The right margin however didn't do anything. Now all four have a user
- // event that can be fired. If you don't want the default editor behaviours
- // turn off Options.MouseEdit to make it 100% user-defined what happens when
- // the user clicks on an area of the chart.
- FOnYAxisClick: TJvChartEvent; // Left margin (Primary Y Axis labels) click
- FOnXAxisClick: TJvChartEvent; // Bottom margin (X Axis Header) click
- FOnAltYAxisClick: TJvChartEvent; // Right margin click (Secondary Y Axis labels)
- FOnTitleClick: TJvChartEvent; // Title area click (Top margin)
- FOnChartClick: TJvChartClickEvent; // mouse click event
- FOnBeginFloatingMarkerDrag: TJvChartFloatingMarkerDragEvent;
- FOnEndFloatingMarkerDrag: TJvChartFloatingMarkerDragEvent;
- //FOnChartPaint: TJvChartPaintEvent; // wrong event. bugfix requires removal.
- FMouseDownShowHint: Boolean; // True=showing hint.
- FMouseDownHintBold: Boolean; // True=first line of hint is bold.
- FMouseDownHintStrs: TStringList;
-
- FExtPicture:TPicture; // An external image!
-
- { TImage stuff}
- FPicture: TPicture; // An image drawn via GDI primitives, saveable as
- // bitmap or WMF, or displayable to screen
- FData: TJvChartData;
-
- FDragFloatingMarker: TJvChartFloatingMarker; //Current object we are dragging ( nil=none )
- FFloatingMarker: TObjectList; // NEW: collection of TJvChartFloatingMarker objects.
- FHorizontalBars: TObjectList; // NEW 2007
- FVerticalBars: TObjectList; // NEW 2007
-
- FAverageData: TJvChartData;
- FBitmap: TBitmap;
- FOptions: TJvChartOptions; //^TOptions;
- //Options2 : ^TOptions2; // now FData
- PrintInSession: Boolean;
- FStartDrag: Boolean;
- FMouseLegend: Boolean;
- FContainsNegative: Boolean;
- { strColorFile: string;}// not used (ahuser)
- FOldYOrigin: Integer;
- FOldYGap: Double;
- FMouseDownX: Longint;
- FMouseDownY: Longint;
- FMouseValue: Integer;
- FMousePen: Integer;
-// FYFont: TFont; // Delphi Font object wrapper.
- //NEW:
- FXOrigin: Double; {was in TJvChart.PlotGraph}
- FYOrigin: Double; {was in TJvChart.PlotGraph}
- FXAxisPosition: Integer; // how far down (in Y dimension) is the X axis?
- FOnOptionsChangeEvent: TJvChartEvent; { Component fires this event for when options change.}
- FOnPaint: TJvChartPaintEvent; {NEW JAN 2005: Custom paint event called from TjvChart.Paint.}
-
- FCursorPosition: Integer; // NEW: -1 means no visible cursor, 0..n means make
- // particular value highlighted. The highlight is painted
- // over top of the TImage, so that we can just restore the TImage
- // without replotting the whole chart.
- // Y Axis Vertical Font
- // FYFontHandle: HFONT; // Y AXIS VERTICAL TEXT: Vertical Font Handle (remember to DeleteObject)
-// FYLogFont: TLogFont; // Y AXIS VERTICAL TEXT: Logical Font Options Record
-// procedure MakeVerticalFont; // Call GDI calls to get the Y Axis Vertical Font handle
-// procedure MyGraphVertFont(ACanvas: TCanvas); // vertical font handle
- procedure PaintCursor; // called from Paint iif a Cursor is visible. does NOT modify FPicture!
- protected
- procedure DrawFloatingMarkers;
- procedure DrawHorizontalBars; // NEW 2007
- procedure DrawVerticalBars; // NEW 2007
- procedure DrawGradient; // NEW 2007
-
- procedure DrawChartLegendBelow(ACanvas: TCanvas); {accidentally deleted during Jedi_new to Jedi_2009 branch. Restored by WP Sept 2009}
-
- function GetFloatingMarker(Index: Integer): TJvChartFloatingMarker;
- function GetHorizontalBar(index:integer):TJvChartHorizontalBar; // new 2009
- function GetVerticalBar(index:integer):TJvChartVerticalBar; // new 2009
-
- { Right Side Legend showing Pen Names, and/or Data Descriptors }
- procedure GraphXAxisLegendMarker(ACanvas: TCanvas; MarkerKind: TJvChartPenMarkerKind; X, Y: Integer);
- procedure GraphXAxisLegend;
- procedure MyHeader(ACanvas: TCanvas; StrText: string);
- procedure MyXHeader(ACanvas: TCanvas; StrText: string);
- procedure MyYHeader(ACanvas: TCanvas; StrText: string); // NEW
- procedure MyHeaderFont(ACanvas: TCanvas);
- procedure MyAxisFont(ACanvas: TCanvas);
- procedure MyAxisTitleFont(ACanvas: TCanvas; Vertical: Boolean);
- procedure MySmallGraphFont(ACanvas: TCanvas);
- function MyTextHeight(ACanvas: TCanvas; StrText: string): Longint;
- { TEXTOUT stuff }
- procedure MyRightTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string); // RIGHT TEXT
- procedure MyCenterTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string); // CENTER TEXT
- procedure MyLeftTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string; Vertical: Boolean = false); // LEFT ALIGN TEXT
-
- // Use HintColor:
- procedure MyLeftTextOutHint(ACanvas: TCanvas; X, Y: Integer; const AText: string);
-
- { line, curve, rectangle stuff }
- procedure MyPenLineTo(ACanvas: TCanvas; X, Y: Integer);
- procedure MyAxisLineTo(ACanvas: TCanvas; X, Y: Integer);
- procedure MyRectangle(ACanvas: TCanvas; X, Y, X2, Y2: Integer);
- procedure MyColorRectangle(ACanvas: TCanvas; Pen: Integer; X, Y, X2, Y2: Integer);
- procedure MyPie(ACanvas: TCanvas; X1, Y1, X2, Y2, X3, Y3, X4, Y4: Longint); { pie chart segment }
- // procedure MyArc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); { arc } // not used (ahuser)
-
- // procedure MyEllipse(X1, Y1, X2, Y2: Integer); // not used (ahuser)
- procedure MyDrawLine(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer); // not used (ahuser)
- procedure MyDrawAxisMark(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer); // solid line as a tick on an axis.
- procedure MyDrawDotLine(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer);
-
- procedure EditXHeader;
- procedure EditYScale;
- procedure EditHeader;
-
- procedure SetSolidLines(ACanvas: TCanvas);
- procedure SetDotLines(ACanvas: TCanvas);
-
- procedure SetLineColor(ACanvas: TCanvas; Pen: Integer);
- procedure SetRectangleColor(ACanvas: TCanvas; Pen: Integer);
- procedure SetFontColor(ACanvas: TCanvas; Pen: Integer);
- procedure CountGraphAverage;
- procedure DrawPenColorBox(ACanvas: TCanvas; NColor, W, H, X, Y: Integer);
- { function GetDefaultColorString(nIndex: Integer): string;}// (rom) not used
- procedure MyPiePercentage(X1, Y1, W: Longint; NPercentage: Double);
- procedure GraphPieChart(NPen: Integer);
- procedure GraphDeltaAverage;
- procedure MyPieLegend(NPen: Integer);
- procedure ShowMouseMessage(X, Y: Integer);
- // marker symbols:
- procedure MyPolygon(ACanvas: TCanvas; Points: array of TPoint);
- procedure PlotCross(ACanvas: TCanvas; X, Y: Integer);
- procedure PlotDiamond(ACanvas: TCanvas; X, Y: Integer);
- procedure PlotFilledDiamond(ACanvas: TCanvas; X, Y: Integer);
- procedure PlotCircle(ACanvas: TCanvas; X, Y: Integer);
- procedure PlotSquare(ACanvas: TCanvas; X, Y: Integer);
-
- procedure PlotMarker(ACanvas: TCanvas; MarkerKind: TJvChartPenMarkerKind; X, Y: Integer);
- // Calls one of the Plot functions.
-
- procedure ClearScreen;
- // internal graphics methods
- procedure GraphSetup; // These set up variables used for all the rest of the plotting functions
- procedure GraphXAxis;
- procedure GraphYAxis;
- procedure GraphYAxisDivisionMarkers;
- procedure GraphXAxisDivisionMarkers; // new.
- function CalcXAxisTextHeight: Integer; // calculate height of x axis labels and title;
- procedure CalcYEnd; // Determine where the below-the bottom axis area starts
-
- function GetChartCanvas(isFloating:Boolean): TCanvas; // Get Picture.Bitmap Canvas.
- function GetChartCanvasWidth: Integer; //WP NEW 2007
- function GetChartCanvasHeight: Integer; //WP NEW 2007
-
- function DestRect: TRect; // from TImage
- procedure DesignModePaint; virtual; // Invoked by Paint method when we're in design mode.
- procedure Paint; override; // from TImage
- procedure Resize; override; // from TControl
- procedure Loaded; override;
- { draw dummy data for design mode}
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
-
- procedure PrimaryYAxisLabels; // Put contents into Options.PrimaryYAxis.YLegends
- procedure NotifyOptionsChange; {NEW}
-
- procedure InternalPlotGraph; { internal version of _PlotGraph that doesn't call Invalidate. }
-
- { internal drawing properties, valid during Paint method invocations only }
- property XOrigin: Double read FXOrigin; {was in TJvChart.PlotGraph}
- property YOrigin: Double read FYOrigin; {was in TJvChart.PlotGraph}
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
-
- // Get the X and Y Value for a particular Mouse location:
- function MouseToXValue(X: Integer): Integer;
- // convert X pixel mouse position to data index, ie Data.Values[..,].
- function MouseToYValue(Y: Integer): Double;
- // convert Y pixel mouse position to value in range Options.PrimaryYAxis.Min to Options.PrimaryYAxis.mAx
-
- {General procedures for the graph...}
- procedure ResetGraphModule; {Call this before totally new values and Pen}
- //procedure AutoFormatGraph; {XXX BAD CODE. TO BE DELETED. MAY BE REPLACED LATER BY NEW AutoRange FUNCTION!}
-
- procedure PlotGraph; {Update screen / draw graph to screen. calls Invalidate. Don't call from inside Paint code!}
-
- procedure PlotPicture( picture : TPicture; fontScaling:Double );
-
- procedure PrintGraph; {Send picture to printer; all printing done by component}
- procedure AddGraphToOpenPrintCanvas(XStartPos, YStartPos, GraphWidth, GraphHeight: Longint);
- {adds the graph to the "OPEN" printer canvas}
- {printing control=outside this component; add other text etc}
- procedure GraphToClipboard; {Puts picture on clipboard}
- procedure ResizeChartCanvas; {Call this after screen resize and after start up}
- procedure PivotData; { Pivot Table. Switches the x values with Pen! Resets AverageLine}
- procedure AutoHint; // Make the automatic hint message showing all pens and their values.
- procedure SetCursorPosition(Pos: Integer);
- procedure DisplayBars; // NEW 2007
-
- // FLOATING MARKERS: NEW JAN 2005. -WP
- function AddFloatingMarker: TJvChartFloatingMarker; // NEW Jan 2005!
-
- property FloatingMarker[Index: Integer]: TJvChartFloatingMarker read GetFloatingMarker; // NEW Jan 2005!
- property HorizontalBar[Index:Integer]:TJvChartHorizontalBar read GetHorizontalBar; // new 2009
- property VerticalBar[Index:Integer]:TJvChartVerticalBar read GetVerticalBar; // new 2009
-
- procedure DeleteFloatingMarker(Index: Integer); // NEW Jan 2005!
-
- // --NEW 2007 METHOD--
-
- procedure DeleteFloatingMarkerObj(Marker: TJvChartFloatingMarker); // NEW 2007
- procedure CopyFloatingMarkers(Source: TJvChart);
- procedure ClearFloatingMarkers;
- function FloatingMarkerCount: Integer; // NEW 2007
-
- function AddHorizontalBar: TJvChartHorizontalBar; // NEW 2007
- procedure ClearHorizontalBars; // NEW 2007
- function HorizontalBarsCount: Integer; // NEW 2007
-
- function AddVerticalBar: TJvChartVerticalBar; // NEW 2007
- procedure ClearVerticalBars; // NEW 2007
- function VerticalBarsCount: Integer; // NEW 2007
-
- // -- END NEW 2007 METHOD--
-
- property Data: TJvChartData read FData;
- property AverageData: TJvChartData read FAverageData;
- public
- {runtime only helper properties}
- { TImage-like stuff }
- property Picture: TPicture read FPicture; // write SetPicture;
- // NEW: Ability to highlight a particular sample by setting the Cursor position!
- property CursorPosition: Integer read FCursorPosition write SetCursorPosition;
- // procedure DataTests; // TESTING. WAP.
- published
- { Standard TControl Stuff}
- //property Color default clWindow;
- property Font;
- property Align;
- property Anchors;
- property BorderSpacing;
- property Constraints;
- property OnDblClick; { TNotifyEvent from TControl }
- property AutoSize;
- property DragCursor;
- property DragKind;
- //property OnKeyDown; // Tried to add this, but it was too hard. -WP APril 2004.
- property DragMode;
- property Enabled;
- property ParentShowHint;
- property PopupMenu;
- property ShowHint;
- property Visible;
- { chart options}
- property Options: TJvChartOptions read FOptions write FOptions;
- { chart events}
-
- property OnChartClick: TJvChartClickEvent read FOnChartClick write FOnChartClick;
-
- property OnChartPaint: TJvChartPaintEvent read FOnPaint write FOnPaint; // Chart paint event fixed Sept 2009
- // After chart bitmap is painted onto control surface we can "decorate" it with owner-drawn extras.
-
- { Drag and Drop of Floating Marker Events - NEW Jan 2005 -WP}
- property OnBeginFloatingMarkerDrag: TJvChartFloatingMarkerDragEvent read FOnBeginFloatingMarkerDrag write
- FOnBeginFloatingMarkerDrag; // Drag/drop of floating markers beginning.
- property OnEndFloatingMarkerDrag: TJvChartFloatingMarkerDragEvent read FOnEndFloatingMarkerDrag write
- FOnEndFloatingMarkerDrag; // Drag/drop of floating markers ending.
-
- {
- Chart Margin Click Events - you can click on the four
- 'margin' areas (left,right,top,bottom) around the main chart
- area. The left and top margins have default behaviours
- which you can disable by turning off Options.MouseEdit.
- The other 2 margin areas are entirely up to the user to define.
- Clicking bottom or right margins does nothing by default.
- }
- property OnYAxisClick: TJvChartEvent read FOnYAxisClick write FOnYAxisClick;
- // When user clicks on Y axis, they can enter a new Y Scale value.
- property OnXAxisClick: TJvChartEvent read FOnXAxisClick write FOnXAxisClick;
- // Also allow user to define some optional action for clicking on the X axis.
- property OnAltYAxisClick: TJvChartEvent read FOnAltYAxisClick write FOnAltYAxisClick;
- // Right margin click (Secondary Y Axis labels)
- property OnTitleClick: TJvChartEvent read FOnTitleClick write FOnTitleClick; // Top margin area (Title area) click.
- end;
-
-
-implementation
-
-uses
- SysUtils, Forms, Dialogs, Printers, Clipbrd,
- Math, // uses Ceil routine, also defines IsNaN on Delphi 6 and up.
- JvJCLUtils, // StrToFloatDef
- JvJVCLUtils, JvResources;
-
-const
- {$IFDEF TJVCHART_ARRAY_OF_ARRAY}
- CHART_SANITY_LIMIT = 60000;
- {$ELSE}
- CHART_SANITY_LIMIT = 12000000;
- {$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
- // Any attempt to have more than CHART_SANITY_LIMIT elements in this
- // graph will be treated as an internal failure on our part. This prevents
- // ugly situations where we thrash because of excessive memory usage.
- // Better to set this than to have the system pig out when we
- // don't want it to. Set this very small when debugging,
- // large when releasing component, and don't remove it unless
- // you're absolutely sure. Increase it whenever necessary.
- // Remember, it's a debugging tool, here on purpose to help keep you
- // out of thrashing-virtual-memory-hell. You probably have a screen
- // to view the chart that is a maximum of 1600x1200, so more than 1600
- // samples will mean the data should be reduced before charting.
-
- MAX_VALUES = 20000;
- // Any attempt to exceed this values count will cause array size and performance problems, thus we limit it.
- MAX_PEN = 100;
- // Any attempt to exceed this pen count will cause array size and performance problems, thus we hardcode the pen limit to 100 pens.
- DEFAULT_PEN_COUNT = 16; // By Default TJvChartData's internal data structures have room for up to 16 pens
- MAX_X_LEGENDS = 50;
- MAX_GRAPH_LEGEND_LEN = 9;
- REALPREC = 7;
- DEFAULT_MARKER_SIZE = 3;
- DEFAULT_VALUE_COUNT = 100;
- // By Default TJvChartData holds 100 values per pen. Grows autofragellisticexpialidociously. :-)
-
- X_TITLE_LABEL_DISTANCE = 4;
- TITLE_MARGIN = 4;
-
-// NEW 2007:
-
- // HELPER FUNCTIONS - NEW 2007
-//-------------------Helper to draw a Gradient. Use it with TJvChartHorizontalBar, for example-------------------------
-
-procedure GradHorizontal(Canvas: TCanvas; Rect: TRect; FromColor, ToColor: TColor); // NEW 2007
-var
- X: Integer;
- dr, dg, DB: Extended;
- C1, C2: TColor;
- r1, r2, g1, g2, b1, b2: Byte;
- R, G, B: Byte;
- Cnt: Integer;
- XDelta: Integer;
-begin
- C1 := FromColor;
- R1 := GetRValue(C1);
- G1 := GetGValue(C1);
- B1 := GetBValue(C1);
-
- C2 := ToColor;
- R2 := GetRValue(C2);
- G2 := GetGValue(C2);
- B2 := GetBValue(C2);
-
- XDelta := Rect.Right - Rect.Left;
- if XDelta <= 0 then
- Exit;
-
- dr := (R2 - R1) / XDelta;
- dg := (G2 - G1) / XDelta;
- DB := (B2 - B1) / XDelta;
-
- Cnt := 0;
- for X := Rect.Left to Rect.Right - 1 do
- begin
- R := R1 + Ceil(dr * Cnt); // uses Math.
- G := G1 + Ceil(dg * Cnt);
- B := B1 + Ceil(DB * Cnt);
-
- Canvas.Pen.Color := RGB(R, G, B);
- Canvas.MoveTo(X, Rect.Top);
- Canvas.LineTo(X, Rect.Bottom);
- Inc(Cnt);
- end;
-end;
-
-procedure GradVertical(Canvas: TCanvas; Rect: TRect; FromColor, ToColor: TColor); // NEW 2007
-var
- Y: Integer;
- dr, dg, DB: Extended;
- C1, C2: TColor;
- r1, r2, g1, g2, b1, b2: Byte;
- R, G, B: Byte;
- Cnt: Integer;
- YDelta: Integer;
-begin
- C1 := FromColor;
- R1 := GetRValue(C1);
- G1 := GetGValue(C1);
- B1 := GetBValue(C1);
-
- C2 := ToColor;
- R2 := GetRValue(C2);
- G2 := GetGValue(C2);
- B2 := GetBValue(C2);
-
- YDelta := Rect.Bottom - Rect.Top;
- if YDelta <= 0 then
- Exit;
- dr := (R2 - R1) / YDelta;
- dg := (G2 - G1) / YDelta;
- DB := (B2 - B1) / YDelta;
-
- Cnt := 0;
- for Y := Rect.Top to Rect.Bottom - 1 do
- begin
- R := R1 + Ceil(dr * Cnt);
- G := G1 + Ceil(dg * Cnt);
- B := B1 + Ceil(DB * Cnt);
-
- Canvas.Pen.Color := RGB(R, G, B);
- Canvas.MoveTo(Rect.Left, Y);
- Canvas.LineTo(Rect.Right, Y);
- Inc(Cnt);
- end;
-end;
-
-//=== { TJvChartGradientBar } ================================================
-
-constructor TJvChartGradientBar.Create(Owner: TJvChart);
-begin
- inherited Create;
- FOwner := Owner;
- FVisible := false;
- FColor := clWhite;
- FGradDirection := grNone;
- FGradColor := FColor;
- FPenStyle := psClear;
- FPenColor := clNone;
-end;
-
-procedure TJvChartGradientBar.SetVisible(AVisible: Boolean);
-begin
- if AVisible <> FVisible then
- begin
- FVisible := AVisible;
- if Assigned(FOwner) and not FOwner.FUpdating then
- FOwner.Invalidate;
- end
-end;
-
-procedure TJvChartGradientBar.SetColor(AColor: TColor);
-begin
- if AColor <> FColor then
- begin
- FColor := AColor;
- if Assigned(FOwner) and not FOwner.FUpdating then
- FOwner.Invalidate;
- end
-end;
-
-procedure TJvChartGradientBar.SetGradientColor(AColor: TColor);
-begin
- if AColor <> FGradColor then
- begin
- FGradColor := AColor;
- if Assigned(FOwner) and not FOwner.FUpdating then
- FOwner.Invalidate;
- end
-end;
-
-procedure TJvChartGradientBar.SetGradientType(AType: TJvChartGradientDirection);
-begin
- if AType <> FGradDirection then
- begin
- FGradDirection := AType;
- if Assigned(FOwner) and not FOwner.FUpdating then
- FOwner.Invalidate;
- end
-end;
-
-//=== { TJvChartHorizontalBar } ==============================================
-
-constructor TJvChartHorizontalBar.Create(Owner: TJvChart);
-begin
- inherited Create(Owner);
- FYTop := 0;
- FYBottom := 0;
-end;
-
-//=== { TJvChartVerticalBar } ================================================
-
-constructor TJvChartVerticalBar.Create(Owner: TJvChart);
-begin
- inherited Create(Owner);
- FXLeft := 0;
- FXRight := 0;
-end;
-
-//=== {TJvChartFloatingMarker} ===============================================
-
-constructor TJvChartFloatingMarker.Create(Owner: TJvChart);
-begin
- inherited Create;
- FOwner := Owner;
- FVisible := False; // NOT visible by default.
- FIndex := -1; // not yet set.
- FLineToMarker := -1; // Don't draw a line to connect to another marker.
- //FYPositionToPen := -1; // Don't copy FYPosition from the pen values.
- FMarkerColor := clRed;
- FMarker := pmkDiamond; // default is diamond marker.
- FLineStyle := psDot;
- FLineColor := clBlue;
- //FCaptionBorderStyle := psClear;
- FXDragMin := -1; // no limit.
- FXDragMax := -1; // no limit.
- FRawXPosition := -1;
- FRawYPosition := -1;
- FLineWidth := 1;
- //FXPosition := 0;
- //FYPosition := 0.0;
-end;
-
-procedure TJvChartFloatingMarker.Assign(Source: TPersistent); // NEW 2007.
-var
- Src: TJvChartFloatingMarker;
-begin
- // don't assign FOwner, FIndex, etc.
- //FRawXPosition {don't copy}
- //FRawYPosition {don't copy}
- if Source is TJvChartFloatingMarker then
- begin
- Src := TJvChartFloatingMarker(Source);
-
- FCaption := Src.Caption;
- FTag := Src.Tag;
-
- //FYPositionToPen := Src.YPositionToPen;
- FMarkerColor := Src.MarkerColor;
- FMarker := Src.Marker;
- FLineStyle := Src.LineStyle;
- FLineColor := Src.LineColor;
- //FCaptionBorderStyle := psClear;
- FXDragMin := Src.XDragMin;
- FXDragMax := Src.XDragMax;
-
- FLineWidth := Src.LineWidth;
- FLineToMarker := Src.LineToMarker;
- FLineVertical := Src.LineVertical;
-
- FCaptionColor := Src.CaptionColor;
- FCaptionPosition := Src.CaptionPosition;
- FCaptionBoxed := Src.CaptionBoxed;
-
- {don't use internal property set for these:}
- XPosition := Src.XPosition;
- YPosition := Src.YPosition;
- Visible := Src.Visible;
- end;
-end;
-
-procedure TJvChartFloatingMarker.SetCaption(ACaption: string);
-begin
- if ACaption <> FCaption then
- begin
- FCaption := ACaption;
- if Assigned(FOwner) and FVisible then
- if not FOwner.FUpdating then
- FOwner.Invalidate;
- end;
-end;
-
-procedure TJvChartFloatingMarker.SetCaptionColor(const Value: TColor);
-begin
- FCaptionColor := Value;
-end;
-
-procedure TJvChartFloatingMarker.SetXPosition(XPos: Integer); // should invalidate the chart (FOwner) if changed.
-begin
- if XPos <> FXPosition then
- begin
- FXPosition := XPos;
- if Assigned(FOwner) and FVisible then
- if not FOwner.FUpdating then
- FOwner.Invalidate;
- end
-end;
-
-procedure TJvChartFloatingMarker.SetYPosition(YPos: Double); // should invalidate the chart (FOwner) if changed.
-begin
- if YPos <> FYPosition then
- begin
- FYPosition := YPos;
- if Assigned(FOwner) and FVisible then
- if not FOwner.FUpdating then
- FOwner.Invalidate;
- end
-end;
-
-procedure TJvChartFloatingMarker.SetVisible(AVisible: Boolean);
-begin
- if AVisible <> FVisible then
- begin
- FVisible := AVisible;
- if Assigned(FOwner) then
- if not FOwner.FUpdating then
- FOwner.Invalidate;
- end
-end;
-
-//=== { TJvChartData } =======================================================
-
-constructor TJvChartData.Create;
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-var
- I: Integer;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-begin
- inherited Create;
- FPenCount := DEFAULT_PEN_COUNT; // Can never set less than one inside TJvChartData!
- {$IFDEF TJVCHART_ARRAY_OF_ARRAY}
- // FPenCount must be valid here:
- for I := 0 to DEFAULT_PEN_COUNT do
- Grow(I, DEFAULT_VALUE_COUNT);
- {$ELSE}
- Grow(DEFAULT_PEN_COUNT, DEFAULT_VALUE_COUNT);
- {$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-end;
-
-destructor TJvChartData.Destroy;
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-var
- I: Integer;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-begin
- {$IFDEF TJVCHART_ARRAY_OF_ARRAY}
- for I := 0 to FDataAlloc - 1 do
- Finalize(FData[I]);
- {$ENDIF TJVCHART_ARRAY_OF_ARRAY}
- Finalize(FData); // Free array.
- inherited Destroy;
-end;
-
-function TJvChartData.GetValue(Pen, ValueIndex: Integer): Double;
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-begin
- Assert(ValueIndex >= 0);
- Grow(Pen, ValueIndex);
- Result := FData[ValueIndex, Pen]; // This will raise EInvalidOP for NaN values.
-end;
-{$ELSE}
-var
- Idx: Integer;
-begin
- // Grow base array
- if (Pen < 0) or (Pen >= FPenCount) then
- Result := NaN
- else
- begin
- Assert(FPenCount > 0);
- Idx := (ValueIndex * FPenCount) + Pen;
-
- if (Idx < 0) or (Idx > CHART_SANITY_LIMIT) then // Sanity check!
- raise ERangeError.CreateRes(@RsEDataIndexTooLargeProbablyAnInternal);
-
- if Idx >= Length(FData) then
- Grow(Pen, ValueIndex);
- Result := FData[Idx];
- end;
-end;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
-procedure TJvChartData.SetValue(Pen, ValueIndex: Integer; NewValue: Double);
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-begin
- // Grow base array
- Grow(Pen, ValueIndex);
- FData[ValueIndex, Pen] := NewValue;
- if ValueIndex >= FValueCount then
- begin
- Grow(Pen, ValueIndex + 1);
- FData[ValueIndex + 1, Pen] := NewValue; // Workaround for a graphical bug. Sorry.
- FValueCount := ValueIndex + 1;
- end;
-end;
-{$ELSE}
-var
- Idx: Integer;
-begin
- Assert(FPenCount > 0);
-
- // Grow base array
- if (Pen < 0) or (Pen >= FPenCount) then
- raise ERangeError.CreateRes(@RsEPenIndexInvalid);
-
- Idx := (ValueIndex * FPenCount) + Pen;
-
- if (Idx < 0) or (Idx > CHART_SANITY_LIMIT) then // Sanity check!
- raise ERangeError.CreateRes(@RsEDataIndexTooLargeProbablyAnInternal);
-
- if Idx >= Length(FData) then
- Grow(Pen, ValueIndex);
- FData[Idx] := NewValue;
-
- if ValueIndex >= FValueCount then
- FValueCount := ValueIndex + 1;
-end;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
-function TJvChartData.GetTimestamp(ValueIndex: Integer): TDateTime;
-begin
- if (ValueIndex < 0) or (ValueIndex >= Length(FTimeStamp)) then
- Result := 0.0 // null datetime
- else
- Result := FTimeStamp[ValueIndex];
-end;
-
-procedure TJvChartData.SetEndDateTime(const Value: TDateTime);
-begin
- FEndDateTime := Value;
-end;
-
-procedure TJvChartData.SetStartDateTime(const Value: TDateTime);
-begin
- FStartDateTime := Value;
-end;
-
-procedure TJvChartData.SetTimestamp(ValueIndex: Integer; AValue: TDateTime);
-begin
- if ValueIndex < 0 then
- Exit;
- if ValueIndex >= Length(FTimeStamp) then
- SetLength(FTimeStamp, ValueIndex + 1);
- FTimeStamp[ValueIndex] := AValue;
-end;
-
-procedure TJvChartData.Scroll;
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-var
- I, J: Integer;
-begin
- if FValueCount < 2 then
- begin
- Clear;
- Exit;
- end;
- { ULTRA SLOW BUT NON-CRASHING Version }
- for I := 0 to FValueCount - 1 do
- begin
- for J := 0 to Length(FData[I]) - 1 do
- FData[I, J] := FData[I + 1, J];
- SetTimestamp(I, GetTimestamp(I + 1));
- end;
- FTimeStamp[FValueCount - 1] := 0;
- // Check we didn't Break the heap:
-end;
-{$ELSE}
-var
- T: Integer;
- Idx: Integer;
-begin
- if FValueCount > FPenCount then
- begin
- Assert(FPenCount > 0);
- Idx := FValueCount * FPenCount;
-
- // Yeah, I wish:
- //System.Move( {Source} FData[FPenCount], {Dest} FData[0], Idx-FPenCount);
- for T := 0 to Idx - FPenCount do
- FData[T] := FData[T + FPenCount];
-
- for T := Idx - FPenCount to Idx - 1 do
- begin
- if T > Length(FData) then
- Break;
- FData[T] := FClearToValue;
- end;
- //Dec(FValueCount,FPenCount);
- end
- else
- begin
- FPenCount := 0;
- Clear;
- end;
-end;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
-procedure TJvChartData.PreGrow(Pen, ValueIndex: Integer);
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-var
- T: Integer;
-begin
- if Length(FData) < ValueIndex then
- SetLength(FData, ValueIndex);
- for T := 0 to ValueIndex - 1 do
- SetLength(FData[T], Pen);
- FDataAlloc := ValueIndex;
-end;
-{$ELSE}
-begin
- if Pen > FPenCount then
- FPenCount := Pen;
- Grow(Pen, ValueIndex);
- FDataAlloc := ValueIndex;
-end;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-procedure TJvChartData.Grow(Pen, ValueIndex: Integer);
-var
- I, J, OldLength: Integer;
-begin
- if (Pen < 0) or (ValueIndex < 0) then
- raise ERangeError.CreateRes(@RsEDataIndexCannotBeNegative);
- if (Pen > CHART_SANITY_LIMIT) or (ValueIndex > CHART_SANITY_LIMIT) then
- raise ERangeError.CreateRes(@RsEDataIndexTooLargeProbablyAnInternal);
-
- if ValueIndex >= FDataAlloc then
- begin
- //--------------------------------------------------------
- // Performance tweak: Uses more memory but makes JvChart
- // much faster!
- // We Double our allocation unit size
- // until we start to get Really Huge, then grow in chunks!
- //--------------------------------------------------------
- if ValueIndex < 640000 then
- FDataAlloc := ValueIndex * 2 // Double in size
- else
- FDataAlloc := ValueIndex + 64000;
-
- OldLength := Length(FData);
- SetLength(FData, FDataAlloc);
-
- // new: If we set FClearToValue to NaN, special handling in growing arrays:
- if IsNaN(FClearToValue) then
- for I := OldLength to FDataAlloc - 1 do
- for J := 0 to Length(FData[I]) - 1 do
- FData[I][J] := FClearToValue; // XXX Debug me!
-
- end;
- if Pen >= Length(FData[ValueIndex]) then
- begin
- OldLength := Length(FData[ValueIndex]);
- SetLength(FData[ValueIndex], Pen + 1);
- if IsNaN(FClearToValue) then
- begin
- for I := OldLength to FDataAlloc - 1 do
- begin
- Assert(Length(FData) > ValueIndex);
- if (Length(FData[ValueIndex]) < FDataAlloc) then
- SetLength(FData[ValueIndex], FDataAlloc); // Safety code!
- FData[ValueIndex][I] := FClearToValue; // XXX Debug me!
- end;
- end;
- end;
-end;
-{$ELSE}
-procedure TJvChartData.Grow(Pen, ValueIndex: Integer);
-var
- N, Idx: Integer;
- OldLen: Integer;
-begin
- Assert(Assigned(Self));
- Assert(FPenCount > 0);
- Idx := (ValueIndex + 1) * FPenCount;
- OldLen := Length(FData);
- if Idx >= OldLen then
- begin
- Idx := Idx + 1024; // Add 1024 floats (8k) headroom.
- SetLength(FData, Idx + 1);
- for N := OldLen to Idx do
- FData[N] := FClearToValue;
- end;
- FDataAlloc := Length(FData);
-end;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
-function TJvChartData.DebugStr(ValueIndex: Integer): string; // dump all pens for particular valueindex, as string.
-var
- S: string;
- I: Integer;
- LValue: Double;
-begin
- if (ValueIndex < 0) or (ValueIndex >= FDataAlloc) then
- Exit;
-
- if Timestamp[ValueIndex] > 0.0 then
- S := FormatDateTime('hh:nn:ss ', Timestamp[ValueIndex]);
- for I := 0 to FPenCount - 1 do
- begin
- LValue := GetValue(I, ValueIndex);
- if IsNaN(LValue) then
- S := S + '-'
- else
- S := S + Format('%5.2f', [LValue]);
-
- if I < FPenCount - 1 then
- S := S + ', '
- end;
- Result := S;
-end;
-
-procedure TJvChartData.Clear; // Resets FValuesCount/FPenCount to zero. Zeroes everything too, just for good luck.
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-var
- I, J: Integer;
-begin
- for I := 0 to FDataAlloc - 1 do
- for J := 0 to Length(FData[I]) - 1 do
- FData[I, J] := FClearToValue;
- FValueCount := 0;
-end;
-{$ELSE}
-var
- I: Integer;
-begin
- for I := 0 to Length(FData) - 1 do
- FData[I] := FClearToValue;
-end;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
-procedure TJvChartData.ClearPenValues; // Clears all pen values to NaN but does not reset pen definitions etc.
-{$IFDEF TJVCHART_ARRAY_OF_ARRAY}
-var
- I, J: Integer;
-begin
- for I := 0 to FDataAlloc - 1 do
- for J := 0 to Length(FData[I]) - 1 do
- FData[I, J] := ClearToValue; // 0.0;
-end;
-{$ELSE}
-begin
- Clear;
-end;
-{$ENDIF TJVCHART_ARRAY_OF_ARRAY}
-
-//=== { TJvChartYAxisOptions } ===============================================
-
-constructor TJvChartYAxisOptions.Create(Owner: TJvChartOptions);
-begin
- inherited Create;
- FOwner := Owner;
-
- FMarkerValueDecimals := -1; // -1 = default (automatic decimals)
-
- FYLegends := TStringList.Create;
- FMaxYDivisions := 20;
- FMinYDivisions := 5;
- FYDivisions := 10;
- FDefaultYLegends := JvDefaultYLegends;
-end;
-
-destructor TJvChartYAxisOptions.Destroy;
-begin
- FYLegends.Free;
- inherited Destroy;
-end;
-
-procedure TJvChartYAxisOptions.Clear;
-begin
- YDivisions := DefaultYLegends;
- YLegends.Clear;
- Normalize;
-end;
-
-
-procedure TJvChartYAxisOptions.Assign(Source:TPersistent);// Warren added sept 2009
-var
- src:TJvChartYAxisOptions;
-begin
- //inherited Assign(Source); //raises exception!
- if Source is TJvChartYAxisOptions then begin
- src := TJvChartYAxisOptions(Source);
- FYLegends.Assign(src.YLegends);
-
- FMarkerValueDecimals := src.MarkerValueDecimals;
- FYDivisions := src.YDivisions;
- FMaxYDivisions := src.MaxYDivisions;
- FMinYDivisions := src.MinYDivisions;
- FYLegendDecimalPlaces:= src.YLegendDecimalPlaces;
- FDefaultYLegends := src.DefaultYLegends;
-
- //FYGap : not copied!
- //FYGap1 : not copied!
- //FYPixelGap: not copied!
- YMin := src.YMin; // always first!
- YMax := src.YMax; // property set method calls Normalize!
- // Always set YMax last!
-
- end;
-end;
-
-procedure TJvChartYAxisOptions.Normalize;
-var
- // CheckYDivisions: Integer;
- VC: Integer;
-begin
- if FYMax - FYMin < 0.00001 then // make sure that there is some difference here!
- FYMax := FYMin + 10;
-
- if (DefaultYLegends > 0) and (YDivisions = 0) then
- YDivisions := DefaultYLegends;
-
- // DON'T KNOW WHY WE NEEDED THIS. REMOVED IT.
- (*
-if (YGap>0.0) then
-begin
- CheckYDivisions := Round((YMax + (YGap - 1)) / YGap);
- if CheckYDivisions<>YDivisions then
- YDivisions :=CheckYDivisions;
-end;*)
-
- VC := YDivisions;
- if VC < 1 then
- VC := 1;
- FYGap := (YMax - YMin) / VC;
- FYGap1 := ((YMax - YMin) + 1) / VC;
-
- YPixelGap := (FOwner.YEnd - 1) / VC; // Vertical Pixels Per Value Division counter.
-
- (*CheckYDivisions := Round(((YMax-YMin) + (YGap - 1)) / YGap);
- if CheckYDivisions <> YDivisions then
- YDivisions := CheckYDivisions; *)
-
- //---------------------------------------------------------------------
- // Here's the normalization section:
- // !!!The 10 and 20 here should be properties settable by the user!!!
- //---------------------------------------------------------------------
- if YDivisions < MinYDivisions then
- begin
- YDivisions := MinYDivisions;
- FYGap := (YMax - YMin) / YDivisions;
- end
- else
- if YDivisions > MaxYDivisions then
- begin
- YDivisions := MaxYDivisions;
- FYGap := (YMax - YMin) / YDivisions;
- end;
-end;
-
-procedure TJvChartYAxisOptions.SetYMin(NewYMin: Double);
-begin
- if IsNaN(NewYMin) then
- Exit;
-
- try
- if NewYMin = FYMin then
- Exit;
- except
- {$IFDEF DEBUGINFO_ON}
- OutputDebugString('TJvChartYAxisOptions.SetYMin-WTF?');
- {$ENDIF DEBUGINFO_ON}
- Exit;
- end;
-
- FYMin := NewYMin;
-
- if not Assigned(FOwner) then
- Exit;
- if not Assigned(FOwner.FOwner) then
- Exit;
- if csLoading in FOwner.FOwner.ComponentState then
- Exit;
-
- // Rework other values around new YMin:
- Normalize;
- FOwner.NotifyOptionsChange;
- {NEW: Auto-Regenerate Y Axis Labels}
- if Assigned(FYLegends) then
- if FYLegends.Count > 0 then
- begin
- FYLegends.Clear;
- FOwner.FOwner.PrimaryYAxisLabels;
- end;
-end;
-
-procedure TJvChartYAxisOptions.SetYMax(NewYMax: Double);
-begin
- if IsNaN(NewYMax) then
- Exit;
-
- if NewYMax = FYMax then
- Exit;
-
- FYMax := NewYMax;
-
- if not Assigned(FOwner) then
- Exit;
- if not Assigned(FOwner.FOwner) then
- Exit;
- if csLoading in FOwner.FOwner.ComponentState then
- Exit;
-
- // Rework other values around new YMax:
- Normalize;
- FOwner.NotifyOptionsChange;
-
- {NEW: Auto-Regenerate Y Axis Labels}
- if Assigned(FYLegends) then
- if FYLegends.Count > 0 then
- begin
- FYLegends.Clear;
- FOwner.FOwner.PrimaryYAxisLabels;
- end;
-end;
-
-(*procedure TJvChartYAxisOptions.SetYGap(newYgap: Double);
-begin
- if (FYGap < 5.0) and (YMax>100) then
- begin
- OutputDebugString('Bug');
- end;
-
- FYGap := newYGap;
- // TODO: Fire event, and cause a refresh, recalculate other
- // dependant fields that are calculated from the YGap.
- FOwner.NotifyOptionsChange; // Fire event before we auto-format graph. Allows some customization to occur here.
-end;
- *)
-
-function TJvChartYAxisOptions.GetYLegends: TStrings;
-begin
- Result := TStrings(FYLegends);
-end;
-
-procedure TJvChartYAxisOptions.SetYLegends(Value: TStrings);
-begin
- FYLegends.Assign(Value);
- if Assigned(FOwner) then
- FOwner.NotifyOptionsChange; // Fire event before we auto-format graph. Allows some customization to occur here.
-end;
-
-procedure TJvChartYAxisOptions.SetYDivisions(AValue: Integer);
-begin
- FYDivisions := AValue;
-
- if not Assigned(FOwner) then
- Exit;
- if not Assigned(FOwner.FOwner) then
- Exit;
- if csLoading in FOwner.FOwner.ComponentState then
- Exit;
-
- // Rework other values around new YMax:
- Normalize;
- FOwner.NotifyOptionsChange;
-end;
-
-procedure TJvchartYAxisOptions.SetYPixelGap(AValue: Double);
-begin
- if FYPixelGap = AValue then exit;
- FYPixelGap := AValue;
- FOwner.NotifyOptionsChange;
-end;
-
-
-//=== { TJvChartOptions } ====================================================
-
-constructor TJvChartOptions.Create(Owner: TJvChart);
-begin
- inherited Create;
- FOwner := Owner;
-
- FAutoUpdateGraph := True;
-
- FPrimaryYAxis := TJvChartYAxisOptions.Create(Self);
- FSecondaryYAxis := TJvChartYAxisOptions.Create(Self);
-
- FXAxisDivisionMarkers := True; //default property.
- FYAxisDivisionMarkers := True; //default property.
-
- SetLength(FPenColors, 12);
- FPenColors[0] := clLime;
- FPenColors[1] := clRed;
- FPenColors[2] := clBlue;
- FPenColors[3] := clYellow;
- FPenColors[4] := clMaroon;
- FPenColors[5] := clGreen;
- FPenColors[6] := clOlive;
- FPenColors[7] := clNavy;
- FPenColors[8] := clPurple;
- FPenColors[9] := clTeal;
- FPenColors[10] := clFuchsia;
- FPenColors[11] := clAqua;
-
- FChartKind := ckChartLine;
-
- FPenCount := 1;
-
- FLegend := clChartLegendNone; //default Legend is None.
-
- // Create TStringList property objects
- FXLegends := TStringList.Create;
- FPenLegends := TStringList.Create;
- FPenUnit := TStringList.Create;
- // dynamic array setup
- SetLength(FAverageValue, DEFAULT_VALUE_COUNT);
-
- // Defaults for Graph Options:
-
- FMarkerSize := JvChartDefaultMarkerSize;
- FXStartOffset := 45; {DEFAULT}
- FYStartOffset := 10;
- FTitle := '';
- // FXAxisHeader := 'X';
- // FYAxisHeader := 'Y';
-
- FPaperColor := clWhite;
- FAxisLineColor := clBlack;
- FAverageLineColor := JvDefaultAvgLineColor;
- FDivisionLineColor := JvDefaultDivisionLineColor; // NEW!
- FShadowColor := JvDefaultShadowColor; //NEW!
- FPaperColor := JvDefaultPaperColor;
- FHintColor := JvDefaultHintColor;
-
- FHeaderFont := TFont.Create;
- FLegendFont := TFont.Create;
- FAxisFont := TFont.Create;
- FAxisTitleFont := TFont.Create;
-
- //FShowLegend := True;
- FMouseEdit := True;
- FMouseInfo := True;
- FLegendWidth := 150;
- FPenLineWidth := 1;
- FAxisLineWidth := 2;
-
- FXValueCount := 10;
-
- FXAxisLegendSkipBy := 1;
- FXLegendHoriz := 0;
-
-end;
-
-destructor TJvChartOptions.Destroy;
-begin
- FreeAndNil(FPrimaryYAxis); //memory leak fix SEPT 21, 2004.WAP.
- FreeAndNil(FSecondaryYAxis); //memory leak fix SEPT 21, 2004. WAP.
-
- FreeAndNil(FXLegends);
- FreeAndNil(FPenLegends);
- FreeAndNil(FPenUnit);
-
- FreeAndNil(FHeaderFont);
- FreeAndNil(FLegendFont);
- FreeAndNil(FAxisFont);
- FreeAndNil(FAxisTitleFont);
-
- inherited Destroy;
-end;
-
-
-procedure TJvChartOptions.Assign(Source: TPersistent); // Warren added sept 2009
-var
- src:TJvChartOptions;
- t:Integer;
-begin
-// inherited Assign(Source); {raises exception!}
- if (Source is TJvChartOptions) then begin
- src := Source as TJvChartOptions;
-
- FLegend := src.Legend;
- FHeaderFont.Assign(src.HeaderFont);
- FLegendFont.Assign(src.LegendFont);
- FAxisFont.Assign(src.AxisFont);
- FAxisTitleFont.Assign(src.AxisTitleFont);
- FPenLegends.Assign(src.PenLegends);
- FPenUnit.Assign(src.PenUnit);
- FXLegends.Assign(src.XLegends);
-
- FChartKind := src.ChartKind;
- FTitle := src.Title;
- FNoDataMessage := src.NoDataMessage;
- FYAxisHeader := src.YAxisHeader;
- FYAxisDivisionMarkers := src.YAxisDivisionMarkers;
- FXAxisDivisionMarkers := src.XAxisDivisionMarkers;
- FXAxisHeader := src.XAxisHeader;
-
- FXLegendMaxTextWidth := src.XLegendMaxTextWidth;
- FXAxisValuesPerDivision:= src.XAxisValuesPerDivision;
- FXAxisLegendSkipBy := src.XAxisLegendSkipBy;
- FXLegendHoriz := src.FXLegendHoriz;
- FXAxisLabelAlignment := src.XAxisLabelAlignment;
- FXAxisDateTimeMode := src.XAxisDateTimeMode;
- FXAxisDateTimeFormat := src.XAxisDateTimeFormat;
- FXAxisDateTimeDivision := src.XAxisDateTimeDivision;
- FDateTimeFormat := src.DateTimeFormat;
- FXValueCount := src.XValueCount;
- FPenCount := src.PenCount;
-
- // Array copies
- SetLength(FPenColors, Length(src.FPenColors));
- for t := 0 to Length(FPenColors)-1 do
- FPenColors[t] := src.FPenColors[t];
-
- SetLength(FPenStyles, Length(src.FPenStyles));
- for t := 0 to Length(FPenStyles)-1 do
- FPenStyles[t] := src.FPenStyles[t];
-
- SetLength(FPenMarkerKind, Length(src.FPenMarkerKind));
- for t := 0 to Length(FPenMarkerKind)-1 do
- FPenMarkerKind[t] := src.FPenMarkerKind[t];
-
- SetLength(FPenSecondaryAxisFlag, Length(src.FPenSecondaryAxisFlag));
- for t := 0 to Length(FPenSecondaryAxisFlag)-1 do
- FPenSecondaryAxisFlag[t] := src.FPenSecondaryAxisFlag[t];
-
- SetLength(FPenValueLabels, Length(src.FPenValueLabels));
- for t := 0 to Length(FPenValueLabels)-1 do
- FPenValueLabels[t] := src.FPenValueLabels[t];
-
- //SetLength(FAverageValue,Length(src.FAverageValue));
- // no copy of averages!
-
- FXOrigin := src.XOrigin;
- FYOrigin := src.YOrigin;
- FXStartOffset := src.XStartOffset;
- FYStartOffset := src.YStartOffset;
- FXEnd := src.XEnd;
- FYEnd := src.YEnd;
- FMarkerSize := src.MarkerSize;
- { more design time }
- FLegendWidth := src.LegendWidth;
- FLegendRowCount := src.LegendRowCount;
- FAutoUpdateGraph := src.AutoUpdateGraph;
- FMouseEdit := src.MouseEdit;
- FMouseDragObjects := src.MouseDragObjects;
- FMouseInfo := src.MouseInfo;
-
- FPenLineWidth := src.PenLineWidth;
- FAxisLineWidth := src.AxisLineWidth;
-
- //COLORS:
- FPaperColor := src.PaperColor;
- FDivisionLineColor := src.DivisionLineColor;
- FShadowColor := src.ShadowColor;
- FAxisLineColor := src.AxisLineColor;
- FHintColor := src.HintColor;
- FAverageLineColor := src.AverageLineColor;
- FCursorColor := src.CursorColor;
-
- FCursorStyle := src.CursorStyle;
- FGradientColor := src.GradientColor;
- FGradientDirection := src.GradientDirection;
-
- // more internal dynamically calculated stuff:
- //FXAxisDateTimeFirstMarker not copied
- //FXAxisDateTimeSkipBy not copied
- //FXAxisDateTimeLines not copied
- //FXGap,FYGap: not copied.
-
-
-
- // Second last:
- FSecondaryYAxis.Assign(src.SecondaryYAxis);
-
- // Last!
- FPrimaryYAxis.Assign(src.PrimaryYAxis);
-
- // re-plot chart:
- NotifyOptionsChange;
- end;
-
-end;
-procedure TJvChartOptions.NotifyOptionsChange;
-begin
- if Assigned(FOwner) then
- FOwner.NotifyOptionsChange;
-end;
-
-// Each pen can be associated with either the primary or secondary axis,
-// this function decides which axis to return depending on the pen configuration:
-
-function TJvChartOptions.GetPenAxis(Index: Integer): TJvChartYAxisOptions;
-begin
- if (Index < 0) or (Index >= Length(FPenSecondaryAxisFlag)) then
- Result := FPrimaryYAxis // default
- else
- if FPenSecondaryAxisFlag[Index] then
- Result := FSecondaryYAxis // alternate!
- else
- Result := FPrimaryYAxis; // default
-end;
-
-function TJvChartOptions.GetPenMarkerKind(Index: Integer): TJvChartPenMarkerKind;
-begin
- if (Index >= 0) and (Index < Length(FPenMarkerKind)) then
- Result := FPenMarkerKind[Index]
- else
- Result := pmkNone;
-end;
-
-function TJvChartOptions.GetPenColor(Index: Integer): TColor;
-begin
- // Don't check for out of range values, since we use that on purpose in this
- // function. Okay, ugly, but it works. -WP.
- case Index of
- jvChartAverageLineColorIndex:
- Result := FAverageLineColor;
- jvChartDivisionLineColorIndex: // horizontal and vertical division line color
- Result := FDivisionLineColor;
- jvChartShadowColorIndex: // legend shadow (light gray)
- Result := FShadowColor;
- jvChartAxisColorIndex:
- Result := FAxisLineColor; // get property.
- jvChartHintColorIndex:
- Result := FHintColor; // Get property.
- jvChartPaperColorIndex:
- Result := FPaperColor; // Get property.
- else
- if Index < jvChartAverageLineColorIndex then
- Result := clBtnFace
- else
- if Index >= 0 then
- Result := FPenColors[Index]
- else
- Result := clNone; // I hope clNone is a good unknown value (ahuser). {{Good enough. -WP.}}
- end;
-end;
-
-function TJvChartOptions.GetPenStyle(Index: Integer): TPenStyle;
-begin
- if (Index >= 0) and (Index < Length(FPenStyles)) then
- Result := FPenStyles[Index]
- else
- Result := psSolid;
-end;
-
-function TJvChartOptions.GetAverageValue(Index: Integer): Double;
-begin
- if Index < 0 then
- raise ERangeError.CreateRes(@RsEGetAverageValueIndexNegative);
- if Index >= Length(FAverageValue) then
- Result := 0.0
- else
- Result := FAverageValue[Index];
-end;
-
-procedure TJvChartOptions.SetAverageValue(Index: Integer; AValue: Double);
-begin
- if Index < 0 then
- raise ERangeError.CreateRes(@RsESetAverageValueIndexNegative);
- if Index >= Length(FAverageValue) then
- SetLength(FAverageValue, Index + 1);
- FAverageValue[Index] := AValue;
-end;
-
-function TJvChartOptions.GetPenSecondaryAxisFlag(Index: Integer): Boolean;
-begin
- if (Index < 0) or (Index >= Length(FPenSecondaryAxisFlag)) then
- Result := False
- else
- Result := FPenSecondaryAxisFlag[Index];
-end;
-
-procedure TJvChartOptions.SetPenSecondaryAxisFlag(Index: Integer; NewValue: Boolean);
-begin
- if (Index < 0) or (Index >= MAX_PEN) then
- raise ERangeError.CreateRes(@RsEChartOptionsPenCountPenCountOutOf);
- if Index >= Length(FPenSecondaryAxisFlag) then
- SetLength(FPenSecondaryAxisFlag, Index + 1);
- FPenSecondaryAxisFlag[Index] := NewValue;
- NotifyOptionsChange;
-end;
-
-function TJvChartOptions.GetPenValueLabels(Index: Integer): Boolean;
-begin
- if (Index < 0) or (Index >= Length(FPenValueLabels)) then
- Result := False
- else
- Result := FPenValueLabels[Index];
-end;
-
-procedure TJvChartOptions.SetPenValueLabels(Index: Integer; NewValue: Boolean);
-begin
- if (Index < 0) or (Index >= MAX_PEN) then
- raise ERangeError.CreateRes(@RsEChartOptionsPenCountPenCountOutOf);
-
- if Index >= Length(FPenValueLabels) then
- SetLength(FPenValueLabels, Index + 1);
- FPenValueLabels[Index] := NewValue;
-end;
-
-procedure TJvChartOptions.SetPenCount(Count: Integer);
-begin
- if (Count < 0) or (Count >= MAX_PEN) then
- raise ERangeError.CreateRes(@RsEChartOptionsPenCountPenCountOutOf);
- FPenCount := Count;
- SetLength(FPenSecondaryAxisFlag, FPenCount + 1);
- // notify data object:
- NotifyOptionsChange;
-end;
-
-function TJvChartOptions.GetPenLegends: TStrings;
-begin
- Result := TStrings(FPenLegends);
-end;
-
-function TJvChartOptions.GetPenUnit: TStrings;
-begin
- Result := TStrings(FPenUnit);
-end;
-
-procedure TJvChartOptions.SetPenUnit(Value: TStrings);
-begin
- FPenUnit.Assign(Value);
-end;
-
-function TJvChartOptions.GetXLegends: TStrings;
-begin
- Result := TStrings(FXLegends);
-end;
-
-procedure TJvChartOptions.SetAxisLineWidth(const Value: Integer);
-begin
- if FAxisLineWidth <> Value then
- begin
- FAxisLineWidth := Value;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetAxisTitleFont(const Value: TFont);
-begin
- FAxisTitleFont.Assign(Value);
- NotifyOptionsChange;
-end;
-
-procedure TJvChartOptions.SetChartKind(AKind: TJvChartKind);
-begin
- if AKind <> FChartKind then
- begin
- FChartKind := AKind;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetDivisionLinecolor(const AColor: TColor);
-begin
- if FDivisionLineColor <> AColor then
- begin
- FDivisionLineColor := AColor;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetFillUnderLine(const AValue: Boolean);
-begin
- if FFillUnderLine <> AValue then
- begin
- FFillUnderLine := AValue;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetLegend(const ALegend: TJvChartLegend);
-begin
- if FLegend <> ALegend then
- begin
- FLegend := ALegend;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetMarkerSize(const Value: Integer);
-begin
- if FMarkerSize <> Value then
- begin
- FMarkerSize := Value;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetPaperColor(const AColor: TColor);
-begin
- if AColor <> FPaperColor then
- begin
- FPaperColor := AColor;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetPenColor(Index: Integer; AColor: TColor);
-begin
- if (Index < 0) or (Index >= MAX_PEN) then
- raise ERangeError.CreateRes(@RsEChartOptionsPenCountPenCountOutOf);
-
- if Index >= Length(FPenColors) then
- SetLength(FPenColors, Index + 1);
-
- FPenColors[Index] := AColor;
- NotifyOptionsChange;
-end;
-
-procedure TJvChartOptions.SetPenLegends(Value: TStrings);
-begin
- FPenLegends.Assign(Value);
- NotifyOptionsChange;
-end;
-
-procedure TJvChartOptions.SetPenLineWidth(const Value: Integer);
-begin
- if FPenLineWidth <> Value then
- begin
- FPenLineWidth := Value;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetPenMarkerKind(Index: Integer; AMarkKind: TJvChartPenMarkerKind);
-begin
- if Index >= 0 then
- begin
- if Index >= Length(FPenMarkerKind) then
- SetLength(FPenMarkerKind, Index + 1);
- FPenMarkerKind[Index] := AMarkKind;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetPenStyle(Index: Integer; APenStyle: TPenStyle);
-begin
- if (Index < 0) or (Index >= MAX_PEN) then
- raise ERangeError.CreateRes(@RsEChartOptionsPenCountPenCountOutOf);
-
- if Index >= Length(FPenStyles) then
- SetLength(FPenStyles, Index + 1);
- FPenStyles[Index] := APenStyle;
- NotifyOptionsChange;
-end;
-
-procedure TJvChartOptions.SetShadowColor(const AColor: TColor);
-begin
- if FShadowColor <> AColor then
- begin
- FShadowColor := AColor;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvchartOptions.SetTitle(const Value: String);
-begin
- if FTitle <> Value then
- begin
- FTitle := Value;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetXAxisDateTimeDivision(const Value: Double);
-begin
- FXAxisDateTimeDivision := Value;
-end;
-
-procedure TJvChartOptions.SetXAxisHeader(const Value: String);
-begin
- if FXAxisHeader <> Value then
- begin
- FXAxisHeader := Value;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetXLegends(Value: TStrings);
-begin
- FXLegends.Assign(Value);
-end;
-
-procedure TJvChartOptions.SetYAxisHeader(const Value: String);
-begin
- if FYAxisHeader <> Value then
- begin
- FYAxisHeader := Value;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetHeaderFont(AFont: TFont);
-begin
- FHeaderFont.Assign(AFont);
-end;
-
-procedure TJvChartOptions.SetLegendFont(AFont: TFont);
-begin
- FLegendFont.Assign(AFont);
-end;
-
-procedure TJvChartOptions.SetAxisFont(AFont: TFont);
-begin
- FAxisFont.Assign(AFont);
-end;
-
-procedure TJvChartOptions.SetPrimaryYAxis(AssignFrom: TJvChartYAxisOptions);
-begin
- FPrimaryYAxis.Assign(AssignFrom);
-end;
-
-procedure TJvChartOptions.SetSecondaryYAxis(AssignFrom: TJvChartYAxisOptions);
-begin
- FSecondaryYAxis.Assign(AssignFrom);
-end;
-
-procedure TJvChartOptions.SetXStartOffset(Offset: Integer);
-begin
- if FXStartOffset <> Offset then
- begin
- FXStartOffset := Offset;
- NotifyOptionsChange;
- end;
-end;
-
-procedure TJvChartOptions.SetYStartOffset(Offset: Integer);
-begin
- if FYStartOffset <> Offset then
- begin
- FYStartOffset := Offset;
- if Assigned(FOwner) then FOwner.CalcYEnd;
- NotifyOptionsChange;
- end;
-end;
-
-
-//=== { TJvChart } ===========================================================
-
-{ GRAPH }
-{**************************************************************************}
-{ call this function : NEVER! }
-{**************************************************************************}
-
-constructor TJvChart.Create(AOwner: TComponent);
-begin
- inherited Create(AOwner); {by TImage...}
-
- ControlStyle := ControlStyle + [csOpaque];
- // XXX FLICKER REDUCTION: Set ControlStyle properly. -WP. APRIL 2004.
-
- FPicture := TPicture.Create;
-
- FCursorPosition := -1; // Invisible until CursorPosition is set >=0 to make it visible.
-
- FMouseDownHintStrs := TStringList.Create;
-
- { logical font used for rotating text to show vertical labels }
-
- FData := TJvChartData.Create;
- FAverageData := TJvChartData.Create;
-
- FFloatingMarker := TObjectList.Create; // NEW: collection of TJvChartFloatingMarker objects.
- FFloatingMarker.OwnsObjects := True;
-
- FHorizontalBars := TObjectList.Create; // NEW: collection of TJvChartFloatingMarker objects.
- FHorizontalBars.OwnsObjects := True;
-
- FVerticalBars := TObjectList.Create; // NEW: collection of TJvChartFloatingMarker objects.
- FVerticalBars.OwnsObjects := True;
-
- FOptions := TJvChartOptions.Create(Self);
- CalcYEnd;
-
- PrintInSession := False;
-
- FOldYGap := 1;
- FOldYOrigin := 0;
- FStartDrag := False;
- FMouseLegend := False;
- FContainsNegative := False;
- FMouseValue := 0;
- FMousePen := 0;
-
- {Set default values for component fields...}
-
- if csDesigning in ComponentState then
- begin
- // default height and width
- if not Assigned(Parent) then
- begin
- Width := 300;
- Height := 300;
- end;
- end;
-end;
-
-{**************************************************************************}
-{ call this function : NEVER! }
-{**************************************************************************}
-
-destructor TJvChart.Destroy;
-begin
- {Add code for destroying my own data...here}
- FBitmap.Free;
- {
- if Ord(FYFontHandle) <> 0 then
- DeleteObject(FYFontHandle); // vertical font object
- FreeAndNil(FYFont);
- }
- FreeAndNil(FPicture);
- FreeAndNil(FAverageData);
- FreeAndNil(FOptions);
- FreeAndNil(FData);
-
- FreeAndNil(FFloatingMarker); // Destroy collection of TJvChartFloatingMarker objects. Destroys contained objects also.
- FreeAndNil(FHorizontalBars); // NEW 2007
- FreeAndNil(FVerticalBars); // NEW 2007
-
- FreeAndNil(FMouseDownHintStrs); //new.
-
- inherited Destroy;
-end;
-
-{Paint helper}
-
-function TJvChart.DestRect: TRect;
-begin
- Result.Left := 0;
- Result.Top := 0;
- Result.Right := GetChartCanvasWidth;
- Result.Bottom := GetChartCanvasHeight;
-end;
-
-procedure TJvChart.Loaded;
-begin
- inherited Loaded;
- ResizeChartCanvas;
-end;
-
-procedure TJvChart.Resize;
-begin
- inherited Resize;
- ResizeChartCanvas;
- // Invalidate already happens in ResizeChartCanvas.
-end;
-
-{ PAINT }
-
-procedure TJvChart.DesignModePaint;
-var
- DesignStr: string;
- TW, TH: Integer;
- LCanvas: TCanvas;
-begin
- LCanvas := GetChartCanvas(false);
-
- LCanvas.Brush.Color := Options.PaperColor;
- LCanvas.Rectangle(0, 0, Width, Height);
-
- DesignStr := ClassName + RsChartDesigntimeLabel;
-
- if Options.PrimaryYAxis.YMin >= Options.PrimaryYAxis.YMax then
- begin
- if Options.PrimaryYAxis.YMax > 0 then
- Options.PrimaryYAxis.YMin := 0.0;
- end;
-
- if (Abs(Options.PrimaryYAxis.YMax) < 0.000001) and (Abs(Options.PrimaryYAxis.YMin) < 0.000001) then
- Options.PrimaryYAxis.YMax := 10.0; // Reasonable non-zero default, so that charting works!
-
- Options.PrimaryYAxis.Normalize;
- Options.SecondaryYAxis.Normalize;
- GraphSetup;
-
- DrawGradient;
- DisplayBars;
-
- PrimaryYAxisLabels;
- GraphXAxis;
- GraphXAxisDivisionMarkers;
- GraphYAxis;
- GraphYAxisDivisionMarkers;
-
- { designtime component label }
- TW := LCanvas.TextWidth(DesignStr);
- TH := LCanvas.TextHeight(DesignStr);
-
- LCanvas.Brush.Color := Options.PaperColor;
- LCanvas.Pen.Color := Color;
-
- //ACanvas.Pen.Style := psDot;
- //ACanvas.Rectangle( (width div 2) - (TW div 2), (height div 2) - (TH div 2), TW, TH);
- if (TW < Width) and (TH < Height) then
- LCanvas.TextOut((Width div 2) - (TW div 2), (Height div 2) - (TH div 2), DesignStr);
-end;
-
-procedure TJvChart.Paint; { based on TImage.Paint }
-begin
- if csDesigning in ComponentState then
- begin
- DesignModePaint;
- Exit;
- end;
-
- if Options.AutoUpdateGraph and not FAutoPlotDone then
- begin
- FAutoPlotDone := True;
- PlotGraph; // Makes sure something is visible in the TPicture.
- end;
-
- Assert(Assigned(FPicture));
- //inherited ACanvas.Lock;
- inherited Canvas.StretchDraw(DestRect, Picture.Graphic);
-
- // New: Draw custom moveable markers on TOP of base data pen layer:
- DrawFloatingMarkers;
-
- // Draw cursor (vertical dotted line) if present:
- if (FCursorPosition >= 0) and (FCursorPosition <= Options.XValueCount) then
- PaintCursor;
-
- // Allow end-user to custom paint on the Chart chanvas:
- if Assigned(FOnPaint) then
- FOnPaint(Self, Canvas);
-end;
-
-// Draw an oscilliscope-like cursor over the place where the current sample is in the chart.
-// This is very handy when you want to associate your table, grid, or other data source,
-// with the chart, and highlight one row in the chart.
-
-procedure TJvChart.PaintCursor;
-var
- X: Integer;
- XPixelGap: Double;
-begin
- with inherited Canvas do
- begin
- Pen.Color := Options.CursorColor;
- Pen.Style := Options.CursorStyle;
-
- XPixelGap := ((Options.XEnd - 2) - Options.XStartOffset) / (Options.XValueCount - 1);
-
- X := Round(Options.XStartOffset + XPixelGap * FCursorPosition);
-
- // Vertical line along X position:
- MoveTo(X, Options.YStartOffset);
- LineTo(X, FXAxisPosition - 1);
- end;
-end;
-
-{device independent functions... no checking for printer / screen needed}
-
-{**************************************************************************}
-{ call this function : }
-{ a) before setting totally new values to the graph }
-{ b) note that any custom strings in the PrimaryYAxis.Legends or }
-{ SecondaryYAxis.Legends are CLEARED by this function. }
-{**************************************************************************}
-
-procedure TJvChart.ResetGraphModule;
-begin
- Data.Clear;
-
- FPlotGraphCalled := False;
- FContainsNegative := False;
- Options.Title := '';
- Options.PenCount := 1;
- Options.XValueCount := 0;
-
- Options.PrimaryYAxis.Clear;
- Options.SecondaryYAxis.Clear;
-
- Options.XOrigin := 0;
- Options.YOrigin := 0;
- Options.XGap := 1;
-
- Options.PenLegends.Clear;
-
- (* for I := 0 to MAX_VALUES-1 do
- begin
- Options.AverageValue[I] := 0;
- end; *)
-
- Data.Clear;
- AverageData.Clear;
-
- Options.XLegends.Clear;
-end;
-
-procedure TJvChart.PrimaryYAxisLabels;
-var
- I, J: Integer;
- YDivision: Double;
- FormatStr, YDivisionStr, PrevYDivisionStr: string;
- // left hand side, vertically ascending labels for scale of Y values.
- Decimals: Integer;
- Unique: Boolean;
-begin
- Decimals := Options.PrimaryYAxis.YLegendDecimalPlaces;
- Unique := False; { Add Decimals until we get unique values }
- while not Unique do
- begin
- Unique := True;
- PrevYDivisionStr := '';
- Options.PrimaryYAxis.YLegends.Clear;
- FormatStr := '0.0';
- for J := 2 to Decimals do
- FormatStr := FormatStr + '0';
- for I := 0 to Options.PrimaryYAxis.YDivisions do // NOTE! Don't make this YDivisions-1 That'd be bad! !!!!
- begin
- YDivision := Options.PrimaryYAxis.YMin + (I * Options.PrimaryYAxis.YGap);
- if Decimals <= 0 then
- YDivisionStr := IntToStr(Round(YDivision)) // Whole Numbers Only.
- else
- YDivisionStr := FormatFloat(FormatStr, YDivision); // Variable Decimals
- if (PrevYDivisionStr = YDivisionStr) and (Decimals < 5) then
- begin
- Inc(Decimals);
- Unique := False; // Force repeat
- Break; // Exit for loop.
- end;
- Options.PrimaryYAxis.YLegends.Add(YDivisionStr);
- PrevYDivisionStr := YDivisionStr;
- end;
- end;
-end;
-
-{ Setup Graph Formatting Properties
-
- *** AutoFormatGraph CONSIDERED HARMFUL. REMOVED. ***
- This procedure does nothing helpful, and will be removed from CVS soon.
- What it *does* do is wildly screw up plotting of graphs with negative
- values in it.
- -Wpostma.
-}
-
-(* XXXX BAD CODE. TO BE DELETED SOON. Wpostma.
-procedure TJvChart.AutoFormatGraph;
-var
- V, NYMax, NYMin: Double;
-// NPen: Longint;
- I, J: Integer;
-// calcYGap: Double; // not used (ahuser)
- ATextWidth, SkipBy, MaxFit: Integer;
-begin
- // nMaxXValue := 0;
- // NPen := 0;
- Options.PrimaryYAxis.Normalize;
- Options.SecondaryYAxis.Normalize;
-
- {Set graph type according to component property}
-
- if Options.PrimaryYAxis.YMax <= Options.PrimaryYAxis.YMin then
- begin
- {Analyse graph for max and min values...}
- NYMax := Low(Integer);
- NYMin := High(Integer);
- for I := 0 to Data.ValueCount - 1 do
- begin
- for J := 0 to Options.PenCount - 1 do
- begin
- if Options.PenAxis[J] <> Options.PrimaryYAxis then
- Continue; // XXX !!! AUTO SCALING ONLY ON PRIMARY AXIS, FOR NOW. !!!
-
- V := FData.Value[J, I];
-
- if IsNaN(V) then
- Continue;
- if NYMin > V then
- NYMin := V;
- //if (I>nMaxXValue) and (FData.Value[J,I]<>0) then
- //nMaxXValue := I;
- //if (J>NPen) and (FData.Value[J,I]<>0) then
- // NPen := J;
- if NYMax < FData.Value[J, I] then
- NYMax := FData.Value[J, I];
- end;
- if (NYMin > 0) and (Options.PrimaryYAxis.YMin = 0) then
- NYMin := 0;
- end;
- // Round up YMax so it's got some zeros after it:
- if NYMax > 5000 then
- NYMax := Trunc(Trunc(NYMax + 499) / 500) * 500
- else
- if NYMax > 1000 then
- NYMax := Trunc(Trunc(NYMax + 99) / 100) * 100
- else
- if NYMax > 10 then
- NYMax := Trunc(Trunc(NYMax + 9) / 10) * 10;
-
- // And now the really bad hack:
- Options.PrimaryYAxis.SetYMax(0);
- Options.PrimaryYAxis.SetYMax(NYMax);
- end
- else
- begin
- // !!!!!!!!!!!!! WARNING WARNING WARNING !!!!!!!!!!!!!!!!!!!!
- // The following line has been commented out because it triggers
- // a warning because NYMax is not used anywhere after the
- // setting of its value
- //NYMax := Options.PrimaryYAxis.YMax;
-
- NYMin := Options.PrimaryYAxis.YMin;
- end;
-
- // And some negative handling crap.
- FContainsNegative := False;
- if NYMin < 0 then
- begin
- FContainsNegative := True;
-
-// if Options.PrimaryYAxis.DefaultYLegends>0 then
-// Options.PrimaryYAxis.Normalize
-// else
-// Options.PrimaryYAxis.YGap := 1;
-
-// if Options.PrimaryYAxis.YGap <= 0 then {* XXX WORKAROUND A BUG. Better to have bad looking data than divide by zero exceptions. XXX *}
-// Options.PrimaryYAxis.YGap := 0.00001;
-
- Options.ChartKind := ckChartLine;
- Options.YOrigin := Round(-NYMin / Options.PrimaryYAxis.YGap);
- end;
-
- if Options.PrimaryYAxis.YDivisions = 0 then
- Options.PrimaryYAxis.YDivisions := 1;
-
- //Options.PenCount := NPen;
- if Options.XValueCount < Data.ValueCount then
- Options.XValueCount := Data.ValueCount;
-
-//XXX if Options.PrimaryYAxis.YDivisions < 3 then
-// Options.PrimaryYAxis.YDivisions := 3; // some labels
-
- // Primary Y Axis Labels. This version only supports 0,1,2 decimal places.
- PrimaryYAxisLabels;
-
- // XXX TODO: Draw secondary Y Axis labels, if enabled!
-
- // if we put too many labels on the bottom X axis, they crowd or overlap,
- // so this prevents that:
-
- for I := 0 to Options.XLegends.Count - 1 do
- begin
- ATextWidth := ChartCanvas.TextWidth(Options.XLegends[I]) + 10;
-
- if ATextWidth > Options.XLegendMaxTextWidth then
- Options.XLegendMaxTextWidth := ATextWidth;
- end;
- if Options.XLegendMaxTextWidth < 20 then
- Options.XLegendMaxTextWidth := 20;
-
- MaxFit := ((Width - (Options.XStartOffset * 2)) div
- (Options.XLegendMaxTextWidth + (Options.XLegendMaxTextWidth div 4)));
- if MaxFit < 1 then
- MaxFit := 1;
-
- SkipBy := Data.ValueCount div MaxFit;
- if SkipBy < 1 then
- SkipBy := 1;
- //if SkipBy > Options.XAxisLegendSkipBy then
- Options.XAxisLegendSkipBy := SkipBy;
-
- // Now do the graphing.
- CountGraphAverage;
-
- PlotGraph;
-end;
- XXX BAD CODE. READ WARNING ABOVE.
-*)
-
-procedure TJvChart.CountGraphAverage;
-var
- I, J: Integer;
-begin
- if Options.ChartKind = ckChartLine then
- Exit; // no average needed.
-
- for I := 0 to Data.ValueCount - 1 do
- begin
- Options.AverageValue[I] := 0;
- for J := 0 to MAX_PEN - 1 do
- Options.AverageValue[I] := Options.AverageValue[I] + FData.Value[J, I];
- if Options.PenCount = 0 then
- Options.AverageValue[I] := 0
- else
- Options.AverageValue[I] := Options.AverageValue[I] / Options.PenCount;
- end;
-end;
-
-// These set up variables used for all the rest of the plotting functions.
-
-procedure TJvChart.GraphSetup;
-var
- X1, X2, Y1, Y2, PYVC, VC: Integer;
- ACanvas: TCanvas;
-begin
- ACanvas := GetChartCanvas(false);
-
- ACanvas.Brush.Style := bsSolid;
- if FData.ValueCount > 0 then
- Options.XValueCount := FData.ValueCount;
-
- { Get X value count }
- VC := Options.XValueCount;
- if VC < 1 then
- VC := 1;
-
- { Get Y value count. First normalize. }
- Options.PrimaryYAxis.Normalize;
- Options.SecondaryYAxis.Normalize;
- PYVC := Options.PrimaryYAxis.YDivisions;
- if PYVC < 1 then
- PYVC := 1;
-
- Options.XPixelGap := ((Options.XEnd - 1) - Options.XStartOffset) / VC;
-
- FXOrigin := Options.XStartOffset + Options.XPixelGap * (Options.XOrigin);
- FYOrigin := Options.YStartOffset + Round(Options.PrimaryYAxis.YPixelGap * PYVC);
-
- ACanvas.Brush.Style := bsClear;
-
- { NEW: Box around entire chart area. }
- if Options.AxisLineWidth <> 0 then
- begin
- X1 := Round(XOrigin);
- X2 := Round(Options.XStartOffset + Options.XPixelGap * VC);
- Y1 := Options.YStartOffset - 1;
- Y2 := Round(YOrigin) + 1; // was YTempOrigin
-
- if Y2 > Height then
- begin
- // I suspect that the value of YPixelGap is too large in some cases.
- Options.PrimaryYAxis.Normalize;
- //OutputDebugString( PChar('Y2 is bogus. PYVC='+IntToStr(PYVC)) );
- end;
- MyRectangle(ACanvas, X1, Y1, X2, Y2);
- end;
-
- ACanvas.Brush.Style := bsSolid;
-end;
-
-// internal methods
-
-procedure TJvChart.GraphYAxis;
-var
- ACanvas: TCanvas;
-begin
- if Options.AxisLineWidth = 0 then
- Exit;
-
- ACanvas := GetChartCanvas(false);
- ACanvas.Pen.Style := psSolid;
- ACanvas.Pen.Color := Options.AxisLineColor;
- ACanvas.MoveTo(Round(XOrigin), Options.YStartOffset);
- MyAxisLineTo(ACanvas, Round(XOrigin),
- Round((Options.YStartOffset - 1) +
- Options.PrimaryYAxis.YPixelGap * (Options.PrimaryYAxis.YDivisions)));
-end;
-
-// internal methods
-
-procedure TJvChart.GraphXAxis;
-var
- LCanvas: TCanvas;
-begin
- if Options.AxisLineWidth = 0 then
- Exit;
-
- LCanvas := GetChartCanvas(false);
- LCanvas.Pen.Style := psSolid;
- LCanvas.Pen.Color := Options.AxisLineColor;
- LCanvas.Pen.Width := Options.AxisLineWidth; // was missing. Added Feb 2005. -WPostma.
- FXAxisPosition := Options.YStartOffset + Round(Options.PrimaryYAxis.YPixelGap * (Options.PrimaryYAxis.YDivisions));
-
- {Draw X-axis}
- LCanvas.MoveTo(Options.XStartOffset, FXAxisPosition);
- MyAxisLineTo(LCanvas, Round(Options.XStartOffset + Options.XPixelGap * Options.XValueCount), FXAxisPosition);
-end;
-
-procedure TJvChart.GraphXAxisDivisionMarkers; // new.
-var
- I, X: Integer;
- Lines: Integer;
- LCanvas: TCanvas;
- // these are used only in special XAxisDateTimeMode:
- TimePerXValue: Double;
- ElapsedTime: Double;
-begin
- if not Enabled then
- Exit;
- if Options.XValueCount <= 0 then // NOT VISIBLE WHEN NO VALUES TO SHOW. NEW 2007
- Exit;
- if Options.XStartOffset <= 0 then // NOT VISIBLE WHEN NO ROOM TO SHOW IT. NEW 2007
- Exit;
-
- LCanvas := GetChartCanvas(false);
-
- if not Options.XAxisDivisionMarkers then
- Exit;
- if Options.XAxisValuesPerDivision <= 0 then
- Exit;
-
- //XAxisDateTimeMode: [NEW 2007]
- // Make charts with XAxis divisions synchronized
- // to some regular time division such as hourly periods.
- //
- // new mode! when looking at date/time charts
- // it's useful to be able to force the divisions to be
- // shown at hourly intervals, or if you're looking at a month of data
- // perhaps you might want to plot a division marker at midnight
- // or at weekly intervals.
- //
- if (Options.XAxisDateTimeMode) and
- (Options.XAxisDateTimeDivision > 0.000000001) and
- (FData.EndDateTime > FData.StartDateTime) then
- begin
-
- // How much time goes by in this chart? ( 1.0 = one day)
- ElapsedTime := FData.EndDateTime - FData.StartDateTime;
-
- // How far apart the bars are spaced is determined by
- // XAxisDateTimeDivision.
- // if we plot one day of values, and we want a marker every
- // hour, we want XAxisDateTimeDivision=(1.0/24).
-
- // Given the elapsed time in this chart, how many divisions
- // should we be showing?
- Options.FXAxisDateTimeLines := Round(ElapsedTime / Options.XAxisDateTimeDivision);
- if (Options.FXAxisDateTimeLines < 0) or (Options.FXAxisDateTimeLines > 10000) then // sanity check!
- Exit;
-
- // this value is to help us figure out how much time goes by
- // for each time we go from one X value to the next one.
- TimePerXValue := ElapsedTime / Options.XValueCount;
-
- // figure out how many divisions to move over for firstMarker
- // given TimePerXValue (1.0=one day) and StartDateTime and
- // XAxisDateTimeDivision.
- Options.FXAxisDateTimeFirstMarker := 0;
- // If XAxisDateTimeDivion=1.0, and TimePerXValue=0.25, then
- // we want a division marker for every 4th value
- Options.FXaxisDateTimeSkipBy := Round(Options.XAxisDateTimeDivision / TimePerXValue);
-
- for I := 0 to Options.FXAxisDateTimeLines - 1 do
- begin
- X := Round(Options.XStartOffset + (Options.XPixelGap * I * Options.FXaxisDateTimeSkipBy)) +
- Options.FXAxisDateTimeFirstMarker;
- if X > Options.XEnd then
- Break;
- // don't draw dotted line right at X Axis.
- if X <> Options.XStartOffset then
- begin
- LCanvas.Pen.Color := Options.GetPenColor(jvChartDivisionLineColorIndex);
- MyDrawDotLine(LCanvas, X, Options.YStartOffset + 1, X, FXAxisPosition - 1);
- end;
- end;
-
- // Note: datetime labels aren't drawn yet, they are drawn later,
- // see local procedure XAxisDateTimeModeLabels2 inside
- // GraphXAxisLegend, for the printing of the datetime labels!
-
- Exit; // done!
- end; // END OF NEW CODE IN 2007 FOR THIS METHOD. -WP-
-
- Lines := (((Options.XValueCount + (Options.XAxisValuesPerDivision div 2)) div Options.XAxisValuesPerDivision)) - 1;
-
- for I := 1 to Lines do
- begin
- X := Round(Options.XStartOffset + Options.XPixelGap * I * Options.XAxisValuesPerDivision);
- LCanvas.Pen.Color := Options.GetPenColor(jvChartDivisionLineColorIndex);
- MyDrawDotLine(LCanvas, X, Options.YStartOffset + 1, X, FXAxisPosition - 1);
- end;
-end;
-
-procedure TJvChart.GraphYAxisDivisionMarkers;
-var
- I, Y: Integer;
- LCanvas: TCanvas;
-begin
- Assert(Assigned(Self));
- Assert(Assigned(Options));
- Assert(Assigned(Options.PrimaryYAxis));
- Assert(Options.PrimaryYAxis.YPixelGap > 0);
- LCanvas := GetChartCanvas(false);
-
- LCanvas.Font := Options.AxisFont;
-
- for I := 0 to Options.PrimaryYAxis.YDivisions do
- begin
- Y := Round(YOrigin - (Options.PrimaryYAxis.YPixelGap * ((I) - Options.YOrigin)));
-
- if I < Options.PrimaryYAxis.YLegends.Count then
- MyRightTextOut(LCanvas, Round(XOrigin - 3), Y, Options.PrimaryYAxis.YLegends[I]);
-
- Y := Round(YOrigin - (Options.PrimaryYAxis.YPixelGap * ((I) - Options.YOrigin)));
- if (I > 0) and (I < (Options.PrimaryYAxis.YDivisions)) and Options.YAxisDivisionMarkers then
- begin
- LCanvas.Pen.Color := Options.GetPenColor(jvChartDivisionLineColorIndex);
- MyDrawDotLine(LCanvas, Options.XStartOffset, Y,
- Round(Options.XStartOffset + Options.XPixelGap * Options.XValueCount) - 1, Y);
- end;
- if I > 0 then
- if Options.PrimaryYAxis.YPixelGap > 20 then
- begin // more than 20 pixels per major division?
- LCanvas.Pen.Color := Options.GetPenColor(jvChartAxisColorIndex);
-
- Y := Round(Y + (Options.PrimaryYAxis.YPixelGap / 2));
- MyDrawAxisMark(LCanvas, Options.XStartOffset, Y,
- Options.XStartOffset - 4, // Tick at halfway between major marks.
- Y);
- end;
- end;
-end;
-
-procedure TJvChart.PlotMarker(ACanvas: TCanvas; MarkerKind: TJvChartPenMarkerKind; X, Y: Integer);
-begin
- // Note: each drawing function below uses chart
- // Options.MarkerSize property to determine the
- // size of the markers! Future Idea: More flexible marker sizing
- // might be useful especially in the case of floating markers.
- case MarkerKind of
- pmkDiamond:
- PlotFilledDiamond(ACanvas, X, Y);
- pmkCircle:
- begin
- ACanvas.Brush.Style := bsClear;
- PlotCircle(ACanvas, X, Y);
- ACanvas.Brush.Style := bsSolid;
- end;
- pmkSquare:
- begin
- ACanvas.Brush.Style := bsClear;
- PlotSquare(ACanvas, X, Y);
- ACanvas.Brush.Style := bsSolid;
- end;
- pmkCross:
- PlotCross(ACanvas, X, Y);
- end;
-end;
-
-
-{ PlotPicture:
- New helper method helps us to print a prettier JvChart or save to disk,
- with higher resolution and larger fonts than the ones we can show on
- the on-screen form.
- }
-procedure TJvChart.PlotPicture(picture:TPicture; fontScaling:Double);
-var
-// oldfontsize:Integer;
- oldhdrfontsize:Integer;
- oldlgdfontsize:Integer;
- oldaxisfontsize:Integer;
- oldystartoffset:Integer;
- oldxstartoffset:Integer;
-begin
- if picture.Graphic=nil then begin
- raise Exception.Create('JvChart.PlotToPicture: You must initialize picture.Graphic.Bitmap first');
- end;
-
- if not (picture.Graphic is TBitmap) then begin
- raise Exception.Create('JvChart.PlotToPicture: picture.Graphic.Bitmap must be type TBitmap.');
- end;
-
-
- //oldfontsize := Self.Font.Size;
- //Self.Font.Size := Self.Font.Size * fontScaling;
-
- oldystartoffset := Options.YStartOffset;
- Options.YStartOffset := Round(Options.YStartOffset * fontScaling);
-
- oldxstartoffset := Options.XStartOffset;
- Options.XStartOffset := Round(Options.XStartOffset * fontScaling);
-
-
- oldhdrfontsize := Options.HeaderFont.Size;
- Options.HeaderFont.Size := Round(Options.HeaderFont.Size * fontScaling);
-
- oldlgdfontsize := Options.LegendFont.Size;
- Options.LegendFont.Size := Round(Options.LegendFont.Size * fontScaling);
-
- oldaxisfontsize := Options.AxisFont.Size;
- Options.AxisFont.Size := Round(Options.AxisFont.Size * fontScaling);
-
- FExtPicture := picture;
- try
- ResizeChartCanvas; // Recovery. This shouldn't happen.
- PlotGraph;
- DrawFloatingMarkers;
-
- finally
- FExtPicture := nil;
-
- Options.YStartOffset := oldystartoffset;
- Options.XStartOffset := oldxstartoffset;
- Options.HeaderFont.Size := oldhdrfontsize;
- Options.LegendFont.Size := oldlgdfontsize;
- Options.AxisFont.Size := oldaxisfontsize;
-
- end;
- ResizeChartCanvas; // reset everything.
- Invalidate; // repaint.
-
-end;
-
-{**************************************************************************}
-{ call this function : }
-{ a) you want to show the graph stored in memory }
-{ b) you have changed single graph value (call AutoFormatGraph if all new)}
-{ c) you have changed the settings of the graph and if you do not use }
-{ FAutoUpdateGraph option }
-{**************************************************************************}
-
-procedure TJvChart.PlotGraph;
-begin
- Assert(Assigned(Options));
-
- // Sanity check on YEnd/XEnd:
- if (Options.YEnd <= 0) or (Options.XEnd <= 0) or
- (Options.YEnd > Height) or (Options.XEnd > Width) then
- begin
- FInPlotGraph := True; // recursion blocker.
- ResizeChartCanvas; // Recovery. This shouldn't happen.
- FInPlotGraph := False;
- end;
-
- InternalPlotGraph;
- Invalidate; // Force repaint.
-end;
-
-procedure TJvChart.InternalPlotGraph;
-var
- ACanvas: TCanvas;
- nStackGap: Integer;
- n100Sum: Double;
- // nOldY: Longint;
- YOldOrigin: Integer;
- nMaxTextHeight: Integer;
- // Rectangle plotting:
- X, Y, X2, Y2: Integer;
-
- //aWidth:Integer;
- //aHeight:Integer;
- { Here be lots of local functions }
-
- { Draw symbol markers and text labels on a chart... }
-
- procedure PlotGraphChartMarkers;
- var
- TW, TH, VC, I, J: Integer;
- PenAxisOpt: TJvChartYAxisOptions;
- V: Double;
- MaxV, MinV: array of Double;
- LineXPixelGap: Double;
- LastX, LastY: Integer;
- MinIndex, MaxIndex: array of Integer;
- Decimals: Integer;
- begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
-
- ACanvas.Brush.Color := Options.PaperColor;
- ACanvas.Pen.Style := psSolid;
- ACanvas.Pen.Color := Options.AxisLineColor;
- ACanvas.Brush.Style := bsSolid;
-
- VC := Options.XValueCount;
- LastX := Round(XOrigin);
- LastY := 0;
-
- if VC < 2 then
- VC := 2;
- LineXPixelGap := ((Options.XEnd - 2) - Options.XStartOffset) / (VC - 1);
-
- SetLength(MaxV, Options.PenCount);
- SetLength(MinV, Options.PenCount);
- SetLength(MinIndex, Options.PenCount);
- SetLength(MaxIndex, Options.PenCount);
-
- for I := 0 to Options.PenCount - 1 do
- begin
- if Options.PenMarkerKind[I] = pmkNone then
- Continue;
- PenAxisOpt := Options.PenAxis[I]; // Get whether this pen is plotted using the lefthand or righthand Y axis.
- MaxV[I] := PenAxisOpt.YMin;
- MinV[I] := PenAxisOpt.YMax;
- MinIndex[I] := -1;
- MaxIndex[I] := -1;
-
- for J := 0 to Options.XValueCount - 1 do
- begin
- V := FData.Value[I, J];
- if IsNaN(V) then
- Continue;
- //MaxFlag := False;
- //MinFlag := False;
- if V > MaxV[I] then
- begin
- MaxV[I] := V;
- MaxIndex[I] := J;
- end;
-
- if V < MinV[I] then
- begin
- MinV[I] := V;
- MinIndex[I] := J;
- end;
-
- // Calculate Marker position:
- X := Round(XOrigin + J * LineXPixelGap);
-
- //old:Y := Round(YOrigin - ((V / PenAxisOpt.YGap1) * PenAxisOpt.YPixelGap));
- Y := Round(YOrigin - (((V - PenAxisOpt.YMin) / PenAxisOpt.YGap) * PenAxisOpt.YPixelGap));
- SetLineColor(ACanvas, I);
- if Y < Options.YStartOffset then
- Y := Options.YStartOffset; // constrain Y to stay on chart.
-
- (*
- if MinFlag or MaxFlag then // local min/max markers!
- ACanvas.Pen.Width := 2
- else
- ACanvas.Pen.Width := 1;
- *)
-
- // Now plot the right kind of marker:
- PlotMarker(ACanvas, Options.PenMarkerKind[I], X, Y);
- end;
- end;
-
- { Now plot labels After all the markers. Looks nicer than doing
- it all together }
- for I := 0 to Options.PenCount - 1 do
- begin
- if not Options.PenValueLabels[I] then
- Continue;
- PenAxisOpt := Options.PenAxis[I]; // Get whether this pen is plotted using the lefthand or righthand Y axis.
- for J := 0 to Options.XValueCount - 1 do
- begin
- V := FData.Value[I, J];
- if IsNaN(V) then
- Continue;
- // Calculate Marker position:
- X := Round(XOrigin + J * LineXPixelGap);
- Y := Round(YOrigin - ((V / PenAxisOpt.YGap1) * PenAxisOpt.YPixelGap));
- if Y < (Options.YStartOffset + 10) then
- Y := (Options.YStartOffset + 10); // constrain Y to stay on chart.
-
- // Format with fixed number of decimal places (avoid screen clutter)
- Decimals := Options.PenAxis[I].MarkerValueDecimals;
- if Decimals < 0 then // auto
- if V < 100.0 then
- Decimals := 1 // handy automatic percentage mode.
- else
- Decimals := 0;
- Text := FloatToStrF(V, ffFixed, 16, Decimals);
-
- if Options.PenUnit.Count >= I then
- Text := Text + Options.PenUnit[I];
-
- TW := ACanvas.TextWidth(Text);
- TH := ACanvas.TextHeight(Text);
-
- if Options.GetPenValueLabels(I) and
- ((X > (LastX + (TW div 2))) or // Show if it's not going to collide
- ((Abs(Y - LastY) > (TH * 2)) and
- (X > LastX)) or
- ((J = MinIndex[I]) or (J = MaxIndex[I]))) then // Always show max/mins
- begin
- // TODO: EVENT FOR END-USER-CUSTOMIZED OR FORMATTED LABELS
- //if Assigned(FOnGetValueLabel) then
- // FOnGetValueLabel(Sender, {Pen}I, {Sample#}J, {Value}V, {var}Text );
- if Length(Text) > 0 then
- begin
- Dec(Y, 2);
- // nifty little bit to draw a box around min/max values.
- if (J = MinIndex[I]) or (J = MaxIndex[I]) then
- begin
- ACanvas.Pen.Style := psClear; //was psDot
- ACanvas.Brush.Color := Options.PaperColor; //was HintColor
- MyPolygon(ACanvas, [Point(X - ((TW div 2) + 2), Y - (TH + Options.MarkerSize + 2)),
- Point(X - ((TW div 2) + 2), Y - Options.MarkerSize),
- Point(X + (TW div 2) + 2, Y - Options.MarkerSize),
- Point(X + (TW div 2) + 2, Y - (TH + Options.MarkerSize + 2))]);
- ACanvas.Pen.Style := psSolid;
- end;
-
- if Y >= Options.YStartOffset + 20 then
- begin
- ACanvas.Brush.Style := bsSolid;
- MyCenterTextOut(ACanvas, X + 1, (Y - (Options.MarkerSize + TH)) - 1, Text);
- ACanvas.Brush.Color := Options.PaperColor;
- LastX := X + TW;
- LastY := Y;
- end;
- end;
- end;
- end;
- end;
- end;
-
- procedure PlotGraphStackedBar;
- var
- I, J: Integer;
- begin
- for J := 0 to Options.XValueCount - 1 do
- begin
- YOldOrigin := 0;
- for I := 0 to Options.PenCount - 1 do
- begin
- if Options.PenStyle[I] <> psClear then
- begin
- if Options.XPixelGap < 3.0 then
- ACanvas.Pen.Color := Options.PenColor[I] // greek-out the borders
- else
- ACanvas.Pen.Color := clBlack;
- MyColorRectangle(ACanvas, I,
- Round((XOrigin + J * Options.XPixelGap) + (Options.XPixelGap / 6)),
- Round(YOrigin - YOldOrigin),
- Round(XOrigin + (J + 1) * Options.XPixelGap - nStackGap),
- Round((YOrigin - YOldOrigin) -
- ((FData.Value[I, J] / Options.PenAxis[I].YGap) * Options.PrimaryYAxis.YPixelGap)));
- YOldOrigin := Round(YOldOrigin +
- ((FData.Value[I, J] / Options.PenAxis[I].YGap) * Options.PrimaryYAxis.YPixelGap));
- end;
- end;
- end;
- end;
-
- procedure PlotGraphBar;
- var
- I, J, N: Integer;
- BarCount: Double;
- V, BarGap: Double;
- YTempOrigin: Integer;
-
- function BarXPosition(Index: Integer): Integer;
- begin
- Result := Round(XOrigin + (Index * BarGap));
- end;
-
- begin
- YTempOrigin := Options.YStartOffset + Round(Options.PrimaryYAxis.YPixelGap * (Options.PrimaryYAxis.YDivisions));
-
- BarCount := Options.PenCount * Options.XValueCount;
- BarGap := (((Options.XEnd - 1) - Options.XStartOffset) / BarCount);
-
- for I := 0 to Options.PenCount - 1 do
- begin
- if Options.PenAxis[I].YGap = 0 then
- Continue; // Can't plot this one.
- for J := 0 to Options.XValueCount - 1 do
- begin
- N := (J * Options.PenCount) + I; // Which Bar Number!?
- // Plot a rectangle for each Bar in our bar chart...
- X := BarXPosition(N) + 1;
- // Make a space between groups, 4 pixels per XValue Index:
- //Dec(X,4);
- //Inc(X, 2*J);
- Y := YTempOrigin;
-// Assert(Y < aHeight);
- Assert(Y > 0);
- Assert(X > 0);
- //if (X>=aWidth) then
- // OutputDebugString('foo!');
-// Assert(X < aWidth);
- X2 := BarXPosition(N + 1) - 3;
- // Make a space between groups, 4 pixels per XValue Index:
- //Dec(X2,4);
- //Inc(X2, 2*J);
- V := FData.Value[I, J];
- if IsNaN(V) then
- Continue;
- Y2 := Round(YOrigin - ((V / Options.PenAxis[I].YGap) * Options.PrimaryYAxis.YPixelGap));
- //Assert(Y2 < aHeight);
- if Y2 < 0 then
- Y2 := -1; //clip extreme negatives.
- if Y2 >= Y then
- Y2 := Y - 1;
- Assert(Y2 < Y);
- Assert(X2 > 0);
- //if (X2X);
- if Options.PenCount > 1 then
- if X2 > X then
- Dec(X2); // Additional 1 pixel gap
- if Options.PenStyle[I] <> psClear then
- begin
- if (X2 - X) < 4 then // don't draw black line around bar if it is a very narrow bar.
- ACanvas.Pen.Style := psClear
- else
- ACanvas.Pen.Style := Options.PenStyle[I];
- MyColorRectangle(ACanvas, I, X, Y, X2, Y2);
- end;
- end;
- end;
- {add average line for the type...}
- if Options.ChartKind = ckChartBarAverage then
- begin
- SetLineColor(ACanvas, jvChartAverageLineColorIndex);
- ACanvas.MoveTo(Round(XOrigin + 1 * Options.XPixelGap),
- Round(YOrigin - ((Options.AverageValue[1] / Options.PrimaryYAxis.YGap) * Options.PrimaryYAxis.YPixelGap)));
- for J := 0 to Options.XValueCount do
- MyPenLineTo(ACanvas, Round(XOrigin + J * Options.XPixelGap),
- Round(YOrigin - ((Options.AverageValue[J] / Options.PrimaryYAxis.YGap) * Options.PrimaryYAxis.YPixelGap)));
- SetLineColor(ACanvas, jvChartAxisColorIndex);
- end;
- // NEW: Add markers to bar chart:
- PlotGraphChartMarkers;
- end;
-
- // Keep Y in visible chart range:
-
- function GraphConstrainedLineY(Pen, Sample: Integer): Double;
- var
- V: Double;
- PenAxisOpt: TJvChartYAxisOptions;
- begin
- V := FData.Value[Pen, Sample];
- PenAxisOpt := Options.PenAxis[Pen];
- if IsNaN(V) then
- begin
- Result := NaN; // blank placeholder value in chart!
- Exit;
- end;
- if PenAxisOpt.YGap < 0.0000001 then
- begin
- Result := 0.0; // can't chart! YGap is near zero, zero, or negative.
- Exit;
- end;
- Result := YOrigin - (((V - PenAxisOpt.YMin) / PenAxisOpt.YGap) * PenAxisOpt.YPixelGap);
- if Result >= YOrigin - 1 then
- Result := Round(YOrigin) - 1 // hit the top of the chart
- else
- if Result < Options.YStartOffset - 2 then
- Result := Options.YStartOffset - 2; // Not quite good enough, but better than before.
- end;
-
- function GetUnderLineFillColor(const A, B: TColor) : TColor;
- const
- Lerp = 0.85; // 0-1, where 0 is fully A and 1 is fully B. This value seems good
- var
- AR, AG, AB, BR, BG, BB: Byte;
- begin
- AR := GetRValue(A);
- AG := GetGValue(A);
- AB := GetBValue(A);
- BR := GetRValue(B);
- BG := GetGValue(B);
- BB := GetBValue(B);
-
- Result := RGB(
- Round(AR + Lerp * (BR - AR)),
- Round(AG + Lerp * (BG - AG)),
- Round(AB + Lerp * (BB - AB))
- );
- end;
-
- procedure PlotGraphChartLine;
- var
- I, I2, J, Y1: Integer;
- V, LineXPixelGap: Double;
- NanFlag: Boolean;
- VC: Integer;
- // PenAxisOpt: TJvChartYAxisOptions;
- begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
-
- VC := Options.XValueCount;
- if VC < 2 then
- VC := 2;
- LineXPixelGap := ((Options.XEnd - 2) - Options.XStartOffset) / (VC - 1);
-
- ACanvas.Pen.Style := psSolid;
- for I := 0 to Options.PenCount - 1 do
- begin
- // PenAxisOpt := Options.PenAxis[I];
- // No line types?
- if Options.PenStyle[I] = psClear then
- Continue;
- SetLineColor(ACanvas, I);
- J := 0;
- V := GraphConstrainedLineY(I, J);
- NanFlag := IsNaN(V);
- if not NanFlag then
- begin
- Y := Round(V);
- ACanvas.MoveTo(Round(XOrigin), Y);
- end;
-
- for J := 1 to Options.XValueCount - 1 do
- begin
- V := GraphConstrainedLineY(I, J);
- if IsNaN(V) then
- begin
- NanFlag := True; // skip.
- ACanvas.MoveTo(Round(XOrigin + J * LineXPixelGap), 200); //DEBUG!
- end
- else
- begin
- if NanFlag then
- begin // resume, valid value.
- NanFlag := False;
- Y := Round(V);
- // pick up the pen and slide forward
- ACanvas.MoveTo(Round(XOrigin + J * LineXPixelGap), Y);
- end
- else
- begin
- Y := Round(V);
- ACanvas.Pen.Style := Options.PenStyle[I];
- if I > 0 then
- begin
- for I2 := 0 to I - 1 do
- begin
- V := GraphConstrainedLineY(I2, J);
- if IsNaN(V) then
- Continue;
- Y1 := Round(V);
- if Y1 = Y then
- begin
- Dec(Y); // Prevent line-overlap. Show dotted line above other line.
- if ACanvas.Pen.Style = psSolid then
- ACanvas.Pen.Style := psDot;
- end;
- end;
- end;
- MyPenLineTo(ACanvas, Round(XOrigin + J * LineXPixelGap), Y);
- //OldV := V; // keep track of last valid value, for handling gaps.
- end;
- end;
- end;
- end;
- PlotGraphChartMarkers;
- // MARKERS:
- SetLineColor(ACanvas, jvChartAxisColorIndex);
- end;
-
- procedure PlotGraphChartLineFill;
- var
- I, I2, J: Integer;
- V, LineXPixelGap: Double;
- NanFlag: Boolean;
- VC: Integer;
- FillPoints : array of TPoint;
- FillPolyIndex : Integer;
- begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
-
- SetLength(FillPoints, 0); // Not set to 0 by compiler
- try
- VC := Options.XValueCount;
- if VC < 2 then
- VC := 2;
- LineXPixelGap := ((Options.XEnd - 2) - Options.XStartOffset) / (VC - 1);
-
- for I := 0 to Options.PenCount - 1 do
- begin
- // No line types?
- if Options.PenStyle[I] = psClear then
- Continue;
-
- SetLength(FillPoints, FData.ValueCount + 2 {start and end points});
- FillPolyIndex := 0;
-
- J := 0;
- V := GraphConstrainedLineY(I, J);
- NanFlag := IsNaN(V);
- if not NanFlag then
- begin
- Y := Round(V);
- FillPoints[FillPolyIndex] := Point(Round(XOrigin)+1, Round(YOrigin)); // start at origin
- Inc(FillPolyIndex);
- FillPoints[FillPolyIndex] := Point(Round(XOrigin)+1, Y); // add first point
- Inc(FillPolyIndex);
- end;
-
- for J := 1 to Options.XValueCount - 1 do
- begin
- V := GraphConstrainedLineY(I, J);
- if IsNaN(V) then
- begin
- NanFlag := True; // skip.
- FillPoints[FillPolyIndex] := Point(Round(XOrigin + J * LineXPixelGap), Round(YOrigin)); // !!! DEBUG
- Inc(FillPolyIndex);
- end
- else
- begin
- if NanFlag then
- begin // resume, valid value.
- NanFlag := False;
- Y := Round(V);
- // pick up the pen and slide forward
- FillPoints[FillPolyIndex] := Point(Round(XOrigin + J * LineXPixelGap), Y);
- Inc(FillPolyIndex);
- end
- else
- begin
- Y := Round(V);
- if I > 0 then
- begin
- for I2 := 0 to I - 1 do
- begin
- V := GraphConstrainedLineY(I2, J);
- if IsNaN(V) then
- Continue;
- end;
- end;
-
- FillPoints[FillPolyIndex] := Point(Round(XOrigin + J * LineXPixelGap), Y); // add next point
- Inc(FillPolyIndex);
- end;
- end;
- end;
-
- // Add a final point which is the same as the last, but at the bottom
- if FillPolyIndex > 0 then begin
- FillPoints[FillPolyIndex] := Point(FillPoints[FillPolyIndex-1].X, Round(YOrigin));
- Inc(FillPolyIndex);
- SetLength(FillPoints, FillPolyIndex); // Trim to the actual usage
-
- // First draw the fill
- ACanvas.Pen.Style := psClear;
- ACanvas.Brush.Color := GetUnderLineFillColor(Options.PenColor[I],
- Options.PenColor[jvChartPaperColorIndex]);
- ACanvas.Brush.Style := bsSolid;
- ACanvas.Polygon(FillPoints);
- end;
- end;
- finally
- SetLength(FillPoints, 0);
- end;
- end;
-
- procedure PlotGraphStackedBarAverage;
- var
- I, J: Integer;
- begin
- for J := 0 to Options.XValueCount - 1 do
- begin
- n100Sum := 0;
- for I := 0 to Options.PenCount - 1 do
- n100Sum := n100Sum + FData.Value[I, J];
-
- for I := 0 to Options.PenCount - 1 do
- if n100Sum <> 0 then
- AverageData.Value[I, J] := (FData.Value[I, J] / n100Sum) * 100
- else
- AverageData.Value[I, J] := 0;
- end;
-
- for J := 0 to Options.XValueCount - 1 do
- begin
- YOldOrigin := 0;
- for I := 0 to Options.PenCount - 1 do
- begin
- if I = Options.PenCount then {last one; draw it always to the top line}
- MyColorRectangle(ACanvas, I,
- Round(XOrigin + J * Options.XPixelGap + (Options.XPixelGap / 2)),
- Round(YOrigin - YOldOrigin),
- Round(XOrigin + (J + 1) * Options.XPixelGap + (Options.XPixelGap / 2) - nStackGap),
- Options.YStartOffset)
- else
- begin
- MyColorRectangle(ACanvas, I,
- Round(XOrigin + J * Options.XPixelGap + (Options.XPixelGap / 2)),
- Round(YOrigin - YOldOrigin),
- Round(XOrigin + (J + 1) * Options.XPixelGap + (Options.XPixelGap / 2) - nStackGap),
- Round((YOrigin - YOldOrigin) -
- ((AverageData.Value[I, J] / Options.PenAxis[I].YGap) * Options.PrimaryYAxis.YPixelGap)));
- YOldOrigin := YOldOrigin + Round((AverageData.Value[I, J] / Options.PenAxis[I].YGap) *
- Options.PrimaryYAxis.YPixelGap);
- end;
- end;
- end;
- end;
-
- procedure CheckYAxisFlags;
- var
- I: Integer;
- begin
- Options.PrimaryYAxis.FActive := True;
- Options.SecondaryYAxis.FActive := False;
- for I := 0 to Options.PenCount - 1 do
- if Options.PenSecondaryAxisFlag[I] then
- begin
- Options.SecondaryYAxis.FActive := True;
- Break;
- end;
- end;
-
-begin { Enough local functions for ya? -WP }
- ACanvas := GetChartCanvas(false);
- //aWidth := GetChartCanvasWidth;
- //aHeight:= GetChartCanvasHeight;
-
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- Assert(Assigned(ACanvas.Pen));
-
- FPlotGraphCalled := True;
-
- // refuse to refresh under these conditions:
- if not (Enabled and Visible) then
- Exit;
- if csDesigning in ComponentState then
- begin
- if not Assigned(Self.Parent) then
- Exit;
- if Self.Name = '' then
- Exit;
- end;
-
- // safety before we paint.
- Assert(Assigned(Self));
- Assert(Assigned(Data));
- Assert(Assigned(Options));
- Assert(Assigned(Options.PrimaryYAxis));
- Assert(Assigned(Options.SecondaryYAxis));
- Assert(Assigned(AverageData));
-
- // NEW: Primary Y axis is always shown, but secondary is only shown
- // if a pen is set up to plot on the secondary Y Axis scale.
- CheckYAxisFlags;
-
- ClearScreen;
-
- if Options.XValueCount > MAX_VALUES then
- Options.XValueCount := MAX_VALUES;
- if Options.PenCount > MAX_PEN then
- Options.PenCount := MAX_PEN;
- (*
- if Options.PrimaryYAxis.YGap = 0 then
- Options.PrimaryYAxis.YGap := 1;
- if Options.SecondaryYAxis.YGap = 0 then
- Options.SecondaryYAxis.YGap := 1;
- *)
-
- PrimaryYAxisLabels; // Make sure there are Y Axis labels!
-
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
-
- { Resize Header area according to HeaderFont size }
- if (not PrintInSession) and (Length(Options.XAxisHeader) > 0) then
- begin
- MyHeaderFont(ACanvas);
- // nOldY := Options.YStartOffset;
- nMaxTextHeight := CanvasMaxTextHeight(ACanvas) + 2 * TITLE_MARGIN;
- // Bump bottom margins if the fonts don't fit!
- if Options.YStartOffset < nMaxTextHeight then
- begin
- Options.YStartOffset := nMaxTextHeight;
- //Options.YEnd := Options.YEnd + (nOldY - Options.YStartOffset);
- CalcYEnd;
- Options.PrimaryYAxis.Normalize;
- Options.SecondaryYAxis.Normalize;
- end;
- end;
-
- if (Options.ChartKind = ckChartStackedBar) or
- (Options.ChartKind = ckChartStackedBarAverage) then
- begin
- FOldYOrigin := Options.YOrigin;
- Options.YOrigin := 0;
- end
- else
- FOldYOrigin := Options.YOrigin;
- if Options.ChartKind = ckChartStackedBarAverage then
- FOldYGap := Options.PrimaryYAxis.YGap
- else
- FOldYGap := Options.PrimaryYAxis.YGap;
-
- { This effects only graph type: JvChartStackedBar(_100) }
- nStackGap := 1;
- if Options.XEnd > 200 then
- nStackGap := 3;
-
- MyAxisFont(ACanvas);
-
- YOldOrigin := Trunc(YOrigin);
-
- {Draw header and other stuff...}
- GraphSetup;
-
- // If FData.ValueCount is zero we can preview the visual appearance of the chart,
- // but there is no plotting of pens that can occur, so stop now...
- if FData.ValueCount = 0 then // EMPTY!
- begin
- { draw a blank chart. Component shouldn't just be a white square, it makes
- users think we're broken, when we're not, they just haven't given us any
- data.}
- Options.PrimaryYAxis.Normalize;
- Options.SecondaryYAxis.Normalize;
- GraphSetup;
-
- GraphXAxis;
- GraphXAxisDivisionMarkers;
- GraphYAxis;
- GraphYAxisDivisionMarkers;
-
- ACanvas.Font.Color := clRed;
- if Length(Options.NoDataMessage) = 0 then
- MyLeftTextOut(ACanvas, Round(XOrigin), Round(YOrigin) + 4, RsNoData)
- else
- MyLeftTextOut(ACanvas, Round(XOrigin), Round(YOrigin) + 4, Options.NoDataMessage); // NEW! NOV 2004. WP.
-
- Exit;
- end;
-
- DrawGradient; // NEW 2007
- DisplayBars; // NEW 2007
-
- {Y Axis}
- GraphYAxis;
- GraphYAxisDivisionMarkers; // dotted lines making graph-paper across graph
-
- {X Axis}
- GraphXAxis;
- GraphXAxisDivisionMarkers; // new.
-
- {X-axis legends...}
- GraphXAxisLegend;
-
- {Main Header}
- if Options.Title <> '' then
- MyHeader(ACanvas, Options.Title);
-
- {X axis header}
- if Options.XAxisHeader <> '' then
- MyXHeader(ACanvas, Options.XAxisHeader);
-
- {Create the actual graph...}
- case Options.ChartKind of
- ckChartBar, ckChartBarAverage:
- PlotGraphBar;
- ckChartStackedBar:
- PlotGraphStackedBar;
- ckChartLine: //, ckChartLineWithMarkers:
- begin
- if Options.FillUnderLine then
- PlotGraphChartLineFill; // Do this before drawing lines, so lines are always visible
- PlotGraphChartLine;
- end;
- ckChartMarkers:
- PlotGraphChartMarkers;
- ckChartStackedBarAverage:
- PlotGraphStackedBarAverage;
- ckChartPieChart:
- GraphPieChart(1); { special types}
- ckChartDeltaAverage:
- GraphDeltaAverage; { special types}
- end;
- {Y axis header}
- MyYHeader(ACanvas, Options.YAxisHeader); // vertical text out on Y axis
-end;
-
-
-
-procedure TJvChart.DrawChartLegendBelow(ACanvas: TCanvas); {accidentally deleted during Jedi_new to Jedi_2009 branch. Restored by WP June 2009}
-var
- I,Y,nTextHeight:Integer;
- BoxWidth:Integer;
- LLabel:String;
-begin
- if (Options.Legend <> clChartLegendBelow) then exit;
-
- if (Options.YStartOffset<=0) or (Options.XStartOffset<=0) then exit;
-
- // space-saving pen-legend below chart
- MySmallGraphFont(ACanvas);
- nTextHeight := CanvasMaxTextHeight(ACanvas);
-
- //BoxHeight := nTextHeight - 2;
-
- Options.FXLegendHoriz := Options.XStartOffset;
- for I := 0 to Options.PenCount - 1 do
- begin
- if Options.PenStyle[I] = psClear then
- if Options.GetPenMarkerKind(I) = pmkNone then
- Continue; // Skip invisible pens.
-
- Y := Options.YStartOffset + Options.YEnd + X_TITLE_LABEL_DISTANCE; //(nTextHeight div 2);
-
- // If chart has X legends:
- if (Options.XLegends.Count > 0) or Options.XAxisDateTimeMode then
- Y := Y + nTextHeight;
-
- if Options.PenStyle[I] = psClear then
- begin
- // For markers, draw marker:
- ACanvas.Pen.Color := Options.GetPenColor(I);
- GraphXAxisLegendMarker(ACanvas, Options.GetPenMarkerKind(I),
- Options.FXLegendHoriz, (Y + 8) - (Options.MarkerSize div 2));
- BoxWidth := Options.MarkerSize + 2;
- end
- else
- begin
- // For lines, draw a pen color box:
- BoxWidth := ACanvas.TextWidth('X') * 2 - 2;
- DrawPenColorBox(ACanvas, I, {pen#}
- BoxWidth - 2, {width}
- nTextHeight - 2, {height}
- Options.FXLegendHoriz, {X=}
- Y + 2); {Y=}
- end;
-
- //SetFontColor(ACanvas, jvChartAxisColorIndex); XXX
- ACanvas.Font.Color := Options.AxisFont.Color;
-
- // Draw the Pen Legend (WAP :add unit to legend. )
- if Options.PenLegends.Count > I then
- LLabel := Options.PenLegends[I]
- else
- LLabel := IntToStr(I + 1);
-
- // Put units in pen legends
- //
- // if ( Options.PenUnit.Count > I )
- // and ( Length( Options.PenUnit[I] ) > 0 ) then
- // myLabel := myLabel + ' ('+Options.PenUnit[I]+')';
-
-
- MyLeftTextOut(ACanvas, Options.FXLegendHoriz + BoxWidth + 3, Y, LLabel);
- Inc(Options.FXLegendHoriz, BoxWidth + ACanvas.TextWidth( LLabel) + 14);
- //Inc(VisiblePenCount);
- //end;
- end;
-end;{procedure}
-
-
-
-
-procedure TJvChart.GraphXAxisLegendMarker(ACanvas: TCanvas; MarkerKind: TJvChartPenMarkerKind; X, Y: Integer);
-begin
- case MarkerKind of
- pmkDiamond:
- PlotFilledDiamond(ACanvas, X, Y);
- pmkCircle:
- PlotCircle(ACanvas, X, Y);
- pmkSquare:
- PlotSquare(ACanvas, X, Y);
- pmkCross:
- PlotCross(ACanvas, X, Y);
- end;
-end;
-
-procedure TJvChart.GraphXAxisLegend; // reworked in 2007.
-var
- I: Integer;
- Timestamp: TDateTime;
- TimestampStr: string;
- XOverlap: Integer;
- ACanvas: TCanvas;
-
- { draw x axis text at various alignments:}
- function LeftXAxisText: Boolean;
- var
- Y: Integer;
- begin
- Result := True;
- // Don't exceed right margin - causes some undesirable clipping. removed. -wpostma.
- {if I < Options.XLegends.Count then
- if ACanvas.TextWidth(Options.XLegends[I]) + Options.FXLegendHoriz > (Width XEnd+10) then begin
- Result := False;
- Exit;
- end;}
-
- // Label X axis above or below?
- if FContainsNegative then
- begin
- if I < Options.XLegends.Count then
- begin // fix exception. June 23, 2004- WPostma.
- if Options.FXLegendHoriz < XOverlap then
- Exit; // would overlap, don't draw it.
- MyLeftTextOut(ACanvas, Options.FXLegendHoriz, Options.YEnd + 3, Options.XLegends[I]);
- XOverlap := Options.FXLegendHoriz + ACanvas.TextWidth(Options.XLegends[I]);
- end;
- end
- else
- if I < Options.XLegends.Count then
- begin
- if Options.FXLegendHoriz < XOverlap then
- Exit; // would overlap, don't draw it.
- Y := FXAxisPosition + Options.AxisLineWidth div 2;
- MyLeftTextOut(ACanvas, Options.FXLegendHoriz, Y, Options.XLegends[I]);
- XOverlap := Options.FXLegendHoriz + ACanvas.TextWidth(Options.XLegends[I]);
- end
- else
- Result := False;
- end;
-
- function RightXAxisText: Boolean;
- var
- Y: Integer;
- begin
- Result := True;
- // Label X axis above or below?
- if FContainsNegative then
- begin
- if I < Options.XLegends.Count then // fix exception. June 23, 2004- WPostma.
- MyRightTextOut(ACanvas, Options.FXLegendHoriz, Options.YEnd + 3, Options.XLegends[I])
- end else
- if I < Options.XLegends.Count then
- begin
- Y := FXAxisPosition + Options.AxisLineWidth div 2;
- MyRightTextOut(ACanvas, Options.FXLegendHoriz, Y, Options.XLegends[I]);
- end else
- Result := False;
- end;
-
- function CenterXAxisText: Boolean;
- var
- Y: Integer;
- begin
- Result := True;
- // Label X axis above or below?
- if FContainsNegative then
- begin
- if I < Options.XLegends.Count then // fix exception. June 23, 2004- WPostma.
- MyCenterTextOut(ACanvas, Options.FXLegendHoriz, Options.YEnd + 3, Options.XLegends[I])
- end
- else
- if I < Options.XLegends.Count then
- begin
- Y := FXAxisPosition + Options.AxisLineWidth div 2;
- MyCenterTextOut(ACanvas, Options.FXLegendHoriz, Y, Options.XLegends[I]);
- end else
- Result := False;
- end;
-
- procedure XAxisDateTimeModeLabels1; // Classic mode [REFACTORED 2007]
- var
- L: Integer;
- Y: Integer;
- begin
- // classic JvChart XAxisDateTime mode labels painting code.
-
- // if not Options.XAxisDivisionMarkers then Exit;
- if Options.XAxisValuesPerDivision <= 0 then
- Exit;
- if Options.XStartOffset <= 0 then
- Exit;
-
- for L := 1 to Options.XValueCount div Options.XAxisValuesPerDivision - 1 do
- begin
- Options.FXLegendHoriz := Round(Options.XStartOffset + Options.XPixelGap * L * Options.XAxisValuesPerDivision);
-
- Timestamp := FData.Timestamp[L * Options.XAxisValuesPerDivision - 1];
- if Timestamp < 0.0000001 then
- Continue;
-
- if Length(Options.FXAxisDateTimeFormat) = 0 then // not specified, means use Locale defaults
- TimestampStr := TimeToStr(Timestamp)
- else
- TimestampStr := FormatDateTime(Options.FXAxisDateTimeFormat, Timestamp);
-
- // Check if writing this label would collide with previous label, if not, plot it
- if (Options.FXLegendHoriz - (ACanvas.TextWidth(TimestampStr) div 2)) > XOverlap then
- begin
- Y := FXAxisPosition + Options.AxisLineWidth div 2;
- MyCenterTextOut(ACanvas, Options.FXLegendHoriz, Y, TimeStampStr);
-
- // draw a ticky-boo (technical term used by scientists the world over)
- // so that we can see where on the chart the X axis datetime is pointing to.
- ACanvas.Pen.Width := 1;
- ACanvas.MoveTo(Options.FXLegendHoriz, FXAxisPosition);
- ACanvas.LineTo(Options.FXLegendHoriz, FXAxisPosition + Options.AxisLineWidth + 2);
-
- XOverlap := Options.FXLegendHoriz + ACanvas.TextWidth(TimestampStr);
- end;
- end;
-
- end;
-
- //XAxisDateTimeModeLabels2: [NEW 2007]
- // make text labels line up with new division line drawing code
- // in GraphXAxisDivisionMarkers:
-
- procedure XAxisDateTimeModeLabels2; // [NEW 2007]
- var
- L: Integer;
- X, Y: Integer;
- DivPixels: Integer;
- TextWidth: Integer;
- Modn: Integer;
- begin
- Assert(Options.FXAxisDateTimeSkipBy > 0);
-
- DivPixels := Round(Options.XPixelGap * Options.FXaxisDateTimeSkipBy);
-
- for L := 0 to FOptions.FXAxisDateTimeLines - 1 do
- begin
- Timestamp := FData.Timestamp[(L * Options.FXaxisDateTimeSkipBy)] + Options.FXAxisDateTimeFirstMarker;
-
- if Timestamp < 0.0000001 then
- Continue;
-
- if Length(Options.FXAxisDateTimeFormat) = 0 then // not specified, means use Locale defaults
- TimestampStr := TimeToStr(Timestamp)
- else
- TimestampStr := FormatDateTime(Options.FXAxisDateTimeFormat, Timestamp);
-
- TextWidth := ACanvas.TextWidth(TimeStampStr);
- if DivPixels > 0 then
- begin
- Modn := Trunc(TextWidth / DivPixels) + 1;
- if Modn > 1 then
- begin
- if (L mod Modn) <> 0 then
- Continue; // skip labels if they are too densely spaced.
- end;
- end;
-
- X := Round(Options.XStartOffset + (Options.XPixelGap * L * Options.FXaxisDateTimeSkipBy)) +
- Options.FXAxisDateTimeFirstMarker;
- if X > Options.XEnd then
- Break;
- if X = Options.XStartOffset then
- Continue; // don't draw dotted line right at X Axis.
-
- Y := FXAxisPosition + Options.AxisLineWidth div 2;
- MyCenterTextOut(ACanvas, X, Y, TimeStampStr);
-
- ACanvas.Pen.Color := Options.GetPenColor(jvChartDivisionLineColorIndex);
- MyDrawDotLine(ACanvas, X, Options.YStartOffset + 1, X, FXAxisPosition - 1);
- end;
- end;
-
- procedure DefaultXAxisLegendMode;
- var
- count: Integer;
- K: Integer;
- begin
- {default X axis legend mode: use text legends}
- if Options.FXAxisLegendSkipBy < 1 then
- Options.FXAxisLegendSkipBy := 1;
-
- Count := (Options.XValueCount + (Options.FXAxisLegendSkipBy - 1)) div Options.FXAxisLegendSkipBy;
- // Skip the first (Index 0) Axis Label, for visual reasons.
- for K := 0 to Count - 1 do
- begin
- I := K * Options.FXAxisLegendSkipBy;
- //Options.FXLegendHoriz := Round(Options.XStartOffset + (Options.XPixelGap * I));
- Options.FXLegendHoriz := Round(Options.XStartOffset + Options.XPixelGap * I );
-
- case Options.FXAxisLabelAlignment of
- taLeftJustify: if not leftXAxisText then break;
- taRightJustify: if not rightXAxisText then break;
- taCenter: if not centerXAxisText then break;
- end;
- end; {for K}
- end; {default mode}
-
-begin
- {X-LEGEND: ...}
- if (Options.XStartOffset = 0) and (Options.YStartOffset = 0) then
- Exit;
- ACanvas := GetChartCanvas(false);
-
- XOverlap := 0; // XAxis Label Overlap protection checking variable.
-
- {Count how many characters to show in the separate legend}
-
- SetLineColor(ACanvas, jvChartAxisColorIndex);
- MyAxisFont(ACanvas);
-
- { datetime mode for X axis legends : follow the time division markers }
- if Options.XAxisDateTimeMode then
- begin { if DateTime mode then legends are painted where the division markers are painted }
- if (Data.EndDateTime > Data.StartDateTime) and (Options.XAxisDateTimeDivision > 0.00001) then
- XAxisDateTimeModeLabels2 // new mode! align division markers to even hour/day/etc boundaries!
- else
- XAxisDateTimeModeLabels1; // classic mode! let the labels displayed be any old time.
- end else
- if Options.XValueCount > 0 then // is there data to plot?
- begin
- DefaultXAxisLegendMode;
- end;
- DrawChartLegendBelow(ACanvas);
-end;
-
-procedure TJvChart.DrawPenColorBox(ACanvas: TCanvas; NColor, W, H, X, Y: Integer);
-begin
- MyColorRectangle(ACanvas, NColor, X, Y, X + W, Y + H);
- SetRectangleColor(ACanvas, jvChartPaperColorIndex);
-end;
-
-
-{**************************************************************************}
-{ call this function : }
-{ a) when you want to print the graph to Windows default printer }
-{**************************************************************************}
-
-procedure TJvChart.PrintGraph;
-var
- nXEnd, nYEnd: Longint;
- nXStart, nYStart: Longint;
- nLegendWidth: Longint;
-begin
- {Save display values...}
- nXEnd := Options.XEnd;
- nYEnd := Options.YEnd;
- nXStart := Options.XStartOffset;
- nYStart := Options.YStartOffset;
- nLegendWidth := Options.LegendWidth;
- {Calculate new values for printer....}
- Options.LegendWidth := Round((Options.LegendWidth / (nXEnd + Options.LegendWidth)) * Printer.PageWidth);
- Options.XStartOffset := Round(Printer.PageWidth * 0.08); {8%}
- Options.YStartOffset := Round(Printer.PageHeight * 0.1); {10%}
- Options.XEnd := Round(Printer.PageWidth - (1.2 * Options.LegendWidth)) - Options.XStartOffset;
- Options.YEnd := Round(Printer.PageHeight * 0.75);
- if Options.YEnd > Options.XEnd then
- Options.YEnd := Options.XEnd;
- {Begin printing...}
- PrintInSession := True;
- Printer.BeginDoc;
- PlotGraph; {Here it goes!}
- Printer.EndDoc;
- PrintInSession := False;
- {Restore display values...}
- Options.XStartOffset := nXStart; {margin}
- Options.YStartOffset := nYStart;
- Options.XEnd := nXEnd;
- Options.YEnd := nYEnd;
- Options.LegendWidth := nLegendWidth;
-end;
-
-{**************************************************************************}
-{ call this function : }
-{ a) when you want to print the graph to Windows default printer }
-{ AND you add something else on the same paper. This function }
-{ will just add the chart to the OPEN printer canvas at given position }
-{**************************************************************************}
-
-// (rom) XStartPos, YStartPos unused
-
-procedure TJvChart.AddGraphToOpenPrintCanvas(XStartPos, YStartPos, GraphWidth, GraphHeight: Longint);
-var
- nXEnd, nYEnd: Longint;
- nXStart, nYStart: Longint;
- nLegendWidth: Longint;
-begin
- {Save display values...}
- nXEnd := Options.XEnd;
- nYEnd := Options.YEnd;
- nXStart := Options.XStartOffset;
- nYStart := Options.YStartOffset;
- nLegendWidth := Options.LegendWidth;
- {Set new values for printing the graph at EXISTING print canvas....}
- Options.LegendWidth := Round((Options.LegendWidth / (nXEnd + Options.LegendWidth)) * GraphWidth);
- Options.XStartOffset := Round(GraphWidth * 0.08); {8%}
- Options.YStartOffset := Round(GraphHeight * 0.1); {10%}
- Options.XEnd := Round(GraphWidth - (1.2 * Options.LegendWidth)) - Options.XStartOffset;
- Options.YEnd := Round(GraphHeight * 0.75);
- {Begin printing...NOTICE BeginDoc And EndDoc must be done OUTSIDE this procedure call}
- PrintInSession := True;
- PlotGraph; {Here it goes!}
- PrintInSession := False;
- {Restore display values...}
- Options.XStartOffset := nXStart; {margin}
- Options.YStartOffset := nYStart;
- Options.XEnd := nXEnd;
- Options.YEnd := nYEnd;
- Options.LegendWidth := nLegendWidth;
-end;
-
-{NEW}
-{ when the user clicks the chart and changes the axis, we need a notification
- so we can save the new settings. }
-
-procedure TJvChart.NotifyOptionsChange;
-begin
- if FUpdating then
- Exit;
- if csDesigning in ComponentState then
- begin
- Invalidate;
- Exit;
- end;
- if csLoading in ComponentState then
- Exit; // Component properties being set at runtime.
-
- if Options.PenCount <> Self.Data.FPenCount then
- begin
- if Options.PenCount > 0 then { never set Data.FPenCount to zero internally! }
- Data.FPenCount := Options.PenCount;
- end;
-
- // Event fire:
- if Assigned(FOnOptionsChangeEvent) then
- FOnOptionsChangeEvent(Self);
- if Options.AutoUpdateGraph then
- begin
- FAutoPlotDone := False; // Next paint will also call PlotGraph
- Invalidate;
- end;
-end;
-
-{ Warren implemented TImage related code directly into TJvChart, to remove TImage as base class.}
-// (rom) simplified by returning the Printer ACanvas when printing
-
-function TJvChart.GetChartCanvas(isFloating:Boolean): TCanvas;
-var
- Bitmap: TBitmap;
-begin
- { designtime - draw directly to screen }
- if csDesigning in ComponentState then
- begin
- Result := Self.Canvas;
- Assert(Assigned(Result));
- Assert(Assigned(Result.Brush));
- Exit;
- end;
-
- // external picture mode?
- if Assigned(FExtPicture) and Assigned(FExtPicture.Graphic) then begin
- if FExtPicture.Graphic is TBitmap then begin
- Result := TBitmap(FExtPicture.Graphic).Canvas;
- exit;
- end else begin
- raise EInvalidOperation.Create(RsEUnableToGetCanvas);
- end;
- end;
-
- { printer canvas }
- if PrintInSession then
- begin
- Result := Printer.Canvas;
- Assert(Assigned(Result));
- Assert(Assigned(Result.Brush));
- Exit;
- end;
-
- { Floating marker draw but not external picture mode:}
- if isFloating then begin
- Result := Self.Canvas;
- exit;
- end;
-
- { FPicture.Graphic -bitmap canvas - normal display method. }
- if FPicture.Graphic = nil then
- begin
- Bitmap := TBitmap.Create;
- try
- Bitmap.Width := Width;
- Bitmap.Height := Height;
- FPicture.Graphic := Bitmap;
- finally
- Bitmap.Free;
- end;
- end;
- if FPicture.Graphic is TBitmap then
- begin
- Result := TBitmap(FPicture.Graphic).Canvas;
- Assert(Assigned(Result));
- Assert(Assigned(Result.Brush));
- end
- else
- raise EInvalidOperation.CreateRes(@RsEUnableToGetCanvas);
-end;
-
-function TJvChart.GetChartCanvasWidth: Integer; // WP NEW 2007
-begin
- { designtime - draw directly to screen }
- if csDesigning in ComponentState then
- begin
- Result := Width;
- Exit;
- end;
-
- if Assigned(FExtPicture) then begin
- result := FExtPicture.Graphic.Width;
- exit;
- end;
-
- if PrintInSession then
- begin
- Result := Printer.PageWidth;
- Exit;
- end;
-
- if Assigned(FPicture) then
- Result := FPicture.Width
- else
- Result := Width;
-end;
-
-function TJvChart.GetChartCanvasHeight: Integer; // WP NEW 2007
-begin
- { designtime - draw directly to screen }
- if csDesigning in ComponentState then
- begin
- Result := Self.Height;
- Exit;
- end;
-
- if Assigned(FExtPicture) then begin
- result := FExtPicture.Graphic.Height;
- exit;
- end;
-
- { printer canvas }
- if PrintInSession then
- begin
- Result := Printer.PageHeight;
- Exit;
- end;
-
- { FPicture.Graphic -bitmap canvas - normal display method. }
- if Assigned(FPicture) then
- Result := FPicture.Height
- else
- Result := Self.Height;
-end;
-
-function TJvChart.CalcXAxisTextHeight: Integer;
-var
- lCanvas: TCanvas;
-begin
- lCanvas := GetChartCanvas(false);
-
- Result := TITLE_MARGIN;
-
- if FOptions.XLegends.Count > 0 then
- begin
- MyAxisFont(lCanvas);
- Result := Result + lCanvas.TextHeight('Tg')
- end;
-
- if FOptions.XAxisHeader <> '' then
- begin
- MyAxisTitleFont(lCanvas, false);
- Result := Result + lCanvas.TextHeight('Tg') + X_TITLE_LABEL_DISTANCE;
- end;
-end;
-
-procedure TJvChart.CalcYEnd;
-var
- aHeight: Integer;
-begin
- if Assigned(FExtPicture) then begin
- aHeight := FExtPicture.Bitmap.Height;
- end else begin
- if not Assigned(FBitmap) then exit;
- aHeight := FBitmap.Height;
- end;
-
-// Options.YEnd := aHeight - 2 * Options.YStartOffset; {canvas size, excluding margin}
- Options.YEnd := aHeight - Options.YStartOffset - CalcXAxisTextHeight;
-end;
-
-
-{**************************************************************************}
-{ call this function : }
-{ a) when you resize the canvas for the AABsoftGraph }
-{ b) at program startup before drawing the first graph }
-{**************************************************************************}
-// ResizeChartCanvas/PlotGraph endless recursion loop fixed. --WP
-procedure TJvChart.ResizeChartCanvas;
-var
- awidth:Integer;
-begin
- {Add code for my own data...here}
- if Assigned(FExtPicture) then begin
- awidth := FExtPicture.Graphic.Width;
- end else begin
- if not Assigned(FBitmap) then
- begin
- FBitmap := TBitmap.Create;
- FBitmap.Height := Height;
- FBitmap.Width := Width;
- FPicture.Graphic := FBitmap;
- end
- else
- begin
- FBitmap.Width := Width;
- FBitmap.Height := Height;
- FPicture.Graphic := FBitmap;
- end;
- awidth := Width;
- end;
-
- CalcYEnd; // YEnd depends on YStartOffset.
-
- if Options.Legend = clChartLegendRight then
- Options.XEnd := Round(((awidth - 2) - 1.5 * Options.XStartOffset) - Options.LegendWidth)
- else
- Options.XEnd := Round((awidth - 2) - 0.5 * Options.XStartOffset);
-
- if Options.XEnd < 10 then
- Options.XEnd := 10;
- if Options.YEnd < 10 then
- Options.YEnd := 10;
-
- if not Assigned(Data) then
- Exit; //safety.
- // if Data.ValueCount = 0 then
- // Exit; // no use, there's no data yet.
-
- Options.PrimaryYAxis.Normalize;
- Options.SecondaryYAxis.Normalize;
-
- if (not FInPlotGraph) and Visible {and (Data.ValueCount>0)} then // endless recursion protection.
- if Options.AutoUpdateGraph or FPlotGraphCalled then
- begin
- FInPlotGraph := True; // recursion blocker.
- InternalPlotGraph; { must not call Invalidate here, causes exceptions in some cases. }
- FInPlotGraph := False;
- end;
-end;
-
-{This procedure is called when user clicks on the main header}
-procedure TJvChart.EditHeader;
-var
- StrString: string;
-begin
- StrString := Options.Title;
- if InputQuery(RsGraphHeader, Format(RsCurrentHeaders, [Options.Title]), StrString) then
- Options.Title := StrString;
- InternalPlotGraph;
- Invalidate;
- if Assigned(FOnTitleClick) then
- FOnTitleClick(Self);
-end;
-
-{This procedure is called when user clicks on the X-axis header}
-procedure TJvChart.EditXHeader;
-var
- StrString: string;
-begin
- StrString := Options.XAxisHeader;
- if InputQuery(RsGraphHeader, Format(RsXAxisHeaders, [Options.XAxisHeader]), StrString) then
- Options.XAxisHeader := StrString;
- InternalPlotGraph;
- Invalidate;
-end;
-
-procedure TJvChart.EditYScale;
-var
- StrString: string;
-begin
- StrString := FloatToStr(Options.PrimaryYAxis.YMax);
-
- // NOTE: StrToFloatDefIgnoreInvalidCharacters now called JvSafeStrToFloatDef:
-
- if InputQuery(RsGraphScale, Format(RsYAxisScales, [FloatToStr(Options.PrimaryYAxis.YMax)]), StrString) then
- Options.PrimaryYAxis.YMax := JvSafeStrToFloatDef(StrString, Options.PrimaryYAxis.YMax)
- else
- Exit;
-
- // Fire event so the application can save this new Options.PrimaryYAxis.YMax value
- if Assigned(FOnYAxisClick) then
- FOnYAxisClick(Self);
-
- //XXX AutoFormatGraph; BAD CODE REMOVED. Wpostma. Call PlotGraph instead.
- InternalPlotGraph;
- Invalidate;
-end;
-
-// NEW: X Axis Header has to move to make room if there is a horizontal
-// X axis legend:
-procedure TJvChart.MyXHeader(ACanvas: TCanvas; StrText: string);
-var
- X, Y, H: Integer;
-begin
- if StrText = '' then
- exit;
-
- MyAxisFont(ACanvas);
- H := ACanvas.TextHeight(StrText); // Height of labels
-
- MyAxisTitleFont(ACanvas, false);
- Y := Options.YStartOffset + Options.YEnd + H + X_TITLE_LABEL_DISTANCE;
- if Options.Legend = clChartLegendBelow then
- begin
- { left aligned X Axis Title, right after the legend itself}
- X := Options.FXLegendHoriz + 32;
- MyLeftTextOut(ACanvas, X, Y, StrText);
- end
- else
- begin
- { center title within range covered by x axis }
- X := (Options.XStartOffset + Options.XEnd) div 2;
- MyCenterTextOut(ACanvas, X, Y, StrText);
- end;
-end;
-
-procedure TJvChart.MyYHeader(ACanvas: TCanvas; StrText: string);
-var
- WD, Vert, Horiz: Integer;
-begin
- if Length(StrText) = 0 then
- Exit;
-
- ACanvas.Brush.Color := Color;
- MyAxisTitleFont(ACanvas, true);
-
- if Options.XStartOffset > 10 then
- begin
- WD := ACanvas.TextWidth(StrText);
- //Vert := Options.YStartOffset + WD; // top-aligned
- Vert := Max(0, Options.YStartOffset + (Options.YEnd + WD) div 2); // centered
- Horiz := 2;
- MyLeftTextOut(ACanvas, Horiz, Vert, StrText, true);
- end;
-// MyAxisFont(ACanvas);
-end;
-
-
-{***************************************************************************}
-{ MOUSE FUNCTIONS AND PROCEDURES }
-{***************************************************************************}
-
-function TJvChart.MouseToXValue(X: Integer): Integer;
-var
- XPixelGap: Double;
-begin
- XPixelGap := ((Options.XEnd - Options.XStartOffset) / Options.XValueCount);
- if XPixelGap > 0.001 then
- begin
- Result := Round(((X - 1) - Options.XStartOffset) / (XPixelGap));
- if (Result >= Data.ValueCount - 1) then
- Result := Data.ValueCount - 1
- else
- if Result < 0 then
- Result := 0;
- end
- else
- Result := 0; // can't figure it out.
-end;
-
-function TJvChart.MouseToYValue(Y: Integer): Double;
-begin
- with FOptions.PrimaryYAxis do
- begin
- //Y = (YOrigin - (((Result - YMin) / YGap) * YPixelGap))
-
- Result := -1 * (((Y / YPixelGap) * YGap) - ((YOrigin / YPixelGap) * YGap) - YMin);
-
- if Result < YMin then
- Result := YMin
- else
- if Result > YMax then
- Result := YMax;
- end;
-end;
-
-procedure TJvChart.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
-begin
- Screen.Cursor := crDefault;
- inherited MouseUp(Button, Shift, X, Y);
-
- if Options.MouseDragObjects then
- begin
- if Assigned(FDragFloatingMarker) then
- begin
- FDragFloatingMarker.FDragging := False;
- // Solve for X Position etc.
- FDragFloatingMarker.XPosition := MouseToXValue(X);
-
- FDragFloatingMarker.YPosition := MouseToYValue(Y);
- //OutputDebugString(PChar( 'End Mouse Drag Floating Object at '+InTToStr(FDragFloatingMarker.XPosition)+','+FloatToStr(FDragFloatingMarker.YPosition)) );
- if Assigned(FOnEndFloatingMarkerDrag) then
- FOnEndFloatingMarkerDrag(Self, FDragFloatingMarker);
-
- FDragFloatingMarker := nil;
- Invalidate;
- Exit;
- end;
- end;
-
- if FStartDrag then
- begin
- Options.LegendWidth := Options.LegendWidth + (FMouseDownX - X);
- Options.XEnd := Options.XEnd - (FMouseDownX - X);
- InternalPlotGraph;
- end;
- if FMouseLegend then
- begin
- InternalPlotGraph;
- FMouseLegend := False;
- end;
- FStartDrag := False;
- Invalidate;
-end;
-
-procedure TJvChart.MouseMove(Shift: TShiftState; X, Y: Integer); //override;
-begin
- inherited MouseMove(Shift, X, Y);
- if Assigned(FDragFloatingMarker) then
- begin
- if FDragFloatingMarker.XDraggable then
- begin
- if X < Options.XStartOffset then
- X := Options.XStartOffset;
- if X > Options.XEnd then
- X := Options.XEnd;
- FDragFloatingMarker.FRawXPosition := X;
- end;
- if FDragFloatingMarker.YDraggable then
- if Y > FXAxisPosition then
- Y := FXAxisPosition;
-
- if Y < Options.YStartOffset then
- Y := Options.YStartOffset;
-
- FDragFloatingMarker.FRawYPosition := Y;
-
- Self.Invalidate; // Repaint control LATER ! .. like a PostMessage(WM_PAINT)
- //Self.Repaint; // much more CPU intensive, but smoother.
- end;
-
-end;
-
-procedure TJvChart.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
-var
- XPixelGap: Double;
- I: Integer;
- // YPixelGap: Double; // not used (ahuser)
- Marker: TJvChartFloatingMarker;
-begin
- inherited MouseDown(Button, Shift, X, Y);
-
- if Options.MouseDragObjects then
- begin
- if not Assigned(FDragFloatingMarker) then
- begin
- for I := 0 to FFloatingMarker.Count - 1 do
- begin
- Marker := GetFloatingMarker(I);
- if not Marker.Visible then
- Continue;
- if not (Marker.XDraggable or Marker.YDraggable) then
- Continue;
- if (Abs(X - Marker.FRawXPosition) < (Options.MarkerSize * 2)) and
- ((Marker.Marker = pmkNone) or (Abs(Y - Marker.FRawYPosition) < Options.MarkerSize * 2)) then
- begin
- FDragFloatingMarker := Marker;
- FDragFloatingMarker.FDragging := True;
- //OutputDebugString('Begin Mouse Drag Floating Object');
- if Assigned(FOnBeginFloatingMarkerDrag) then
- FOnBeginFloatingMarkerDrag(Self, FDragFloatingMarker);
- Exit;
- end;
- end;
- end;
-
- end;
-
- if Options.MouseEdit then
- begin
- if X < Options.XStartOffset then
- begin
- EditYScale;
- Exit;
- end
- else
- // New: Don't let end user mess with title, if we
- // provide our own way to set the title or title options,
- // however, if Options.MouseEdit is on, they can still set the
- // scale via mouse clicking.
- if (Y < Options.YStartOffset) and not Assigned(FOnTitleClick) then
- begin
- EditHeader;
- Exit;
- end;
-
- if (Y > Options.YStartOffset + Options.YEnd) and not Assigned(FOnXAxisClick) then
- begin
- EditXHeader;
- Exit;
- end;
- end;
-
- if X < Options.XStartOffset then
- begin
- // Just fire the Y axis clicked event, don't popup the editor
- if Assigned(FOnYAxisClick) then
- begin
- FOnYAxisClick(Self);
- Exit;
- end;
- end
- else
- if Y < Options.YStartOffset then
- if Assigned(FOnTitleClick) then
- FOnTitleClick(Self);
- // New: Click on bottom area of chart (X Axis) can be defined by
- // user of the component to do something.
- if Assigned(FOnXAxisClick) then
- if (Y > Options.YEnd) and (X > Options.XStartOffset) then
- begin
- FOnXAxisClick(Self);
- Exit;
- end;
- if Assigned(FOnAltYAxisClick) then
- if (Y < Options.YEnd) and (X > Options.XEnd) then
- FOnAltYAxisClick(Self);
-
- if Options.MouseInfo then
- begin
- FStartDrag := False;
- FMouseDownX := X;
- FMouseDownY := Y;
- if (Y > Options.YStartOffset) and
- (Y < Options.YStartOffset + Options.YEnd) and
- (X > Options.XStartOffset) and
- (X < Options.XStartOffset + Options.XEnd + 10) then
- begin
- {Legend resize...}
- if X > (Options.XStartOffset + Options.XEnd) - 5 then
- begin
- FStartDrag := True;
- Screen.Cursor := crSizeWE;
- end;
- {Inside the actual graph...}
- if (X <= (Options.XStartOffset + Options.XEnd) - 5) and
- (Options.ChartKind <> ckChartPieChart) and
- (Options.ChartKind <> ckChartDeltaAverage) then
- begin
- XPixelGap := ((Options.XEnd - Options.XStartOffset) / (Options.XValueCount + 1));
- //if XPixelGap <1 then
- // XPixelGal := 1;
- if XPixelGap > 0.001 then
- FMouseValue := Round((X - Options.XStartOffset) / (XPixelGap))
- else
- FMouseValue := 0; // can't figure it out.
-
- case Options.ChartKind of
- ckChartBar, ckChartBarAverage:
- if Options.PenCount = 1 then {check for Pen count}
- FMousePen := Round(((X + (XPixelGap / 2)) -
- (Options.XStartOffset +
- Options.XOrigin * XPixelGap +
- XPixelGap * FMouseValue)) /
- Round(XPixelGap / (Options.PenCount + 0.1)) + 0.1)
- else
- FMousePen := Round(((X + (XPixelGap / 2)) -
- (Options.XStartOffset +
- Options.XOrigin * XPixelGap +
- XPixelGap * FMouseValue)) /
- Round(XPixelGap / (Options.PenCount + 0.5)) + 0.5);
- ckChartStackedBar, ckChartLine, ckChartStackedBarAverage:
- FMousePen := 0;
- end;
- if (FMouseValue > Options.XValueCount) or (FMouseValue < 0) then
- FMouseValue := 0;
- if FMousePen > Options.PrimaryYAxis.YDivisions then
- FMousePen := 0;
-
- // New: Allow user to do custom hints, or else do other things
- // when a chart is clicked.
- if Assigned(FOnChartClick) then
- begin
- FMouseDownShowHint := False;
- FMouseDownHintBold := False;
- // This event can handle chart clicks on data area only.
- if X <= Options.XEnd then
- FOnChartClick(Self, Button, Shift, X, Y, FMouseValue,
- FMousePen, FMouseDownShowHint,
- FMouseDownHintBold, FMouseDownHintStrs);
- end
- else
- begin
- if Button = mbLeft then
- begin
- FMouseDownShowHint := True;
- FMouseDownHintBold := True;
- AutoHint;
- end
- else
- FMouseDownShowHint := False; { don't show }
- end;
-
- if (FMouseDownHintStrs.Count > 0) and FMouseDownShowHint then
- ShowMouseMessage(X, Y);
- end;
- end;
- end;
-end;
-
-procedure TJvChart.SetCursorPosition(Pos: Integer);
-begin
- FCursorPosition := Pos;
- Invalidate; // repaint!
-end;
-
-procedure TJvChart.DisplayBars; // NEW 2007!
-begin
- DrawHorizontalBars;
- DrawVerticalBars;
-end;
-
-{ make list of 'PenName=Value' strings for each pen.. }
-
-procedure TJvChart.AutoHint; // Make the automatic hint message showing all pens and their values.
-var
- I: Integer;
- Str: string;
- Val: Double;
-begin
- FMouseDownHintStrs.Clear;
-
- if Options.XAxisDateTimeMode then
- begin
- if Length(Options.DateTimeFormat) = 0 then
- Str := DateTimeToStr(FData.GetTimestamp(FMouseValue))
- else
- Str := FormatDateTime(Options.DateTimeFormat, FData.GetTimestamp(FMouseValue));
-
- FMouseDownHintStrs.Add(Str);
- end
- else
- if Options.XLegends.Count > FMouseValue then
- FMouseDownHintStrs.Add(Options.XLegends[FMouseValue]);
-
- for I := 0 to Options.PenCount - 1 do
- begin
- if Options.PenLegends.Count <= I then
- Break; // Exception fixed. WP
- Str := Options.PenLegends[I];
- Val := FData.Value[I, FMouseValue];
- if Length(Str) = 0 then
- Str := IntToStr(I + 1);
- Str := Str + ' : ';
- if IsNaN(Val) then
- Str := Str + RsNA
- else
- begin
- Str := Str + FloatToStrF(Val, ffFixed, REALPREC, 3);
- if Options.PenUnit.Count > I then
- Str := Str + ' ' + Options.PenUnit[I];
- end;
-
- FMouseDownHintStrs.Add(Str);
- {$IFDEF DEBUGINFO_ON}
- OutputDebugString(PChar('TJvChart.AutoHint: ' + Str));
- {$ENDIF DEBUGINFO_ON}
- end;
-end;
-
-(* orphaned
-
- {We will show some Double values...}
-if FMousePen = 0 then
-begin
-{show all values in the Pen...}
-nLineCount := Options.PenCount;
-nHeight := nLineH * (nLineCount + 2);
-if Options.XLegends.Count > FMouseValue then
-strMessage1 := Options.XLegends[FMouseValue]
-else
-strMessage1 := '';
-strMessage2 := '-';
-if nWidth < ChartCanvas.TextWidth(strMessage1) then
-nWidth := ChartCanvas.TextWidth(strMessage1);
-end
-else
-begin
-nLineCount := 1;
-nHeight := nLineH * (nLineCount + 2);
-strMessage1 := Options.XLegends[FMouseValue];
-if nWidth < ChartCanvas.TextWidth(strMessage1) then
-nWidth := ChartCanvas.TextWidth(strMessage1);
-if FMousePen > 0 then
-strMessage2 := Options.PenLegends[FMousePen];
-if ChartCanvas.TextWidth(strMessage2) > nWidth then
-nWidth := ChartCanvas.TextWidth(strMessage2);
-strMessage3 := FloatToStrF(FData.Value[FMousePen, FMouseValue], ffFixed, REALPREC, 3);
-end;
-
-*)
-
-{ ShowMouseMessage can invoke an OnChartClick event, and/or
-shows hint boxes, etc. }
-
-procedure TJvChart.ShowMouseMessage(X, Y: Integer);
-var
- nWidth: Integer;
- nHeight: Integer;
- nLineH: Integer;
- nLineCount: Integer;
- I: Integer;
- StrWidth, StrHeight: Integer;
- ACanvas: TCanvas;
-begin
- ACanvas := GetChartCanvas({floating}true);
- ACanvas.Font.Color := Font.Color; // March 2004 Fixed.
-
- // scan and set nWidth,nLineH
- nWidth := 100; // minimum 100 pixel hint box width.
- nLineH := 8; // minimum 8 pixel line height for hints.
- nLineCount := FMouseDownHintStrs.Count;
-
- for I := 0 to nLineCount - 1 do
- begin
- StrWidth := ACanvas.TextWidth(FMouseDownHintStrs[I]);
- if StrWidth > nWidth then
- nWidth := StrWidth;
- StrHeight := ACanvas.TextHeight(FMouseDownHintStrs[I]);
- if StrHeight > nLineH then
- nLineH := StrHeight;
- end;
-
- // bump height of text in hint box,
- // leaving a little extra pixel space between rows.
- nLineH := Round(nLineH * 1.07) + 1;
-
- {RsNoValuesHere}
- if FMouseDownHintStrs.Count = 0 then
- begin
- StrWidth := ACanvas.TextWidth(RsNoValuesHere);
- if StrWidth > nWidth then
- nWidth := StrWidth;
- MyColorRectangle(ACanvas, jvChartShadowColorIndex, X + 3, Y + 3, X + nWidth + 3, Y + nLineH + 3);
- MyColorRectangle(ACanvas, jvChartHintColorIndex, X, Y, X + nWidth, Y + nLineH);
- ACanvas.Font.Color := Self.Font.Color;
- MyLeftTextOutHint(ACanvas, X + 2, Y, RsNoValuesHere);
- FMouseLegend := True;
- Exit;
- end;
-
- // Get hint box height/width, size to contents:
- nWidth := nWidth + 25;
- nHeight := nLineH * nLineCount + 8;
-
- // keep hint from clipping at bottom and right.
- if (Y + nHeight) > Self.Height then
- Y := (Self.Height - nHeight);
- if (X + nWidth) > Self.Width then
- X := (Self.Width - nWidth);
-
- // Draw hint box:
- MyColorRectangle(ACanvas, jvChartShadowColorIndex, X + 3, Y + 3, X + nWidth + 3, Y + nHeight + 3);
- MyColorRectangle(ACanvas, jvChartHintColorIndex, X, Y, X + nWidth, Y + nHeight);
-
- //MyLeftTextOut( ACanvas, X + 3, Y + 3, 'Foo');
-
- // Draw text inside the hint box:
- ACanvas.Font.Color := Self.Font.Color;
- //ACanvas.Font.Style :=
-
- if FMouseDownHintBold then
- ACanvas.Font.Style := [fsBold];
-
- for I := 0 to nLineCount - 1 do
- begin
- if (I = 1) and FMouseDownHintBold then
- ACanvas.Font.Style := [];
- MyLeftTextOutHint(ACanvas, X + 2, 4 + Y + (I * nLineH), FMouseDownHintStrs[I]); // draw text for each line.
- end;
-
- FMouseLegend := True;
-
- //Invalidate; //removed to solve painting glitch.
- //ResizeChartCanvas; // removed to solve painting glitch.
-end;
-
-{***************************************************************************}
-{ PIE FUNCTIONS AND PROCEDURES }
-{***************************************************************************}
-
-procedure TJvChart.GraphPieChart(NPen: Integer);
-var
- nSize: Integer;
- I: Integer;
- nLast: Integer;
- nXExtra: Integer;
- nSum: Double;
- n100Sum: Double;
- nP: Double;
- ACanvas: TCanvas;
-begin
- ACanvas := GetChartCanvas(false);
- ClearScreen;
-
- {Main Header}
- MyHeader(ACanvas, Options.Title);
- MyPieLegend(NPen);
- if Options.XEnd < Options.YEnd then
- begin
- nSize := Options.XEnd;
- nXExtra := 0;
- end
- else
- begin
- nSize := Options.YEnd;
- nXExtra := Round((Options.XEnd - Options.YEnd) / 2);
- end;
- {Count total sum...}
- n100Sum := 0;
- for I := 1 to MAX_VALUES do
- n100Sum := n100Sum + FData.Value[NPen, I];
- {Show background pie....}
- SetRectangleColor(ACanvas, jvChartAxisColorIndex); {black...}
- MyPiePercentage(Options.XStartOffset + nXExtra + 2,
- Options.YStartOffset + 2, nSize, 100);
- {Show pie if not zero...}
- if n100Sum <> 0 then
- begin
- nSum := n100Sum;
- nLast := Options.XValueCount + 1;
- if nLast > MAX_VALUES then
- nLast := MAX_VALUES;
- for I := nLast downto 2 do
- begin
- nSum := nSum - FData.Value[NPen, I];
- nP := 100 * (nSum / n100Sum);
- SetRectangleColor(ACanvas, I - 1);
- MyPiePercentage(Options.XStartOffset + nXExtra,
- Options.YStartOffset, nSize, nP);
- end;
- end;
-end;
-
-procedure TJvChart.MyPiePercentage(X1, Y1, W: Longint; NPercentage: Double);
-var
- nOriginX, nOriginY: Longint;
- nGrade: Double;
- nStartGrade: Double;
- X, Y: Double;
- nLen: Double;
-begin
- nOriginX := Round((W - 1.01) / 2) + X1;
- nOriginY := Round((W - 1.01) / 2) + Y1;
- nGrade := (NPercentage / 100) * 2 * Pi;
- nStartGrade := (2 / 8) * 2 * Pi;
- nLen := Round((W - 1) / 2);
- X := Cos(nStartGrade + nGrade) * nLen;
- Y := Sin(nStartGrade + nGrade) * nLen;
- MyPie(GetChartCanvas(false), X1, Y1, X1 + W, Y1 + W,
- nOriginX, Y1, nOriginX + Round(X), nOriginY - Round(Y));
-end;
-
-procedure TJvChart.MyPieLegend(NPen: Integer);
-var
- I: Integer;
- nTextHeight: Longint;
- {nChars: Integer;}// not used (ahuser)
- XLegendStr: string;
- ACanvas: TCanvas;
-begin
- ACanvas := GetChartCanvas(false);
- {Count how many characters to show in the separate legend}
- {nChars := Round(Options.LegendWidth / ChartCanvas.TextWidth('1'));}// not used (ahuser)
- {Decrease the value due to the color box shown}
- {if (nChars>4) then nChars := nChars-4;}// not used (ahuser)
-
- MySmallGraphFont(ACanvas);
- nTextHeight := Round(CanvasMaxTextHeight(ACanvas) * 1.2);
-
- // Pie Chart Right Side Legend.
- if Options.Legend = clChartLegendRight then
- begin
- MyColorRectangle(ACanvas, 0,
- Options.XStartOffset + Options.XEnd + 6,
- Options.YStartOffset + 1 * nTextHeight + 6 + 4,
- Options.XStartOffset + Options.XEnd + Options.LegendWidth + 6,
- Options.YStartOffset + (Options.XValueCount + 1) * nTextHeight + 6 + 4);
- MyColorRectangle(ACanvas, jvChartPaperColorIndex,
- Options.XStartOffset + Options.XEnd + 3,
- Options.YStartOffset + 1 * nTextHeight + 3 + 4,
- Options.XStartOffset + Options.XEnd + Options.LegendWidth + 3,
- Options.YStartOffset + (Options.XValueCount + 1) * nTextHeight + 3 + 4);
- for I := 1 to Options.XValueCount do
- begin
- DrawPenColorBox(ACanvas, I, ACanvas.TextWidth('12') - 2, nTextHeight - 4,
- Options.XStartOffset + Options.XEnd + 7,
- Options.YStartOffset + I * nTextHeight + 9);
- SetFontColor(ACanvas, jvChartAxisColorIndex);
- if I - 1 < Options.XLegends.Count then
- XLegendStr := Options.XLegends[I - 1]
- else
- XLegendStr := IntToStr(I);
- MyLeftTextOut(ACanvas, Options.XStartOffset + Options.XEnd + 7 + ACanvas.TextWidth('12'),
- Options.YStartOffset + I * nTextHeight + 7,
- XLegendStr);
- end;
- end;
-end;
-
-// Used in line charting as a Marker kind:
-
-procedure TJvChart.PlotSquare(ACanvas: TCanvas; X, Y: Integer);
-begin
- MyPolygon(ACanvas, [Point(X - Options.MarkerSize, Y - Options.MarkerSize),
- Point(X + Options.MarkerSize, Y - Options.MarkerSize),
- Point(X + Options.MarkerSize, Y + Options.MarkerSize),
- Point(X - Options.MarkerSize, Y + Options.MarkerSize)]);
-end;
-
-// Used in line charting as a Marker kind:
-
-procedure TJvChart.PlotDiamond(ACanvas: TCanvas; X, Y: Integer);
-begin
- MyPolygon(ACanvas, [Point(X, Y - Options.MarkerSize),
- Point(X + Options.MarkerSize, Y),
- Point(X, Y + Options.MarkerSize),
- Point(X - Options.MarkerSize, Y)]);
-end;
-
-procedure TJvChart.PlotFilledDiamond(ACanvas: TCanvas; X, Y: Integer);
-begin
- with ACanvas.Brush do
- begin
- Style := bsSolid;
- Color := ACanvas.Pen.Color;
- PlotDiamond(ACanvas, X, Y);
- Style := bsClear;
- end;
-end;
-
-// Used in line charting as a Marker kind:
-
-procedure TJvChart.PlotCircle(ACanvas: TCanvas; X, Y: Integer);
-begin
- ACanvas.Pen.Style := psSolid;
- ACanvas.Ellipse(X - Options.MarkerSize,
- Y - Options.MarkerSize,
- X + Options.MarkerSize,
- Y + Options.MarkerSize); // Marker Circle radius 3.
-end;
-
-// Used in line charting as a Marker kind:
-
-procedure TJvChart.PlotCross(ACanvas: TCanvas; X, Y: Integer);
-begin
- MyDrawLine(ACanvas, X - Options.MarkerSize, Y, X + Options.MarkerSize, Y);
- MyDrawLine(ACanvas, X, Y - Options.MarkerSize, X, Y + Options.MarkerSize);
-end;
-
-procedure TJvChart.ClearScreen;
-var
- ACanvas: TCanvas;
-begin
- ACanvas := GetChartCanvas(false);
- {Clear screen}
- SetLineColor(ACanvas, jvChartPaperColorIndex);
- // Fishy:
- MyColorRectangle(ACanvas, jvChartPaperColorIndex, 0, 0,
- // XXX The point here is to exceed the edges, wipe it all, thus the 3* and 5* multipliers.
- 3 * Options.XStartOffset + Options.XEnd + Options.LegendWidth,
- 5 * Options.YStartOffset + Options.YEnd);
- SetRectangleColor(ACanvas, jvChartAxisColorIndex);
- SetLineColor(ACanvas, jvChartAxisColorIndex);
-end;
-
-{NEW chart type!!!}
-
-procedure TJvChart.GraphDeltaAverage;
-var
- XPixelGap: Longint;
- YPixelGap: Longint;
- lXOrigin: Longint;
- lYOrigin: Longint;
- I, J: Longint;
- TempYOrigin: Longint;
- ACanvas: TCanvas;
-begin
- ACanvas := GetChartCanvas(false);
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
-
- {new type of chart...}
- ClearScreen;
-
- {Check graph values and correct if wrong. Actually not needed if there are no bugs}
-// if (Options.PrimaryYAxis.YDivisions>MAX_Y_LEGENDS) then
-// Options.PrimaryYAxis.YDivisions := MAX_Y_LEGENDS;
- if Options.PrimaryYAxis.YDivisions = 0 then
- Options.PrimaryYAxis.YDivisions := 1;
- if Options.XValueCount > MAX_VALUES then
- Options.XValueCount := MAX_VALUES;
- if Options.XValueCount = 0 then
- Options.XValueCount := 1;
- if Options.PenCount > MAX_PEN then
- Options.PenCount := MAX_PEN;
- // if Options.PrimaryYAxis.YGap = 0 then
- // Options.PrimaryYAxis.YGap := 1;
-
- XPixelGap := Round((Options.YEnd - Options.YStartOffset) /
- (Options.XValueCount));
- YPixelGap := Round((Options.XEnd - Options.XStartOffset) /
- (Options.PrimaryYAxis.YDivisions + 1)); // SPECIALIZED.
-
- TempYOrigin := Options.YOrigin;
- Options.YOrigin := Options.PrimaryYAxis.YDivisions div 2;
-
- lYOrigin := Options.XStartOffset + (YPixelGap * Options.YOrigin);
- lXOrigin := Options.YStartOffset;
-
- {Create texts for Y-axis}
-// Options.PrimaryYAxis.YLegends.Clear;
-// for I := 0 to MAX_Y_LEGENDS-1 do
- // Options.PrimaryYAxis.YLegends.Add( IntToStr(Round(((I-1)-Options.YOrigin)*Options.PrimaryYAxis.YGap)) );
-
- {Y-axis legends and lines...}
- MyAxisFont(ACanvas);
- for I := 1 to Options.PrimaryYAxis.YDivisions + 1 do
- begin
- if I >= Options.PrimaryYAxis.YLegends.Count then
- Exit;
- MyLeftTextOut(ACanvas,
- lYOrigin + (YPixelGap * ((I - 1) - Options.YOrigin)),
- lXOrigin + XPixelGap * Options.XValueCount + 2,
- Options.PrimaryYAxis.YLegends[I]);
- MyDrawDotLine(ACanvas,
- lYOrigin - (YPixelGap * ((I - 1) - Options.YOrigin)),
- lXOrigin,
- lYOrigin - (YPixelGap * ((I - 1) - Options.YOrigin)),
- lXOrigin + (XPixelGap * (Options.XValueCount)));
- end;
-
- {Draw Y-axis}
- ACanvas.MoveTo(Options.XStartOffset, lXOrigin);
- MyAxisLineTo(ACanvas, Options.XEnd, lXOrigin);
- {Draw second Y-axis}
- ACanvas.MoveTo(Options.XStartOffset, lXOrigin + XPixelGap * Options.XValueCount + 1);
- MyAxisLineTo(ACanvas, Options.XEnd, lXOrigin + XPixelGap * Options.XValueCount + 1);
- {Draw X-axis}
- ACanvas.MoveTo(lYOrigin, lXOrigin);
- MyAxisLineTo(ACanvas, lYOrigin, lXOrigin + XPixelGap * Options.XValueCount + 1);
-
- {X-axis legends...}
- GraphXAxisLegend;
-
- {Main Header}
- MyHeader(ACanvas, Options.Title);
-
- {X axis header}
- MyXHeader(ACanvas, Options.XAxisHeader);
-
- // Now draw the delta average...
- for I := 0 to Options.PenCount - 1 do
- for J := 0 to Options.XValueCount - 1 do
- if Options.PenCount = 1 then
- MyColorRectangle(ACanvas, I,
- lYOrigin,
- lXOrigin + J * XPixelGap + (I) * Round(XPixelGap / (Options.PenCount + 0.1)) - XPixelGap,
- lYOrigin + Round(((FData.Value[I, J] - Options.AverageValue[J]) /
- Options.PrimaryYAxis.YGap) * YPixelGap),
- lXOrigin + J * XPixelGap + (I + 1) * Round(XPixelGap / (Options.PenCount + 0.1)) - XPixelGap)
- else
- MyColorRectangle(ACanvas, I,
- lYOrigin,
- lXOrigin + J * XPixelGap + (I) * Round(XPixelGap / (Options.PenCount + 0.5)) - XPixelGap,
- lYOrigin + Round(((FData.Value[I, J] - Options.AverageValue[J]) /
- Options.PrimaryYAxis.YGap) * YPixelGap),
- lXOrigin + J * XPixelGap + (I + 1) * Round(XPixelGap / (Options.PenCount + 0.5)) - XPixelGap);
- Options.YOrigin := TempYOrigin;
-end;
-
-{****************************************************************************}
-{ Device dependent functions for the rest of this module...check for printer }
-{ or check for metafile output! }
-{****************************************************************************}
-
- (*
-{ !!warning: uses Win32 only font-handle stuff!!}
-procedure TJvChart.MakeVerticalFont;
-begin
- if Ord(FYFontHandle) <> 0 then
- DeleteObject(FYFontHandle); // delete old object
- // Clear the contents of FLogFont
- FillChar(FYLogFont, SizeOf(TLogFont), 0);
- // Set the TLOGFONT's fields - Win32 Logical Font Details.
- with FYLogFont do
- begin
- lfHeight := Abs(Font.Height) + 2;
- lfWidth := 0; //Font.Width;
- lfEscapement := 900; // 90 degree vertical rotation
- lfOrientation := 900; // not used.
- lfWeight := FW_BOLD; //FW_HEAVY; // bold, etc
- lfItalic := 1; // no
- lfUnderline := 0; // no
- lfStrikeOut := 0; // no
- lfCharSet := ANSI_CHARSET; // or DEFAULT_CHARSET
- lfOutPrecision := OUT_TT_ONLY_PRECIS; //Require TrueType!
- // OUT_DEFAULT_PRECIS;
- // OUT_STRING_PRECIS, OUT_CHARACTER_PRECIS, OUT_STROKE_PRECIS,
- // OUT_TT_PRECIS, OUT_DEVICE_PRECIS, OUT_RASTER_PRECIS,
- // OUT_TT_ONLY_PRECIS
-
- lfClipPrecision := CLIP_DEFAULT_PRECIS;
- lfQuality := DEFAULT_QUALITY;
- lfPitchAndFamily := DEFAULT_PITCH or FF_DONTCARE;
- StrPCopy(lfFaceName, Font.Name);
- end;
-
- // Retrieve the requested font
- FYFontHandle := CreateFontIndirect(FYLogFont);
- Assert(Ord(FYFontHandle) <> 0);
- // Assign to the Font.Handle
- //Font.Handle := FYFont; // XXX DEBUG
- //pbxFont.Refresh;
- FYFont := TFont.Create;
- FYFont.Assign(Font);
- FYFont.Color := Options.AxisFont.Color;
- FYFont.Handle := FYFontHandle;
-end;
-*)
-
-
-procedure TJvChart.MyHeader(ACanvas: TCanvas; StrText: string);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
-
- MyHeaderFont(ACanvas);
- MyCenterTextOut(ACanvas,
- (Options.XStartOffset + Round(Options.XEnd)) div 2,
- TITLE_MARGIN,
- StrText
- );
- MyAxisFont(ACanvas);
-end;
-
-procedure TJvChart.MySmallGraphFont(ACanvas: TCanvas);
-begin
- ACanvas.Brush.Color := Options.PaperColor; // was hard coded to clWhite.
- ACanvas.Font.Assign(Options.LegendFont);
-end;
-
-procedure TJvChart.MyAxisFont(ACanvas: TCanvas);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- Assert(Assigned(ACanvas.Font));
- Assert(Assigned(Options));
- ACanvas.Brush.Color := Options.PaperColor; // was hard coded to clWhite.
- ACanvas.Font.Assign(Options.AxisFont);
-end;
-
-procedure TJvChart.MyAxisTitleFont(ACanvas: TCanvas; Vertical: Boolean);
-const
- ORIENTATION: Array[boolean] of Integer = (0, 900);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- Assert(Assigned(ACanvas.Font));
- Assert(Assigned(Options));
- ACanvas.Brush.Color := Options.PaperColor; // was hard coded to clWhite.
- ACanvas.Font.Assign(Options.AxisTitleFont);
- ACanvas.Font.Orientation := ORIENTATION[Vertical];
-end;
-
-
-(*
-{ !!warning: uses Win32 only font-handle stuff!!}
-procedure TJvChart.MyGraphVertFont(ACanvas: TCanvas);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
-
- if Ord(FYFontHandle) = 0 then
- MakeVerticalFont;
- ACanvas.Font.Assign(FYFont); //Handle := FYFontHnd;
- if not PrintInSession then
- Assert(ACanvas.Font.Handle = FYFontHandle);
-end;
-*)
-
-procedure TJvChart.MyHeaderFont(ACanvas: TCanvas);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- Assert(Assigned(Options));
- ACanvas.Brush.Color := Options.PaperColor; //was clWhite;
- ACanvas.Font.Assign(Options.HeaderFont);
-end;
-
-procedure TJvChart.MyPenLineTo(ACanvas: TCanvas; X, Y: Integer);
-begin
- ACanvas.Pen.Width := Options.PenLineWidth;
- ACanvas.LineTo(X, Y);
- ACanvas.Pen.Width := 1;
-end;
-
-procedure TJvChart.MyAxisLineTo(ACanvas: TCanvas; X, Y: Integer);
-begin
- if Options.AxisLineWidth = 0 then
- Exit;
-
- ACanvas.Pen.Width := Options.AxisLineWidth;
- ACanvas.LineTo(X, Y);
- ACanvas.Pen.Width := 1;
-end;
-
-function TJvChart.MyTextHeight(ACanvas: TCanvas; StrText: string): Longint;
-begin
- Result := ACanvas.TextHeight(StrText);
-end;
-
-{ Text Left Aligned to X,Y boundary }
-
-procedure TJvChart.MyLeftTextOut(ACanvas: TCanvas; X, Y: Integer;
- const AText: string; Vertical: Boolean = false);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Brush.Color := Options.PaperColor; // non default paper color.
- {$IFDEF TEXT_BOX}
- ACanvas.Brush.Style := bsSolid;
- if Vertical then
- ACanvas.Rectangle(X, Y, X + ACanvas.TextHeight(AText), Y - ACanvas.TextWidth(AText))
- else
- ACanvas.Rectangle(X, Y, X + ACanvas.TextWidth(AText), Y + ACanvas.TextHeight(AText));
- ACanvas.Brush.Style := bsClear;
- {$ENDIF}
- ACanvas.TextOut(X, Y + 1, AText);
-end;
-
-procedure TJvChart.MyLeftTextOutHint(ACanvas: TCanvas; X, Y: Integer; const AText: string);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Brush.Color := Options.HintColor;
- {$IFDEF TEXT_BOX}
- ACanvas.Brush.Style := bsSolid;
- ACanvas.Rectangle(X, Y, X + ACanvas.TextWidth(AText), Y + ACanvas.TextHeight(AText));
- ACanvas.Brush.Style := bsClear;
- {$ENDIF}
- ACanvas.TextOut(X, Y + 1, AText);
-end;
-
-procedure TJvChart.MyCenterTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Brush.Color := Options.PaperColor; // non default paper color.
- X := X - ACanvas.TextWidth(AText) div 2;
- Y := Y + 1;
- {$IFDEF TEXT_BOX}
- ACanvas.Brush.Style := bsSolid;
- ACanvas.Rectangle(X, Y, X + ACanvas.TextWidth(AText), Y + ACanvas.TextHeight(AText));
- ACanvas.Brush.Style := bsClear;
- {$ENDIF}
- ACanvas.TextOut(X, Y, AText);
-end;
-
-procedure TJvChart.MyRightTextOut(ACanvas: TCanvas; X, Y: Integer; const AText: string);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Brush.Color := Options.PaperColor; // non default paper color.
- X := X - ACanvas.TextWidth(AText);
- Y := Y - ACanvas.TextHeight(AText) div 2;
- {$IFDEF TEXT_BOX}
- ACanvas.Brush.Style := bsSolid;
- ACanvas.Rectangle(X, Y, X + ACanvas.TextWidth(AText), Y + ACanvas.TextHeight(AText));
- ACanvas.Brush.Style := bsClear;
- {$ENDIF}
- ACanvas.TextOut(X, Y, AText);
-end;
-
-procedure TJvChart.MyRectangle(ACanvas: TCanvas; X, Y, X2, Y2: Integer);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Rectangle(X, Y, X2, Y2);
-end;
-
-(*Procedure TJvChart.MyShadowRectangle(Pen : Integer; X, Y, X2, Y2: Integer);
-begin
- SetRectangleColor(Shadow);
- ACanvas.Rectangle(X, Y, X2, Y2);
-end;*)
-
-procedure TJvChart.MyColorRectangle(ACanvas: TCanvas; Pen: Integer; X, Y, X2, Y2: Integer);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- SetRectangleColor(ACanvas, Pen);
- //OutputDebugString(PChar('MyColorRectangle X='+IntToStr(X)+' Y='+IntToStr(Y)+ ' X2='+IntToStr(X2)+ ' Y2='+IntToStr(Y2) ));
- ACanvas.Rectangle(X, Y, X2, Y2);
-end;
-
-procedure TJvChart.MyPie(ACanvas: TCanvas; X1, Y1, X2, Y2, X3, Y3, X4, Y4: Longint);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4);
-end;
-
-{Procedure TJvChart.MyArc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer);
-begin
- ACanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4);
-end;}// not used (ahuser)
-
-procedure TJvChart.MyPolygon(ACanvas: TCanvas; Points: array of TPoint);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Polygon(Points);
-end;
-
-{Procedure TJvChart.MyEllipse(X1, Y1, X2, Y2: Integer);
-begin
- ACanvas.Ellipse(X1, Y1, X2, Y2);
-end;}
-
-procedure TJvChart.MyDrawLine(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.MoveTo(X1, Y1);
- ACanvas.LineTo(X2, Y2);
-end;
-
-procedure TJvChart.MyDrawAxisMark(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- SetSolidLines(ACanvas);
- ACanvas.Pen.Width := 1; // always width 1
- ACanvas.MoveTo(X1, Y1);
- ACanvas.LineTo(X2, Y2);
-end;
-
-procedure TJvChart.MyDrawDotLine(ACanvas: TCanvas; X1, Y1, X2, Y2: Integer);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- SetDotLines(ACanvas);
- ACanvas.MoveTo(X1, Y1);
- ACanvas.LineTo(X2, Y2);
- SetSolidLines(ACanvas);
-end;
-
-{ (rom) not used
-function TJvChart.GetDefaultColorString(nIndex: Integer): string;
-begin
- if nIndex <= 10 then
- case nIndex of
- -2:
- Result := 'clWhite'; // MouseDownBox
- -1:
- Result := 'clWhite';
- 0:
- Result := 'clBlack';
- 1:
- Result := 'clLime';
- 2:
- Result := 'clBlue';
- 3:
- Result := 'clRed';
- 4:
- Result := 'clGreen';
- 5:
- Result := 'clMaroon';
- 6:
- Result := 'clOlive';
- 7:
- Result := 'clSilver';
- 8:
- Result := 'clTeal';
- 9:
- Result := 'clBlack';
- 10:
- Result := 'clAqua';
- end
- else
- Result := '$00888888';
-end;
-}
-
-procedure TJvChart.SetFontColor(ACanvas: TCanvas; Pen: Integer);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Font.Color := Options.PenColor[Pen];
-end;
-
-procedure TJvChart.SetRectangleColor(ACanvas: TCanvas; Pen: Integer);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- ACanvas.Brush.Color := Options.PenColor[Pen];
-end;
-
-procedure TJvChart.SetLineColor(ACanvas: TCanvas; Pen: Integer);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- Assert(Assigned(ACanvas.Pen));
- ACanvas.Pen.Color := Options.PenColor[Pen];
-end;
-
-procedure TJvChart.SetDotLines(ACanvas: TCanvas);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- Assert(Assigned(ACanvas.Pen));
- ACanvas.Pen.Style := psDot;
-end;
-
-procedure TJvChart.SetSolidLines(ACanvas: TCanvas);
-begin
- Assert(Assigned(ACanvas));
- Assert(Assigned(ACanvas.Brush));
- Assert(Assigned(ACanvas.Pen));
- ACanvas.Pen.Style := psSolid;
-end;
-
-procedure TJvChart.GraphToClipboard;
-begin
- {This works with bitmaps at least...how to do it as a metafile?}
- Clipboard.Assign(FPicture);
-end;
-
-{ PivotData: Pivot Data in Table. Formerly ChangeXValuesWithPen }
-
-procedure TJvChart.PivotData;
-var
- I, J: Integer;
- PenCount, XValueCount: Integer;
- TempData: TJvChartData;
- TempStrings: TStringList;
-begin
- TempData := TJvChartData.Create;
- PenCount := Options.PenCount;
- XValueCount := Options.XValueCount;
- try
- { Move data to temp }
- for I := 0 to PenCount - 1 do
- for J := 0 to XValueCount - 1 do
- TempData.Value[I, J] := FData.Value[I, J];
- FData.Clear;
- { copy back, pivot X/Y axis }
- for I := 0 to PenCount - 1 do
- for J := 0 to XValueCount - 1 do
- TempData.Value[I, J] := FData.Value[J, I];
-
- {swap labels}
- TempStrings := Options.FXLegends;
- Options.FXLegends := Options.FPenLegends;
- Options.FPenLegends := TempStrings;
-
- Options.XValueCount := PenCount;
- Options.PenCount := XValueCount;
-
- {recalc average}
- CountGraphAverage;
- InternalPlotGraph;
- Invalidate;
- finally
- TempData.Free;
- end;
-end;
-
-{FLOATING MARKERS: new Jan 2005 by WP }
-
-procedure TJvChart.DrawFloatingMarkers; { called from TJvChart.Paint! }
-var
- Marker, Marker2: TJvChartFloatingMarker;
- LineXPixelGap: Double;
- CaptionYPosition, TextWidth, TextHeight, VC, I: Integer;
- ACanvas: TCanvas;
-begin
- if csDesigning in ComponentState then
- Exit;
- if FFloatingMarker.Count = 0 then
- Exit;
- ACanvas := Self.GetChartCanvas({isFloating}true);
-
- VC := Options.XValueCount;
- if (VC < 2) then
- VC := 2;
- LineXPixelGap := ((Options.XEnd - 2) - Options.XStartOffset) / (VC - 1);
-
- {-- First loop through all and update their Raw X and Y Positions --}
- for I := 0 to FFloatingMarker.Count - 1 do
- begin
- Marker := GetFloatingMarker(I);
- if not Marker.Visible then
- Continue;
- if (Marker.XPosition < 0) or (Marker.XPosition >= VC) then
- Continue; // out of visible X range.
-
- // if following a pen, get the updated pen value:
- //if Marker.YPositionToPen>=0 then begin
- // Marker.YPosition := Self.Data.Value[Marker.YPositionToPen, Marker.XPosition];
- //end;
-
- // find Raw X,Y co-ordinates:
- if not Marker.FDragging then
- begin
- with FOptions.PrimaryYAxis do
- Marker.FRawYPosition := Trunc((YOrigin - (((Marker.YPosition - YMin) / YGap) * YPixelGap)));
- Marker.FRawXPosition := Round(XOrigin + Marker.XPosition * LineXPixelGap);
- end;
- end;
-
- {-- Now draw any connecting lines or vertical lines --}
- for I := 0 to FFloatingMarker.Count - 1 do
- begin
- Marker := GetFloatingMarker(I);
- if not Marker.Visible then
- Continue;
- if (Marker.XPosition < 0) or (Marker.XPosition >= VC) then
- Continue; // out of visible X range.
-
- // Draw connecting (rubberband) line:
- if (Marker.LineToMarker >= 0) and (Marker.FLineStyle <> psClear) then
- begin
- Marker2 := GetFloatingMarker(Marker.LineToMarker);
- ACanvas.Pen.Style := Marker.FLineStyle;
- ACanvas.Pen.Color := Marker.FLineColor;
- ACanvas.Pen.Width := Marker.FLineWidth;
- ACanvas.MoveTo(Marker.FRawXPosition, Marker.FRawYPosition);
- ACanvas.LineTo(Marker2.FRawXPosition, Marker2.FRawYPosition);
- end
- else
- if Marker.FLineVertical then
- begin
- // Vertical line along X position:
- ACanvas.Pen.Style := Marker.FLineStyle;
- ACanvas.Pen.Color := Marker.FLineColor;
- ACanvas.Pen.Width := Marker.FLineWidth;
- ACanvas.MoveTo(Marker.FRawXPosition, Options.YStartOffset);
- ACanvas.LineTo(Marker.FRawXPosition, FXAxisPosition - 1);
- end;
- end;
-
- {-- Now draw the markers themselves, we draw them LAST so they are ON TOP. --}
- MySmallGraphFont(ACanvas);
- for I := 0 to FFloatingMarker.Count - 1 do
- begin
- Marker := GetFloatingMarker(I);
- if not Marker.Visible then
- Continue;
- if (Marker.XPosition < 0) or (Marker.XPosition >= VC) then
- Continue; // out of visible X range.
- if Marker.Marker <> pmkNone then
- begin
- // Draw Marker:
- ACanvas.Pen.Color := Marker.FMarkerColor;
- PlotMarker(ACanvas, Marker.Marker, Marker.FRawXPosition, Marker.FRawYPosition);
- end;
-
- if Marker.Caption <> '' then
- begin
- TextHeight := ACanvas.TextHeight(Marker.Caption);
-
- CaptionYPosition := 0; // not used.
- case Marker.CaptionPosition of
- cpMarker:
- CaptionYPosition := Marker.FRawYPosition - Round(TextHeight * 1.4);
- cpXAxisBottom:
- CaptionYPosition := Options.YStartOffset + Options.YEnd + Round(TextHeight * 1.4);
- cpXAxisTop:
- CaptionYPosition := Trunc(XOrigin - Round(TextHeight * 1.4));
- cpTitleArea:
- CaptionYPosition := (Options.YStartOffset div 2) - (TextHeight div 2);
- end;
-
- if Marker.CaptionBoxed then
- begin
- TextWidth := ACanvas.TextWidth(Marker.Caption) + 10;
-
- ACanvas.Pen.Color := Marker.LineColor;
- ACanvas.Pen.Width := 1;
- ACanvas.Pen.Style := Marker.LineStyle;
- MyRectangle(ACanvas,
- Marker.FRawXPosition - TextWidth div 2,
- CaptionYPosition,
- Marker.FRawXPosition + TextWidth div 2,
- CaptionYPosition + TextHeight + TextHeight div 4);
- ACanvas.Pen.Style := psSolid;
- //MySmallGraphFont(ACanvas); <-redundant.
- //MyCenterTextOut(ACanvas, Marker.FRawXPosition, Options.FYStartOffset + Round(TextHeight / 4),
- // Marker.Caption);
- end;
-
- MyCenterTextOut(ACanvas, Marker.FRawXPosition, CaptionYPosition, Marker.Caption);
- end;
- end;
-end;
-
-function TJvChart.AddFloatingMarker: TJvChartFloatingMarker;
-begin
- Assert(Assigned(FFloatingMarker));
- Result := TJvChartFloatingMarker.Create(Self);
- Result.FIndex := FFloatingMarker.Count;
- FFloatingMarker.Add(Result);
-end;
-
-procedure TJvChart.DeleteFloatingMarker(Index: Integer);
-var
- I: Integer;
-begin
- Assert(Assigned(FFloatingMarker));
- if Assigned(FDragFloatingMarker) then
- FDragFloatingMarker := nil;
-
- FFloatingMarker.Delete(Index);
- for I := Index to FFloatingMarker.Count - 1 do
- with GetFloatingMarker(I) do
- begin
- FIndex := I; // update index.
- if LineToMarker = Index then
- LineToMarker := -1 // Disconnected now.
- else
- if LineToMarker > Index then
- LineToMarker := LineToMarker - 1; // Index changed.
- end;
- Invalidate;
-end;
-
-procedure TJvChart.DeleteFloatingMarkerObj(Marker: TJvChartFloatingMarker); // NEW 2007
-var
- I: Integer;
-begin
- for I := 0 to FFloatingMarker.Count - 1 do
- begin
- if TJvChartFloatingMarker(FFloatingMarker[I]) = Marker then
- begin
- DeletefloatingMarker(I);
- Exit;
- end;
- end;
-end;
-
-procedure TJvChart.CopyFloatingMarkers(Source: TJvChart);
-var
- I: Integer;
- NewMarker: TJvChartFloatingMarker;
-begin
- ClearFloatingMarkers;
- for I := 0 to Source.FloatingMarkerCount - 1 do
- begin
- NewMarker := Self.AddFloatingMarker;
- NewMarker.Assign(Source.GetFloatingMarker(I));
- end;
- Invalidate; // repaint!
-end;
-
-procedure TJvChart.ClearFloatingMarkers;
-begin
- if Assigned(FDragFloatingMarker) then
- FDragFloatingMarker := nil;
- FFloatingMarker.Clear;
-end;
-
-function TJvChart.GetFloatingMarker(Index: Integer): TJvChartFloatingMarker;
-begin
- Assert(Assigned(FFloatingMarker));
- Result := TJvChartFloatingMarker(FFloatingMarker[Index]);
-end;
-
-function TJvChart.GetHorizontalBar(index: integer): TJvChartHorizontalBar;
-begin
- // new 2009
- Assert(Assigned(FHorizontalBars));
- Result := TJvChartHorizontalBar(FHorizontalBars[Index]);
-
-end;
-
-function TJvChart.GetVerticalBar(index: integer): TJvChartVerticalBar;
-begin
-// new 2009
- Assert(Assigned(FVerticalBars));
- Result := TJvChartVerticalBar(FVerticalBars[Index]);
-end;
-
-function TJvChart.FloatingMarkerCount: Integer;
-begin
- Assert(Assigned(FFloatingMarker));
- Result := FFloatingMarker.Count;
-end;
-
-// NEW HORIZONTAL BAR AND VERTICAL BAR AND GRADIENT PAINTING METHODS (2007) - W.Postma.
-
-procedure TJvChart.DrawGradient; // new 2007
-var
- ACanvas: TCanvas;
- RawRect: TRect;
- VC: Integer;
-begin
- if csDesigning in ComponentState then
- Exit;
- if (Options.FGradientDirection = grNone) or (Options.PaperColor = Options.FGradientColor) then
- Exit;
- ACanvas := GetChartCanvas(false);
- VC := Max(1, Options.XValueCount);
- RawRect.Top := FOptions.YStartOffset;
- RawRect.Bottom := Trunc(YOrigin);
- RawRect.Left := Round(XOrigin);
- RawRect.Right := Round(Options.XStartOffset + Options.XPixelGap * VC) - 1;
- case Options.FGradientDirection of
- //grNone:
- // ;
- grUp:
- GradVertical(ACanvas, RawRect, Options.FGradientColor, Options.PaperColor);
- grDown:
- GradVertical(ACanvas, RawRect, Options.PaperColor, Options.FGradientColor);
- grLeft:
- GradHorizontal(ACanvas, RawRect, Options.PaperColor, Options.FGradientColor);
- grRight:
- GradHorizontal(ACanvas, RawRect, Options.FGradientColor, Options.PaperColor);
- end;
-end;
-
-{ Gradient bars - indicators on background of various vertical subranges }
-
-procedure TJvChart.DrawHorizontalBars; // new 2007
-var
- HB: TJvChartHorizontalBar;
- J: Integer;
- ACanvas: TCanvas;
- VC: Integer;
- RawRect: TRect;
- procedure CalcRawRect; // new april 2009
-begin
- with FOptions.PrimaryYAxis do
- if (YGap <> 0) then
- begin
- if IsNaN(HB.FYTop) then
- RawRect.Top := FOptions.YStartOffset
- else
- begin
- RawRect.Top := Trunc((YOrigin - (((HB.FYTop - YMin) / YGap) * YPixelGap)));
- if RawRect.Top < 0 then
- RawRect.Top := FOptions.YStartOffset;
- end;
-
- if IsNaN(HB.FYBottom) then
- RawRect.Bottom := Trunc(YOrigin)
- else
- begin
- RawRect.Bottom := Trunc((YOrigin - (((HB.FYBottom - YMin) / YGap) * YPixelGap)));
- if (RawRect.Bottom < 0) or (RawRect.Bottom > YOrigin) then
- RawRect.Bottom := Trunc(YOrigin);
- end;
-
- RawRect.Left := Round(XOrigin);
- RawRect.Right := Round(Options.XStartOffset + Options.XPixelGap * VC) - 1;
- end;
- end;
-begin
- if csDesigning in ComponentState then
- Exit;
- if FHorizontalBars.Count = 0 then
- Exit;
- ACanvas := GetChartCanvas(false);
- VC := Options.XValueCount;
- if VC < 1 then
- VC := 1;
-
- for J := 0 to FHorizontalBars.Count - 1 do
- begin
- HB := TJvChartHorizontalBar(FHorizontalBars[J]);
- if not HB.FVisible then
- Continue;
-
- CalcRawRect;
-
- ACanvas.Brush.Color := HB.FColor;
- ACanvas.Brush.Style := bsSolid;
- ACanvas.FillRect(RawRect);
- if HB.FColor <> HB.FGradColor then
- case HB.FGradDirection of
- //grNone:
- // ;
- grUp:
- GradVertical(ACanvas, RawRect, HB.FGradColor, HB.FColor);
- grDown:
- GradVertical(ACanvas, RawRect, HB.FColor, HB.FGradColor);
- end;
- end;
-
- {now draw outlines }
- // new april 2009
- for J := 0 to FHorizontalBars.Count - 1 do
- begin
- HB := TJvChartHorizontalBar(FHorizontalBars[J]);
- if not HB.FVisible then
- Continue;
- if HB.PenStyle<>psClear then begin
- CalcRawRect;
- ACanvas.Brush.Style := bsClear;
- ACanvas.Pen.Style := HB.PenStyle;
- ACAnvas.Pen.Color := HB.PenColor;
- ACanvas.Rectangle(RawRect);
- end;
- end;
-
-
-end;
-
-procedure TJvChart.DrawVerticalBars; // new 2007
-var
- VB: TJvChartVerticalBar;
- J: Integer;
- ACanvas: TCanvas;
- VC: Integer;
- RawRect: TRect;
- procedure CalcRawRect;
- begin
- RawRect.Top := FOptions.YStartOffset;
- RawRect.Bottom := Trunc(YOrigin);
- RawRect.Left := Round(Options.XStartOffset + Options.XPixelGap * VB.FXLeft);
- if RawRect.Left <= 0 then
- RawRect.Left := Round(XOrigin);
- RawRect.Right := Round(Options.XStartOffset + Options.XPixelGap * VB.FXRight);
- VC := Round(Options.XStartOffset + Options.XPixelGap * Options.XValueCount);
- if RawRect.Right > VC then
- RawRect.Right := VC;
- end;
-
-begin
- if csDesigning in ComponentState then
- Exit;
- if FVerticalBars.Count = 0 then
- Exit;
- ACanvas := GetChartCanvas(false);
- {VC :=Options.XValueCount;
- if VC<1 then VC:=1;}
-
- for J := 0 to FVerticalBars.Count - 1 do
- begin
- VB := TJvChartVerticalBar(FVerticalBars[J]);
- if not VB.FVisible then
- Continue;
-
- CalcRawRect;
-
- ACanvas.Brush.Color := VB.FColor;
- ACanvas.Brush.Style := bsSolid;
- ACanvas.FillRect(RawRect);
- if VB.FColor <> VB.FGradColor then
- case VB.FGradDirection of
- //grNone:
- // ;
- grUp:
- GradVertical(ACanvas, RawRect, VB.FGradColor, VB.FColor);
- grDown:
- GradVertical(ACanvas, RawRect, VB.FColor, VB.FGradColor);
- grLeft:
- GradHorizontal(ACanvas, RawRect, VB.FColor, VB.FGradColor);
- grRight:
- GradHorizontal(ACanvas, RawRect, VB.FGradColor, VB.FColor);
- end;
- end;
-
-
- {now draw outlines. these are done last so we can properly paint overlaps }
- // new april 2009
- for J := 0 to FVerticalBars.Count - 1 do
- begin
- VB := TJvChartVerticalBar(FVerticalBars[J]);
- if not VB.FVisible then
- Continue;
- if VB.PenStyle<>psClear then begin
- CalcRawRect;
- ACanvas.Brush.Style := bsClear;
- ACanvas.Pen.Style := VB.PenStyle;
- ACAnvas.Pen.Color := VB.PenColor;
- ACanvas.Rectangle(RawRect);
- end;
- end;
-
-end;
-
-function TJvChart.AddHorizontalBar: TJvChartHorizontalBar; // NEW 2007
-begin
- Assert(Assigned(FHorizontalBars));
- Result := TJvChartHorizontalBar.Create(Self);
- Result.FIndex := FHorizontalBars.Count;
- FHorizontalBars.Add(Result);
-end;
-
-function TJvChart.AddVerticalBar: TJvChartVerticalBar; // NEW 2007
-begin
- Assert(Assigned(FVerticalBars));
- Result := TJvChartVerticalBar.Create(Self);
- Result.FIndex := FVerticalBars.Count;
- FVerticalBars.Add(Result);
-end;
-
-procedure TJvChart.ClearHorizontalBars; // NEW 2007
-begin
- FHorizontalBars.Clear;
-end;
-
-procedure TJvChart.ClearVerticalBars; // NEW 2007
-begin
- FVerticalBars.Clear;
-end;
-
-function TJvChart.HorizontalBarsCount: Integer; // NEW 2007
-begin
- Result := FHorizontalBars.Count;
-end;
-
-function TJvChart.VerticalBarsCount: Integer; // NEW 2007
-begin
- Result := FVerticalBars.Count;
-end;
-
-end.