mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-16 03:20:33 +01:00
TAChart: Add and use filtered series enumerator
git-svn-id: trunk@31677 -
This commit is contained in:
parent
e164321e99
commit
609137625e
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
||||
@ -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"/>
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
136
components/tachart/taenumerators.pas
Normal file
136
components/tachart/taenumerators.pas
Normal 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.
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user