From 95c2e4c505053149662d43079a69f513d50cd661 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Mon, 4 Dec 2023 23:16:06 +0000 Subject: [PATCH] fpspreadsheet: Logarithmic axis support in chart link. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9070 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../fpspreadsheet/source/common/fpschart.pas | 4 +- .../source/visual/fpspreadsheetchart.pas | 90 ++++++++++++++----- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/components/fpspreadsheet/source/common/fpschart.pas b/components/fpspreadsheet/source/common/fpschart.pas index 98fbebd32..5be5b5974 100644 --- a/components/fpspreadsheet/source/common/fpschart.pas +++ b/components/fpspreadsheet/source/common/fpschart.pas @@ -341,6 +341,7 @@ type FLabelFont: TsFont; FLabelPosition: TsChartLabelPosition; FLabelSeparator: string; + FXAxis: TsChartAxisLink; FYAxis: TsChartAxisLink; FTitleAddr: TsChartCellAddr; FLabelFormat: String; @@ -389,9 +390,10 @@ type property LabelSeparator: string read FLabelSeparator write FLabelSeparator; property LineColorRange: TsChartRange read FLineColorRange write FLineColorRange; property TitleAddr: TsChartCellAddr read FTitleAddr write FTitleAddr; // use '\n' for line-break + property XAxis: TsChartAxisLink read FXAxis write FXAxis; property XRange: TsChartRange read FXRange write FXRange; - property YRange: TsChartRange read FYRange write FYRange; property YAxis: TsChartAxisLink read FYAxis write FYAxis; + property YRange: TsChartRange read FYRange write FYRange; property Fill: TsChartFill read FFill write FFill; property Line: TsChartLine read FLine write FLine; diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas index b4fe9edb8..41ca27f3f 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas @@ -132,7 +132,11 @@ type procedure ConstructHatchPattern(AWorkbookChart: TsChart; AFill: TsChartFill; ABrush: TBrush); procedure ConstructHatchPatternSolid(AWorkbookChart: TsChart; AFill: TsChartFill; ABrush: TBrush); procedure ConstructSeriesMarks(AWorkbookSeries: TsChartSeries; AChartSeries: TChartSeries); + function GetAutoscaleAxisTransform(AChartAxis: TChartAxis): TAutoScaleAxisTransform; + function GetAxisTransform(AChartAxis: TChartAxis; AClass: TAxisTransformClass): TAxisTransform; + function GetLogAxisTransform(AChartAxis: TChartAxis): TLogarithmAxisTransform; function GetWorkbookChart: TsChart; + function IsLogarithmic(Axis: TChartAxis): Boolean; function IsSecondaryAxis(Axis: TsChartAxis): boolean; function IsStackable(ASeries: TsChartSeries): Boolean; @@ -1099,7 +1103,13 @@ begin Result.Title := src.Title; end; - // Assign series to axis for primary and secondary y axes support + // Assign series to axis for primary and secondary axes support + case ASeries.XAxis of + alPrimary: + Result.AxisIndexX := FChart.AxisList.GetAxisByAlign(calBottom).Index; + alSecondary: + Result.AxisIndexX := FChart.AxisList.GetAxisByAlign(calTop).Index; + end; case ASeries.YAxis of alPrimary: Result.AxisIndexY := FChart.AxisList.GetAxisByAlign(calLeft).Index; @@ -1459,6 +1469,30 @@ begin end; end; +function TsWorkbookChartLink.GetAutoScaleAxisTransform(AChartAxis: TChartAxis): TAutoScaleAxisTransform; +begin + Result := TAutoScaleAxisTransform(GetAxisTransform(AChartAxis, TAutoScaleAxisTransform)); +end; + +function TsWorkbookChartLink.GetAxisTransform(AChartAxis: TChartAxis; + AClass: TAxisTransformClass): TAxisTransform; +var + T: TAxisTransform; +begin + for T in AChartAxis.Transformations.List do + if T is AClass then + begin + Result := T; + exit; + end; + Result := nil; +end; + +function TsWorkbookChartLink.GetLogAxisTransform(AChartAxis: TChartAxis): TLogarithmAxisTransform; +begin + Result := TLogarithmAxisTransform(GetAxisTransform(AChartAxis, TLogarithmAxisTransform)); +end; + function TsWorkbookChartLink.GetWorkbookChart: TsChart; begin if (FWorkbook <> nil) and (FWorkbookChartIndex > -1) then @@ -1467,6 +1501,14 @@ begin Result := nil; end; +function TsWorkbookChartLink.IsLogarithmic(Axis: TChartAxis): Boolean; +var + T: TLogarithmAxisTransform; +begin + T := GetLogAxisTransform(Axis); + Result := (T <> nil) and T.Enabled; +end; + function TsWorkbookChartLink.IsSecondaryAxis(Axis: TsChartAxis): Boolean; begin Result := (Axis = Axis.Chart.Y2Axis) or (Axis = Axis.Chart.X2Axis); @@ -1669,6 +1711,25 @@ begin // Entire axis visible? axis.Visible := AWorkbookAxis.Visible; + // Usually not needed, but axis handling is simplified when there is + // an axis transformations object at each axis with all transforms prepared. + if axis.Transformations = nil then + begin + axis.Transformations := TChartAxisTransformations.Create(FChart); + + // Logarithmic + T := TLogarithmAxisTransform.Create(axis.Transformations); + T.Transformations := axis.Transformations; + TLogarithmAxisTransform(T).Base := 10; + TLogarithmAxisTransform(T).Enabled := AWorkbookAxis.Logarithmic; + + // Autoscale transformation for primary and secondary axes + T := TAutoScaleAxisTransform.Create(axis.Transformations); + T.Transformations := axis.Transformations; + if AWorkbookAxis.Logarithmic or (AWorkbookAxis.Chart.GetChartType in [ctRadar, ctFilledRadar]) then + T.Enabled := false; + end; + // Axis title axis.Title.Caption := AWorkbookAxis.Title.Caption; axis.Title.Visible := true; @@ -1697,7 +1758,10 @@ begin minorAxis := axis.Minors.Add; UpdateChartPen(AWorkbookAxis.Chart, AWorkbookAxis.MinorGridLines, minorAxis.Grid); minorAxis.Grid.Visible := not IsSecondaryAxis(AWorkbookAxis); - minorAxis.Intervals.Count := AWorkbookAxis.MinorCount; + if AWorkbookAxis.Logarithmic then + minorAxis.Intervals.Count := 9 + else + minorAxis.Intervals.Count := AWorkbookAxis.MinorCount; minorAxis.TickLength := IfThen(catOutside in AWorkbookAxis.MinorTicks, 2, 0); minorAxis.TickInnerLength := IfThen(catInside in AWorkbookAxis.MinorTicks, 2, 0); minorAxis.TickColor := axis.AxisPen.Color; @@ -1707,23 +1771,6 @@ begin // Inverted? axis.Inverted := AWorkbookAxis.Inverted; - // Usually not needed, but axis handling is simplified when there is - // an axis transformation at each axis. - if axis.Transformations = nil then - begin - axis.Transformations := TChartAxisTransformations.Create(FChart); - // Autoscale transformation for primary and secondary axes - T := TAutoScaleAxisTransform.Create(axis.Transformations); - T.Transformations := axis.Transformations; - if AWorkbookAxis.Chart.GetChartType in [ctRadar, ctFilledRadar] then - T.Enabled := false; - // Logarithmic - T := TLogarithmAxisTransform.Create(axis.Transformations); - T.Transformations := axis.Transformations; - TLogarithmAxisTransform(T).Base := 10; - TLogarithmAxisTransform(T).Enabled := AWorkbookAxis.Logarithmic; - end; - // Scaling axis.Range.UseMin := not AWorkbookAxis.AutomaticMin; axis.Range.UseMax := not AWorkbookAxis.AutomaticMax; @@ -1731,16 +1778,17 @@ begin axis.Range.Max := AWorkbookAxis.Max; // Logarithmic - logTransf := TLogarithmAxisTransform(axis.Transformations.List[1]); + logTransf := GetLogAxisTransform(axis); logTransf.Enabled := AWorkbookAxis.Logarithmic; if AWorkbookAxis.Logarithmic then begin -// axis.Intervals.Options := axis.Intervals.Options + [aipInteger];; + axis.Intervals.Options := axis.Intervals.Options + [aipGraphCoords]; axis.Intervals.MaxLength := 150; axis.Intervals.MinLength := 30; axis.Intervals.Tolerance := 30; end else begin + axis.Intervals.Options := axis.Intervals.Options - [aipGraphCoords]; axis.Intervals.MaxLength := 100; axis.Intervals.MinLength := 20; axis.Intervals.Tolerance := 0;