diff --git a/components/tachart/demo/unit1.lfm b/components/tachart/demo/unit1.lfm index 1517db0e69..3ed0707f3b 100644 --- a/components/tachart/demo/unit1.lfm +++ b/components/tachart/demo/unit1.lfm @@ -96,11 +96,19 @@ object Form1: TForm1 object lblAddCount: TLabel Left = 288 Height = 14 - Top = 16 + Top = 8 Width = 58 Caption = 'Multiple add' ParentColor = False end + object lblMarkStyle: TLabel + Left = 152 + Height = 14 + Top = 68 + Width = 78 + Caption = 'Add with marks:' + ParentColor = False + end object btnAddPie: TButton Left = 48 Height = 24 @@ -244,7 +252,7 @@ object Form1: TForm1 object edAddCount: TSpinEdit Left = 288 Height = 21 - Top = 41 + Top = 24 Width = 90 MaxValue = 1000000 MinValue = 1 @@ -289,5 +297,28 @@ object Form1: TForm1 OnChange = cbShowReticuleChange TabOrder = 18 end + object cbMarkStyle: TComboBox + Left = 240 + Height = 21 + Top = 68 + Width = 136 + ItemHeight = 13 + ItemIndex = 4 + Items.Strings = ( + 'smsCustom' + 'smsValue' + 'smsPercent' + 'smsLabel' + 'smsLabelPercent' + 'smsLabelValue' + 'smsLegend' + 'smsPercentTotal' + 'smsLabelPercentTotal' + 'smsXValue' + ) + Style = csDropDownList + TabOrder = 19 + Text = 'smsLabelPercent' + end end end diff --git a/components/tachart/demo/unit1.lrs b/components/tachart/demo/unit1.lrs index 87d496160f..6be35e11c0 100644 --- a/components/tachart/demo/unit1.lrs +++ b/components/tachart/demo/unit1.lrs @@ -31,43 +31,45 @@ LazarusResources.Add('TForm1','FORMDATA',[ +'Left'#2#13#6'Height'#2#14#3'Top'#2#10#5'Width'#2#24#7'Caption'#6#4'Add:'#11 +'ParentColor'#8#0#0#6'TLabel'#8'lblClear'#4'Left'#2#13#6'Height'#2#14#3'Top' +#2'('#5'Width'#2#30#7'Caption'#6#6'Clear:'#11'ParentColor'#8#0#0#6'TLabel'#11 - +'lblAddCount'#4'Left'#3' '#1#6'Height'#2#14#3'Top'#2#16#5'Width'#2':'#7'Capt' - +'ion'#6#12'Multiple add'#11'ParentColor'#8#0#0#7'TButton'#9'btnAddPie'#4'Lef' - +'t'#2'0'#6'Height'#2#24#3'Top'#2#8#5'Width'#2'4'#25'BorderSpacing.InnerBorde' - +'r'#2#4#7'Caption'#6#3'Pie'#7'OnClick'#7#14'btnAddPieClick'#8'TabOrder'#2#0#0 - +#0#7'TButton'#10'btnAddLine'#4'Left'#3#216#0#6'Height'#2#24#3'Top'#2#8#5'Wid' - +'th'#2'4'#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#4'Line'#7'OnClick'#7 - +#15'btnAddLineClick'#8'TabOrder'#2#1#0#0#7'TButton'#10'btnAddArea'#4'Left'#2 - +'h'#6'Height'#2#24#3'Top'#2#8#5'Width'#2'4'#25'BorderSpacing.InnerBorder'#2#4 - +#7'Caption'#6#4'Area'#7'OnClick'#7#15'btnAddAreaClick'#8'TabOrder'#2#2#0#0#7 - +'TButton'#9'btnAddBar'#4'Left'#3#160#0#6'Height'#2#24#3'Top'#2#8#5'Width'#2 - +'4'#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#3'Bar'#7'OnClick'#7#14'bt' - +'nAddBarClick'#8'TabOrder'#2#3#0#0#9'TCheckBox'#8'cbLegend'#4'Left'#3#128#1#6 - +'Height'#2#17#3'Top'#2#8#5'Width'#2'8'#7'Caption'#6#6'Legend'#8'OnChange'#7 - +#14'cbLegendChange'#8'TabOrder'#2#4#0#0#9'TCheckBox'#12'cbBottomAxis'#4'Left' - +#3#128#1#6'Height'#2#17#3'Top'#2#24#5'Width'#2'K'#7'Caption'#6#11'Bottom Axi' - +'s'#7'Checked'#9#8'OnChange'#7#18'cbBottomAxisChange'#5'State'#7#9'cbChecked' - +#8'TabOrder'#2#5#0#0#9'TCheckBox'#10'cbLeftAxis'#4'Left'#3#128#1#6'Height'#2 - +#17#3'Top'#2'('#5'Width'#2'<'#7'Caption'#6#9'Left Axis'#7'Checked'#9#8'OnCha' - +'nge'#7#16'cbLeftAxisChange'#5'State'#7#9'cbChecked'#8'TabOrder'#2#6#0#0#9'T' - +'CheckBox'#7'cbTitle'#4'Left'#3#240#1#6'Height'#2#17#3'Top'#2#8#5'Width'#2'(' - +#7'Caption'#6#5'Title'#7'Checked'#9#8'OnChange'#7#13'cbTitleChange'#5'State' - +#7#9'cbChecked'#8'TabOrder'#2#7#0#0#9'TCheckBox'#8'cbFooter'#4'Left'#3#240#1 - +#6'Height'#2#17#3'Top'#2#24#5'Width'#2'2'#7'Caption'#6#6'Footer'#8'OnChange' - +#7#14'cbFooterChange'#8'TabOrder'#2#8#0#0#9'TCheckBox'#10'cbInverted'#4'Left' - +#3#240#1#6'Height'#2#17#3'Top'#2'('#5'Width'#2';'#7'Caption'#6#8'Inverted'#8 - +'OnChange'#7#16'cbInvertedChange'#8'TabOrder'#2#9#0#0#7'TButton'#11'btnClear' - +'Bar'#4'Left'#3#160#0#6'Height'#2#24#3'Top'#2'&'#5'Width'#2'4'#25'BorderSpac' - +'ing.InnerBorder'#2#4#7'Caption'#6#3'Bar'#7'OnClick'#7#16'btnClearBarClick'#8 + +'lblAddCount'#4'Left'#3' '#1#6'Height'#2#14#3'Top'#2#8#5'Width'#2':'#7'Capti' + +'on'#6#12'Multiple add'#11'ParentColor'#8#0#0#6'TLabel'#12'lblMarkStyle'#4'L' + +'eft'#3#152#0#6'Height'#2#14#3'Top'#2'D'#5'Width'#2'N'#7'Caption'#6#15'Add w' + +'ith marks:'#11'ParentColor'#8#0#0#7'TButton'#9'btnAddPie'#4'Left'#2'0'#6'He' + +'ight'#2#24#3'Top'#2#8#5'Width'#2'4'#25'BorderSpacing.InnerBorder'#2#4#7'Cap' + +'tion'#6#3'Pie'#7'OnClick'#7#14'btnAddPieClick'#8'TabOrder'#2#0#0#0#7'TButto' + +'n'#10'btnAddLine'#4'Left'#3#216#0#6'Height'#2#24#3'Top'#2#8#5'Width'#2'4'#25 + +'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#4'Line'#7'OnClick'#7#15'btnAddL' + +'ineClick'#8'TabOrder'#2#1#0#0#7'TButton'#10'btnAddArea'#4'Left'#2'h'#6'Heig' + +'ht'#2#24#3'Top'#2#8#5'Width'#2'4'#25'BorderSpacing.InnerBorder'#2#4#7'Capti' + +'on'#6#4'Area'#7'OnClick'#7#15'btnAddAreaClick'#8'TabOrder'#2#2#0#0#7'TButto' + +'n'#9'btnAddBar'#4'Left'#3#160#0#6'Height'#2#24#3'Top'#2#8#5'Width'#2'4'#25 + +'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#3'Bar'#7'OnClick'#7#14'btnAddBa' + +'rClick'#8'TabOrder'#2#3#0#0#9'TCheckBox'#8'cbLegend'#4'Left'#3#128#1#6'Heig' + +'ht'#2#17#3'Top'#2#8#5'Width'#2'8'#7'Caption'#6#6'Legend'#8'OnChange'#7#14'c' + +'bLegendChange'#8'TabOrder'#2#4#0#0#9'TCheckBox'#12'cbBottomAxis'#4'Left'#3 + +#128#1#6'Height'#2#17#3'Top'#2#24#5'Width'#2'K'#7'Caption'#6#11'Bottom Axis' + +#7'Checked'#9#8'OnChange'#7#18'cbBottomAxisChange'#5'State'#7#9'cbChecked'#8 + +'TabOrder'#2#5#0#0#9'TCheckBox'#10'cbLeftAxis'#4'Left'#3#128#1#6'Height'#2#17 + +#3'Top'#2'('#5'Width'#2'<'#7'Caption'#6#9'Left Axis'#7'Checked'#9#8'OnChange' + +#7#16'cbLeftAxisChange'#5'State'#7#9'cbChecked'#8'TabOrder'#2#6#0#0#9'TCheck' + +'Box'#7'cbTitle'#4'Left'#3#240#1#6'Height'#2#17#3'Top'#2#8#5'Width'#2'('#7'C' + +'aption'#6#5'Title'#7'Checked'#9#8'OnChange'#7#13'cbTitleChange'#5'State'#7#9 + +'cbChecked'#8'TabOrder'#2#7#0#0#9'TCheckBox'#8'cbFooter'#4'Left'#3#240#1#6'H' + +'eight'#2#17#3'Top'#2#24#5'Width'#2'2'#7'Caption'#6#6'Footer'#8'OnChange'#7 + +#14'cbFooterChange'#8'TabOrder'#2#8#0#0#9'TCheckBox'#10'cbInverted'#4'Left'#3 + +#240#1#6'Height'#2#17#3'Top'#2'('#5'Width'#2';'#7'Caption'#6#8'Inverted'#8'O' + +'nChange'#7#16'cbInvertedChange'#8'TabOrder'#2#9#0#0#7'TButton'#11'btnClearB' + +'ar'#4'Left'#3#160#0#6'Height'#2#24#3'Top'#2'&'#5'Width'#2'4'#25'BorderSpaci' + +'ng.InnerBorder'#2#4#7'Caption'#6#3'Bar'#7'OnClick'#7#16'btnClearBarClick'#8 +'TabOrder'#2#10#0#0#7'TButton'#12'btnClearArea'#4'Left'#2'h'#6'Height'#2#24#3 +'Top'#2'&'#5'Width'#2'4'#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#4'Ar' +'ea'#7'OnClick'#7#17'btnClearAreaClick'#8'TabOrder'#2#11#0#0#7'TButton'#12'b' +'tnClearLine'#4'Left'#3#216#0#6'Height'#2#24#3'Top'#2'&'#5'Width'#2'4'#25'Bo' - +'rderSpacing.InnerBorder'#2#4#7'Caption'#6#4'Line'#7'OnClick'#7#17'btnClearL' + ,'rderSpacing.InnerBorder'#2#4#7'Caption'#6#4'Line'#7'OnClick'#7#17'btnClearL' +'ineClick'#8'TabOrder'#2#12#0#0#7'TButton'#11'btnClearPie'#4'Left'#2'0'#6'He' - ,'ight'#2#24#3'Top'#2'&'#5'Width'#2'4'#25'BorderSpacing.InnerBorder'#2#4#7'Ca' + +'ight'#2#24#3'Top'#2'&'#5'Width'#2'4'#25'BorderSpacing.InnerBorder'#2#4#7'Ca' +'ption'#6#3'Pie'#7'OnClick'#7#16'btnClearPieClick'#8'TabOrder'#2#13#0#0#9'TS' - +'pinEdit'#10'edAddCount'#4'Left'#3' '#1#6'Height'#2#21#3'Top'#2')'#5'Width'#2 + +'pinEdit'#10'edAddCount'#4'Left'#3' '#1#6'Height'#2#21#3'Top'#2#24#5'Width'#2 +'Z'#8'MaxValue'#4'@B'#15#0#8'MinValue'#2#1#8'TabOrder'#2#14#5'Value'#2#1#0#0 +#9'TCheckBox'#18'cbShowGridCheckBox'#4'Left'#3#128#1#6'Height'#2#17#3'Top'#2 +'8'#5'Width'#2'F'#7'Caption'#6#10'Show grid '#7'Checked'#9#8'OnChange'#7#24 @@ -79,5 +81,10 @@ LazarusResources.Add('TForm1','FORMDATA',[ +'e'#8'OnChange'#7#24'cbShowVertReticuleChange'#8'TabOrder'#2#17#0#0#9'TCheck' +'Box'#14'cbShowReticule'#4'Left'#3#240#1#6'Height'#2#17#3'Top'#2'H'#5'Width' +#2';'#7'Caption'#6#8'Reticule'#8'OnChange'#7#20'cbShowReticuleChange'#8'TabO' - +'rder'#2#18#0#0#0#0 + +'rder'#2#18#0#0#9'TComboBox'#11'cbMarkStyle'#4'Left'#3#240#0#6'Height'#2#21#3 + +'Top'#2'D'#5'Width'#3#136#0#10'ItemHeight'#2#13#9'ItemIndex'#2#4#13'Items.St' + +'rings'#1#6#9'smsCustom'#6#8'smsValue'#6#10'smsPercent'#6#8'smsLabel'#6#15's' + +'msLabelPercent'#6#13'smsLabelValue'#6#9'smsLegend'#6#15'smsPercentTotal'#6 + +#20'smsLabelPercentTotal'#6#9'smsXValue'#0#5'Style'#7#14'csDropDownList'#8'T' + +'abOrder'#2#19#4'Text'#6#15'smsLabelPercent'#0#0#0#0 ]); diff --git a/components/tachart/demo/unit1.pas b/components/tachart/demo/unit1.pas index 4e611092d7..f63b0a064a 100644 --- a/components/tachart/demo/unit1.pas +++ b/components/tachart/demo/unit1.pas @@ -33,8 +33,10 @@ type cbShowVertReticule: TCheckBox; Chart1LineHor: TLine; Chart1LineVert: TLine; + cbMarkStyle: TComboBox; lblAddCount: TLabel; lblAdd: TLabel; + lblMarkStyle: TLabel; lblClear: TLabel; Panel1: TPanel; edAddCount: TSpinEdit; @@ -73,6 +75,9 @@ var implementation +uses + TAChartUtils; + { TForm1 } procedure TForm1.btnAddAreaClick(Sender: TObject); @@ -121,6 +126,7 @@ var i: integer; begin if FPie = nil then InitPie; + FPie.MarksStyle := TSeriesMarksStyle(cbMarkStyle.ItemIndex); for i := 1 to edAddCount.Value do begin FPie.AddPie(3.4234235235, 'sde21312', clTAColor); FPie.AddPie(0.2323, 'adassssssdddddd', clTAColor); @@ -239,7 +245,6 @@ begin FPie.Title := 'pie'; FPie.LabelBackgroundColor := $80FFFF; FPie.LabelToPieLinkColor := clCream; - FPie.MarksStyle := smsLabelPercent; Chart1.AddSeries(FPie); end; diff --git a/components/tachart/tachartutils.pas b/components/tachart/tachartutils.pas index 88011a7425..6da98bd6e4 100644 --- a/components/tachart/tachartutils.pas +++ b/components/tachart/tachartutils.pas @@ -18,6 +18,8 @@ * * ***************************************************************************** +Authors: Luнs Rodrigues, Philippe Martinole, Alexander Klenin + } unit TAChartUtils; @@ -48,6 +50,18 @@ type TPenBrushFont = set of (pbfPen, pbfBrush, pbfFont); + TSeriesMarksStyle = ( + smsCustom, { user-defined } + smsValue, { 1234 } + smsPercent, { 12 % } + smsLabel, { Cars } + smsLabelPercent, { Cars 12 % } + smsLabelValue, { Cars 1234 } + smsLegend, { ? } + smsPercentTotal, { 12 % of 1234 } + smsLabelPercentTotal, { Cars 12 % of 1234 } + smsXValue); { 21/6/1996 } + { TPenBrushFontRecall } TPenBrushFontRecall = class @@ -62,6 +76,21 @@ type procedure Recall; end; +const + // 0-value, 1-percent, 2-label, 3-total, 4-xvalue + SERIES_MARK_FORMATS: array [TSeriesMarksStyle] of String = ( + '', + '%0:g', // smsValue + '%1:.2f%%', // smsPercent + '%2:s', // smsLabel + '%2:s %1:.2f%%', // smsLabelPercent + '%2:s %0:g', // smsLabelValue + '%2:s', // smsLegend: not sure what it means, left for Delphi compatibility + '%1:.2f%% of %3:g', // smsPercentTotal + '%1:.2f%% of %3:g', // smsLabelPercentTotal + '%4:g' // smsXValue + ); + procedure CalculateIntervals( AMin, AMax: Double; AxisScale: TAxisScale; out AStart, AStep: Double); @@ -79,7 +108,7 @@ procedure RotateLabel( implementation uses - Math, SysUtils, LCLIntF, LCLType; + Math, SysUtils, LCLIntf, LCLType; procedure CalculateIntervals( AMin, AMax: Double; AxisScale: TAxisScale; out AStart, AStep: Double); diff --git a/components/tachart/taseries.pas b/components/tachart/taseries.pas index 8a49b096a2..ad4fabf9c9 100644 --- a/components/tachart/taseries.pas +++ b/components/tachart/taseries.pas @@ -33,18 +33,6 @@ uses type - //not completetly implemented (only TPieSeries - not all) - TSeriesMarksStyle = ( - smsValue, { 1234 } - smsPercent, { 12 % } - smsLabel, { Cars } - smsLabelPercent, { Cars 12 % } - smsLabelValue, { Cars 1234 } - smsLegend, { ? } - smsPercentTotal, { 12 % of 1234 } - smsLabelPercentTotal, { Cars 12 % of 1234 } - smsXValue); { 21/6/1996 } - TChartCoord = record x, y: Double; Color: TColor; @@ -69,6 +57,8 @@ type FActive: Boolean; FMarks: TSeriesMarksStyle; FShowInLegend: Boolean; + FValuesTotal: Double; + FValuesTotalValid: Boolean; procedure SetActive(Value: Boolean); procedure SetMarks(Value: TSeriesMarksStyle); @@ -85,6 +75,7 @@ type procedure UpdateBounds( var ANumPoints: Integer; var AXMin, AYMin, AXMax, AYMax: Double); override; procedure UpdateParentChart; + function GetValuesTotal: Double; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; @@ -101,6 +92,7 @@ type function Add(AValue: Double; XLabel: String; Color: TColor): Longint; virtual; procedure Delete(AIndex: Integer); virtual; procedure Clear; + function FormattedMark(AIndex: integer): String; published property Active: Boolean read FActive write SetActive default true; @@ -373,6 +365,14 @@ begin ACanvas.TextOut(ARect.Right + 3, ARect.Top, Title); end; +function TChartSeries.FormattedMark(AIndex: integer): String; +begin + with PChartCoord(FCoordList[AIndex])^ do + Result := Format( + SERIES_MARK_FORMATS[MarksStyle], + [y, y / GetValuesTotal * 100, Text, GetValuesTotal, x]); +end; + function TChartSeries.GetLegendCount: Integer; begin Result := 1; @@ -383,6 +383,19 @@ begin Result := ACanvas.TextWidth(Title); end; +function TChartSeries.GetValuesTotal: Double; +var + i: Integer; +begin + if not FValuesTotalValid then begin + FValuesTotal := 0; + for i := 0 to FCoordList.Count - 1 do + FValuesTotal += PChartCoord(FCoordList[i])^.y; + FValuesTotalValid := true; + end; + Result := FValuesTotal; +end; + function TChartSeries.GetXMinVal: Integer; begin if Count > 0 then @@ -430,6 +443,8 @@ begin while (Result > 0) and (PChartCoord(FCoordList.Items[Result - 1])^.x > X) do Dec(Result); FCoordList.Insert(Result, pcc); + if FValuesTotalValid then + FValuesTotal += Y; end; function TChartSeries.Add(AValue: Double; XLabel: String; Color: TColor): Longint; @@ -448,6 +463,7 @@ procedure TChartSeries.Delete(AIndex:Integer); begin Dispose(PChartCoord(FCoordList.Items[AIndex])); FCoordList.Delete(AIndex); + FValuesTotalValid := false; UpdateParentChart; end; @@ -459,6 +475,7 @@ begin YGraphMin := MaxDouble; XGraphMax := MinDouble; YGraphMax := MinDouble; + FValuesTotalValid := false; UpdateParentChart; end; @@ -1337,12 +1354,7 @@ begin SetLength(labelTexts, FCoordList.Count); for i := 0 to FCoordList.Count - 1 do with PChartCoord(FCoordList[i])^ do begin - case MarksStyle of - smsLabel: - labelTexts[i] := Text; - smsLabelPercent: - labelTexts[i] := Text + Format(' %1.3g%%', [y / yTotal * 100]); - end; + labelTexts[i] := FormattedMark(i); with ACanvas.TextExtent(labelTexts[i]) do begin labelWidths[i] := cx; labelHeights[i] := cy;