From 609137625e8f4dcf4b6ba3131770bece4648acc2 Mon Sep 17 00:00:00 2001 From: ask Date: Tue, 12 Jul 2011 11:21:37 +0000 Subject: [PATCH] TAChart: Add and use filtered series enumerator git-svn-id: trunk@31677 - --- .gitattributes | 1 + components/tachart/tachartlazaruspkg.lpk | 8 +- components/tachart/tachartlazaruspkg.pas | 2 +- components/tachart/taenumerators.pas | 136 +++++++++++++++++++++++ components/tachart/tatools.pas | 27 ++--- 5 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 components/tachart/taenumerators.pas diff --git a/.gitattributes b/.gitattributes index 31e6a2c290..74d4d142c4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2618,6 +2618,7 @@ components/tachart/tadraweropengl.pas svneol=native#text/pascal components/tachart/tadrawersvg.pas svneol=native#text/pascal components/tachart/tadrawerwmf.pas svneol=native#text/pascal components/tachart/tadrawutils.pas svneol=native#text/pascal +components/tachart/taenumerators.pas svneol=native#text/pascal components/tachart/tafuncseries.pas svneol=native#text/pascal components/tachart/tageometry.pas svneol=native#text/pascal components/tachart/tagraph.lrs svneol=native#text/pascal diff --git a/components/tachart/tachartlazaruspkg.lpk b/components/tachart/tachartlazaruspkg.lpk index 5da7e2c9fc..8516ab202d 100644 --- a/components/tachart/tachartlazaruspkg.lpk +++ b/components/tachart/tachartlazaruspkg.lpk @@ -30,7 +30,7 @@ for details about the copyright. "/> - + @@ -158,8 +158,12 @@ - + + + + + diff --git a/components/tachart/tachartlazaruspkg.pas b/components/tachart/tachartlazaruspkg.pas index 8dce011ae8..c5c7453372 100644 --- a/components/tachart/tachartlazaruspkg.pas +++ b/components/tachart/tachartlazaruspkg.pas @@ -12,7 +12,7 @@ uses TATypes, TADrawUtils, TAMultiSeries, TALegend, TAStyles, TAFuncSeries, TALegendPanel, TARadialSeries, TACustomSource, TAGeometry, TANavigation, TADrawerCanvas, TADrawerSVG, TAIntervalSources, TAChartAxisUtils, - TAChartListbox, LazarusPackageIntf; + TAChartListbox, TAEnumerators, LazarusPackageIntf; implementation diff --git a/components/tachart/taenumerators.pas b/components/tachart/taenumerators.pas new file mode 100644 index 0000000000..2b4639ebf5 --- /dev/null +++ b/components/tachart/taenumerators.pas @@ -0,0 +1,136 @@ +{ + + ***************************************************************************** + * * + * See the file COPYING.modifiedLGPL.txt, included in this distribution, * + * for details about the copyright. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * * + ***************************************************************************** + + Authors: Alexander Klenin + +} +unit TAEnumerators; + +{$H+} + +interface + +uses + Classes, Types, + TACustomSeries, TAGraph; + +type + TBasicFilteredChartSeriesEnumeratorFactory = class + strict protected + FChart: TChart; + FFilter: TBooleanDynArray; + public + constructor Create(AChart: TChart; AFilter: TBooleanDynArray); + property Chart: TChart read FChart; + property Filter: TBooleanDynArray read FFilter; + end; + + {$IFNDEF fpdoc} // Workaround for issue #18549. + generic TFilteredChartSeriesEnumerator<_T> = class + {$ELSE} + TFilteredChartSeriesEnumerator = class + {$ENDIF} + strict private + FFactory: TBasicFilteredChartSeriesEnumeratorFactory; + FPosition: Integer; + public + constructor Create(AFactory: TBasicFilteredChartSeriesEnumeratorFactory); + destructor Destroy; override; + function GetCurrent: _T; + function MoveNext: Boolean; + property Current: _T read GetCurrent; + end; + + {$IFNDEF fpdoc} // Workaround for issue #18549. + generic TFilteredChartSeriesEnumeratorFactory<_T> = class( + TBasicFilteredChartSeriesEnumeratorFactory) + {$ELSE} + TFilteredChartSeriesEnumeratorFactory = class( + TBasicFilteredChartSeriesEnumeratorFactory) + {$ENDIF} + public + type + TEnum = specialize TFilteredChartSeriesEnumerator<_T>; + function GetEnumerator: TEnum; + end; + + {$IFNDEF fpdoc} // Workaround for issue #18549. + TFilteredCustomChartSeriesEnumeratorFactory = + specialize TFilteredChartSeriesEnumeratorFactory; + {$ENDIF} + + function CustomSeries( + AChart: TChart; AFilter: TBooleanDynArray = nil + ): TFilteredCustomChartSeriesEnumeratorFactory; + +implementation + +uses + SysUtils; + +function CustomSeries( + AChart: TChart; AFilter: TBooleanDynArray): + TFilteredCustomChartSeriesEnumeratorFactory; +begin + Result := TFilteredCustomChartSeriesEnumeratorFactory.Create(AChart, AFilter); +end; + +{ TBasicFilteredChartSeriesEnumeratorFactory } + +constructor TBasicFilteredChartSeriesEnumeratorFactory.Create( + AChart: TChart; AFilter: TBooleanDynArray); +begin + FChart := AChart; + FFilter := AFilter; +end; + +{ TFilteredChartSeriesEnumerator } + +constructor TFilteredChartSeriesEnumerator.Create( + AFactory: TBasicFilteredChartSeriesEnumeratorFactory); +begin + FFactory := AFactory; +end; + +destructor TFilteredChartSeriesEnumerator.Destroy; +begin + FreeAndNil(FFactory); + inherited; +end; + +function TFilteredChartSeriesEnumerator.GetCurrent: _T; +begin + Result := _T(FFactory.Chart.Series.List[FPosition]); +end; + +function TFilteredChartSeriesEnumerator.MoveNext: Boolean; +begin + Result := false; + repeat + FPosition += 1; + if FPosition >= FFactory.Chart.SeriesCount then exit; + Result := + (TBasicChartSeries(FFactory.Chart.Series.List[FPosition]).InheritsFrom(_T)) and + ((FPosition > High(FFactory.Filter)) or FFactory.Filter[FPosition]); + until Result; +end; + +{ TFilteredChartSeriesEnumeratorFactory } + +function TFilteredChartSeriesEnumeratorFactory.GetEnumerator: TEnum; +begin + Result := TEnum.Create(Self); +end; + +end. + diff --git a/components/tachart/tatools.pas b/components/tachart/tatools.pas index 8f1b52f7b8..14512b077a 100644 --- a/components/tachart/tatools.pas +++ b/components/tachart/tatools.pas @@ -363,7 +363,8 @@ implementation uses ComponentEditors, Forms, GraphMath, Math, PropEdits, SysUtils, - TACustomSeries, TADrawerCanvas, TAGeometry, TASubcomponentsEditor; + TACustomSeries, TADrawerCanvas, TAEnumerators, TAGeometry, + TASubcomponentsEditor; type { TToolsComponentEditor } @@ -937,23 +938,21 @@ var retPos: TPoint; value: TDoublePoint; end; - i, bestSeries: Integer; d, minDist: Double; df: TPointDistFunc; + s, bestS: TCustomChartSeries; begin if FChart.ReticuleMode = rmNone then exit; minDist := SafeInfinity; df := DIST_FUNCS[FChart.ReticuleMode]; - for i := 0 to FChart.SeriesCount - 1 do + for s in CustomSeries(FChart) do if - (FChart.Series[i] is TCustomChartSeries) and - (FChart.Series[i] as TCustomChartSeries).GetNearestPoint( - df, APoint, cur.pointIndex, cur.retPos, cur.value) and + s.GetNearestPoint(df, APoint, cur.pointIndex, cur.retPos, cur.value) and PtInRect(FChart.ClipRect, cur.retPos) then begin d := df(APoint, cur.retPos); if d < minDist then begin - bestSeries := i; + bestS := s; best := cur; minDist := d; end; @@ -961,7 +960,7 @@ begin if not IsInfinite(minDist) and (best.retPos <> FChart.ReticulePos) then begin FChart.ReticulePos := best.retPos; if Assigned(FChart.OnDrawReticule) then - FChart.OnDrawReticule(FChart, bestSeries, best.pointIndex, best.value); + FChart.OnDrawReticule(FChart, bestS.Index, best.pointIndex, best.value); end; end; @@ -1158,20 +1157,14 @@ end; procedure TDataPointTool.FindNearestPoint(APoint: TPoint); var - i, d, bestd, idx: Integer; - bests: TBasicChartSeries; - s: TCustomChartSeries; - affected: TBooleanDynArray; + d, bestd, idx: Integer; + s, bests: TCustomChartSeries; dummy: TDoublePoint; nearest: TPoint; begin bestd := MaxInt; bests := nil; - affected := ParseAffectedSeries; - for i := 0 to FChart.SeriesCount - 1 do begin - if not affected[i] or not (FChart.Series[i] is TCustomChartSeries) then - continue; - s := FChart.Series[i] as TCustomChartSeries; + for s in CustomSeries(FChart, ParseAffectedSeries) do begin if not s.GetNearestPoint(@PointDist, APoint, idx, nearest, dummy) then continue; d := PointDist(APoint, nearest);