TAChart: Add and use filtered series enumerator

git-svn-id: trunk@31677 -
This commit is contained in:
ask 2011-07-12 11:21:37 +00:00
parent e164321e99
commit 609137625e
5 changed files with 154 additions and 20 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -30,7 +30,7 @@
for details about the copyright.
"/>
<Version Major="1"/>
<Files Count="29">
<Files Count="30">
<Item1>
<Filename Value="tagraph.pas"/>
<HasRegisterProc Value="True"/>
@ -158,8 +158,12 @@
<Item29>
<Filename Value="tachartlistbox.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="tachartlistbox"/>
<UnitName Value="TAChartListbox"/>
</Item29>
<Item30>
<Filename Value="taenumerators.pas"/>
<UnitName Value="TAEnumerators"/>
</Item30>
</Files>
<LazDoc Paths="$(LazarusDir)\components\tachart\fpdoc"/>
<Type Value="RunAndDesignTime"/>

View File

@ -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

View File

@ -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<TCustomChartSeries>;
{$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.

View File

@ -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);