TAChart: Make sure that builtin ColorSource of TCustomColorMapSeries always provides at least one x value. Patch by Marcin Wiazowski, issue #35705.

git-svn-id: trunk@61409 -
This commit is contained in:
wp 2019-06-17 17:53:09 +00:00
parent e1b1260935
commit 900910e4c4

View File

@ -18,7 +18,7 @@ interface
uses uses
Classes, Graphics, typ, Types, Classes, Graphics, typ, Types,
TAChartUtils, TACustomFuncSeries, TACustomSeries, TACustomSource, TAChartUtils, TACustomFuncSeries, TACustomSeries, TACustomSource, TASources,
TADrawUtils, TAFitUtils, TALegend, TATypes, TAFitLib, TAStyles; TADrawUtils, TAFitUtils, TALegend, TATypes, TAFitLib, TAStyles;
const const
@ -417,7 +417,7 @@ type
FStepY: TFuncSeriesStep; FStepY: TFuncSeriesStep;
FUseImage: TUseImage; FUseImage: TUseImage;
FColorExtentMin, FColorExtentMax: Double; FColorExtentMin, FColorExtentMax: Double;
FBuiltinColorSource: TCustomChartSource; FBuiltinColorSource: TListChartSource;
FBuiltinPalette: TColormapPalette; FBuiltinPalette: TColormapPalette;
FPaletteMax: Double; FPaletteMax: Double;
FPaletteMin: Double; FPaletteMin: Double;
@ -437,9 +437,12 @@ type
protected protected
FMinZ, FMaxZ: Double; FMinZ, FMaxZ: Double;
procedure BuildPalette(APalette: TColorMapPalette); procedure BuildPalette(APalette: TColorMapPalette);
procedure CheckColorSource(ASource: TCustomChartSource);
procedure ColorSourceChanged(ASender: TObject); virtual;
procedure GetLegendItems(AItems: TChartLegendItems); override; procedure GetLegendItems(AItems: TChartLegendItems); override;
procedure GetZRange(ARect: TRect; dx, dy: Integer); procedure GetZRange(ARect: TRect; dx, dy: Integer);
procedure UpdateColorExtent; procedure UpdateColorExtent;
class procedure GetXYCountNeeded(out AXCount, AYCount: Cardinal); virtual;
public public
procedure Assign(ASource: TPersistent); override; procedure Assign(ASource: TPersistent); override;
@ -498,7 +501,7 @@ implementation
uses uses
{$IF FPC_FullVersion >= 30101}ipf{$ELSE}ipf_fix{$ENDIF}, {$IF FPC_FullVersion >= 30101}ipf{$ELSE}ipf_fix{$ENDIF},
GraphType, GraphUtil, IntfGraphics, Math, spe, StrUtils, SysUtils, GraphType, GraphUtil, IntfGraphics, Math, spe, StrUtils, SysUtils,
TAChartStrConsts, TAGeometry, TAGraph, TAMath, TASources; TAChartStrConsts, TAGeometry, TAGraph, TAMath;
const const
DEF_PARAM_MIN = 0.0; DEF_PARAM_MIN = 0.0;
@ -2374,7 +2377,7 @@ var
cmax, cmin, factor: Double; cmax, cmin, factor: Double;
ex: TDoubleRect; ex: TDoubleRect;
begin begin
with FBuiltinColorSource as TListChartSource do begin with FBuiltinColorSource do begin
BeginUpdate; BeginUpdate;
try try
Clear; Clear;
@ -2417,32 +2420,40 @@ begin
else else
raise EChartError.CreateFmt('[%s.BuildPalette] Palette not supported', [NameOrClassName(Self)]); raise EChartError.CreateFmt('[%s.BuildPalette] Palette not supported', [NameOrClassName(Self)]);
end; end;
if FPaletteMin < FPaletteMax then begin
cmin := FPaletteMin;
cmax := FPaletteMax;
end else
if FPaletteMax < FPaletteMin then begin
cmin := FPaletteMax;
cmax := FPaletteMin;
end else
exit;
ex := Extent;
if (ex.a.x = ex.b.x) then
exit;
factor := (cmax - cmin) / (ex.b.x - ex.a.x);
for i:=0 to Count-1 do
Item[i]^.X := (Item[i]^.X - ex.a.x) * factor + cmin;
finally finally
EndUpdate; EndUpdate;
end; end;
end; end;
end;
if FPaletteMin < FPaletteMax then begin procedure TCustomColorMapSeries.CheckColorSource(ASource: TCustomChartSource);
cmin := FPaletteMin; var
cmax := FPaletteMax; nx, ny: Cardinal;
end else begin
if FPaletteMax < FPaletteMin then begin if ASource = nil then
cmin := FPaletteMax;
cmax := FPaletteMin;
end else
exit; exit;
GetXYCountNeeded(nx, ny);
with FBuiltInColorSource do begin if ASource.XCount < nx then
ex := Extent; raise EXCountError.CreateFmt(rsSourceCountError, [ClassName, nx, 'x']);
if (ex.a.x = ex.b.x) then if ASource.YCount < ny then
exit; raise EYCountError.CreateFmt(rsSourceCountError, [ClassName, ny, 'y']);
factor := (cmax - cmin) / (ex.b.x - ex.a.x);
for i:=0 to Count-1 do
Item[i]^.X := (Item[i]^.X - ex.a.x) * factor + cmin;
end;
if FColorSource = nil then
UpdateColorExtent;
end; end;
function TCustomColorMapSeries.ColorByValue(AValue: Double): TColor; function TCustomColorMapSeries.ColorByValue(AValue: Double): TColor;
@ -2474,10 +2485,15 @@ end;
constructor TCustomColorMapSeries.Create(AOwner: TComponent); constructor TCustomColorMapSeries.Create(AOwner: TComponent);
const const
BUILTIN_SOURCE_NAME = 'BuiltinColors'; BUILTIN_SOURCE_NAME = 'BuiltinColors';
var
nx, ny: Cardinal;
begin begin
inherited Create(AOwner); inherited Create(AOwner);
FColorSourceListener := TListener.Create(@FColorSource, @StyleChanged); FColorSourceListener := TListener.Create(@FColorSource, @ColorSourceChanged);
FBuiltinColorSource := TListChartSource.Create(self); GetXYCountNeeded(nx, ny);
FBuiltinColorSource := TBuiltinListChartSource.Create(self, nx, ny);
FBuiltinColorSource.XCount := nx;
FBuiltinColorSource.YCount := ny;
FBuiltinColorSource.Name := BUILTIN_SOURCE_NAME; FBuiltinColorSource.Name := BUILTIN_SOURCE_NAME;
FBuiltinColorSource.Broadcaster.Subscribe(FColorSourceListener); FBuiltinColorSource.Broadcaster.Subscribe(FColorSourceListener);
FBrush := TBrush.Create; FBrush := TBrush.Create;
@ -2489,9 +2505,9 @@ end;
destructor TCustomColorMapSeries.Destroy; destructor TCustomColorMapSeries.Destroy;
begin begin
FreeAndNil(FBrush);
FreeAndNil(FBuiltinColorSource);
FreeAndNil(FColorSourceListener); FreeAndNil(FColorSourceListener);
FreeAndNil(FBuiltinColorSource);
FreeAndNil(FBrush);
inherited Destroy; inherited Destroy;
end; end;
@ -2679,6 +2695,12 @@ begin
end; end;
end; end;
class procedure TCustomColorMapSeries.GetXYCountNeeded(out AXCount, AYCount: Cardinal);
begin
AXCount := 1;
AYCount := 0;
end;
procedure TCustomColorMapSeries.GetZRange(ARect: TRect; dx, dy: Integer); procedure TCustomColorMapSeries.GetZRange(ARect: TRect; dx, dy: Integer);
var var
gp: TDoublePoint; gp: TDoublePoint;
@ -2747,18 +2769,20 @@ procedure TCustomColorMapSeries.SetBuiltinPalette(AValue: TColorMapPalette);
begin begin
FBuiltinPalette := AValue; FBuiltinPalette := AValue;
BuildPalette(FBuiltinPalette); BuildPalette(FBuiltinPalette);
UpdateParentChart;
end; end;
procedure TCustomColorMapSeries.SetColorSource(AValue: TCustomChartSource); procedure TCustomColorMapSeries.SetColorSource(AValue: TCustomChartSource);
begin begin
if FColorSource = AValue then exit; if AValue = FBuiltinColorSource then
AValue := nil;
if FColorSource = AValue then
exit;
CheckColorSource(AValue);
if FColorSourceListener.IsListening then if FColorSourceListener.IsListening then
ColorSource.Broadcaster.Unsubscribe(FColorSourceListener); ColorSource.Broadcaster.Unsubscribe(FColorSourceListener);
FColorSource := AValue; FColorSource := AValue;
ColorSource.Broadcaster.Subscribe(FColorSourceListener); ColorSource.Broadcaster.Subscribe(FColorSourceListener);
UpdateColorExtent; ColorSourceChanged(Self);
UpdateParentChart;
end; end;
procedure TCustomColorMapSeries.SetInterpolate(AValue: Boolean); procedure TCustomColorMapSeries.SetInterpolate(AValue: Boolean);
@ -2773,7 +2797,6 @@ begin
if AValue = FPaletteMax then exit; if AValue = FPaletteMax then exit;
FPaletteMax := AValue; FPaletteMax := AValue;
BuildPalette(FBuiltinPalette); BuildPalette(FBuiltinPalette);
UpdateParentChart;
end; end;
procedure TCustomColorMapSeries.SetPaletteMin(AValue: Double); procedure TCustomColorMapSeries.SetPaletteMin(AValue: Double);
@ -2781,7 +2804,6 @@ begin
if AValue = FPaletteMin then exit; if AValue = FPaletteMin then exit;
FPaletteMin := AValue; FPaletteMin := AValue;
BuildPalette(FBuiltinPalette); BuildPalette(FBuiltinPalette);
UpdateParentChart;
end; end;
procedure TCustomColorMapSeries.SetStepX(AValue: TFuncSeriesStep); procedure TCustomColorMapSeries.SetStepX(AValue: TFuncSeriesStep);
@ -2805,6 +2827,19 @@ begin
UpdateParentChart; UpdateParentChart;
end; end;
procedure TCustomColorMapSeries.ColorSourceChanged(ASender: TObject);
begin
if (ASender <> FBuiltinColorSource) and (ASender is TCustomChartSource) then
try
CheckColorSource(TCustomChartSource(ASender));
except
ColorSource := nil; // revert to built-in source
raise;
end;
UpdateColorExtent;
StyleChanged(ASender);
end;
procedure TCustomColorMapSeries.UpdateColorExtent; procedure TCustomColorMapSeries.UpdateColorExtent;
var var
ext: TDoubleRect; ext: TDoubleRect;