mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 11:56:45 +02:00
TAChart: Fix TListChartSource.DataPoints streaming error. Issue #0035125, patch by Marcin Wiazowski. Update test program.
git-svn-id: trunk@60490 -
This commit is contained in:
parent
97462a220d
commit
cd2e076da1
@ -290,6 +290,10 @@ msgstr "Linear"
|
||||
msgid "Line series"
|
||||
msgstr "Linien-Diagramm"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr "Die Anzahl der Datenwerte im %s.DataPoints-String \"%s\" entspricht nicht der, die aufgrund von XCount und YCount erwartet wird."
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Logarithmisch"
|
||||
|
@ -278,6 +278,10 @@ msgstr "Lineaarinen"
|
||||
msgid "Line series"
|
||||
msgstr "Viivakuvaaja"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Logaritminen"
|
||||
|
@ -288,6 +288,10 @@ msgstr "Linéaire"
|
||||
msgid "Line series"
|
||||
msgstr "Séries de lignes"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Logarithmique"
|
||||
|
@ -288,6 +288,10 @@ msgstr "Lineáris"
|
||||
msgid "Line series"
|
||||
msgstr "Vonal"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Logaritmikus"
|
||||
|
@ -289,6 +289,10 @@ msgstr "Tiesinė"
|
||||
msgid "Line series"
|
||||
msgstr "Linijų sekos"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Logaritminė"
|
||||
|
@ -288,6 +288,10 @@ msgstr "Liniowy"
|
||||
msgid "Line series"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Logarytmiczny"
|
||||
|
@ -278,6 +278,10 @@ msgstr ""
|
||||
msgid "Line series"
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr ""
|
||||
|
@ -288,6 +288,10 @@ msgstr "Linear"
|
||||
msgid "Line series"
|
||||
msgstr "Série Linha"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Logarítimo"
|
||||
|
@ -288,6 +288,10 @@ msgstr "Линейный масштаб"
|
||||
msgid "Line series"
|
||||
msgstr "График"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Логарифмический масштаб"
|
||||
|
@ -291,6 +291,10 @@ msgstr "Linjär"
|
||||
msgid "Line series"
|
||||
msgstr "Linjediagram"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Logaritmisk"
|
||||
|
@ -291,6 +291,10 @@ msgstr "Лінійний масштаб"
|
||||
msgid "Line series"
|
||||
msgstr "Графік"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "Логарифмічний масштаб"
|
||||
|
@ -289,6 +289,10 @@ msgstr "线性的(Linear)"
|
||||
msgid "Line series"
|
||||
msgstr "折线图系列"
|
||||
|
||||
#: tachartstrconsts.rslistsourcestringformaterror
|
||||
msgid "The data value count in the %0:s.DataPoints string \"%1:s\" differs from what is expected from XCount and YCount."
|
||||
msgstr ""
|
||||
|
||||
#: tachartstrconsts.rslogarithmic
|
||||
msgid "Logarithmic"
|
||||
msgstr "对数的"
|
||||
|
@ -71,6 +71,9 @@ resourcestring
|
||||
// Chart sources
|
||||
rsSourceCountError = '%0:s requires a chart source with at least %1:d %2:s value(s) per data point.';
|
||||
rsSourceCountError2 = 'This %0:s instance must have at least %1:d %2:s value(s) per data point.';
|
||||
rsListSourceStringFormatError = 'The data value count in the %0:s.DataPoints '+
|
||||
'string "%1:s" differs from what is expected from XCount and YCount.';
|
||||
|
||||
|
||||
// Transformations
|
||||
tasAxisTransformsEditorTitle = 'Edit axis transformations';
|
||||
|
@ -73,6 +73,7 @@ type
|
||||
EEditableSourceRequired = class(EChartError);
|
||||
EXCountError = class(EChartError);
|
||||
EYCountError = class(EChartError);
|
||||
EListSourceStringFormatError = class(EChartError);
|
||||
|
||||
TChartValueText = record
|
||||
FText: String;
|
||||
|
@ -38,6 +38,7 @@ type
|
||||
protected
|
||||
function GetCount: Integer; override;
|
||||
function GetItem(AIndex: Integer): PChartDataItem; override;
|
||||
procedure Loaded; override;
|
||||
procedure SetXCount(AValue: Cardinal); override;
|
||||
procedure SetYCount(AValue: Cardinal); override;
|
||||
public
|
||||
@ -258,7 +259,10 @@ type
|
||||
TListChartSourceStrings = class(TStrings)
|
||||
strict private
|
||||
FSource: TListChartSource;
|
||||
FLoadingCache: TStringList;
|
||||
procedure Parse(AString: String; ADataItem: PChartDataItem);
|
||||
private
|
||||
procedure LoadingFinished;
|
||||
protected
|
||||
function Get(Index: Integer): String; override;
|
||||
function GetCount: Integer; override;
|
||||
@ -266,6 +270,7 @@ type
|
||||
procedure SetUpdateState(AUpdating: Boolean); override;
|
||||
public
|
||||
constructor Create(ASource: TListChartSource);
|
||||
destructor Destroy; override;
|
||||
procedure Clear; override;
|
||||
procedure Delete(Index: Integer); override;
|
||||
procedure Insert(Index: Integer; const S: String); override;
|
||||
@ -284,7 +289,10 @@ end;
|
||||
|
||||
procedure TListChartSourceStrings.Clear;
|
||||
begin
|
||||
FSource.Clear;
|
||||
if not (csLoading in FSource.ComponentState) then
|
||||
FSource.Clear
|
||||
else
|
||||
FreeAndNil(FLoadingCache);
|
||||
end;
|
||||
|
||||
constructor TListChartSourceStrings.Create(ASource: TListChartSource);
|
||||
@ -293,6 +301,12 @@ begin
|
||||
FSource := ASource;
|
||||
end;
|
||||
|
||||
destructor TListChartSourceStrings.Destroy;
|
||||
begin
|
||||
inherited;
|
||||
FLoadingCache.Free;
|
||||
end;
|
||||
|
||||
procedure TListChartSourceStrings.Delete(Index: Integer);
|
||||
begin
|
||||
FSource.Delete(Index);
|
||||
@ -306,29 +320,49 @@ begin
|
||||
fs := DefaultFormatSettings;
|
||||
fs.DecimalSeparator := '.';
|
||||
with FSource[Index]^ do begin
|
||||
Result := Format('%g', [X], fs);
|
||||
Result := '';
|
||||
if FSource.XCount > 0 then
|
||||
Result += Format('%g|', [X], fs);
|
||||
for i := 0 to High(XList) do
|
||||
Result += Format('|%g', [XList[i]], fs);
|
||||
Result += Format('%g|', [XList[i]], fs);
|
||||
if FSource.YCount > 0 then
|
||||
Result += Format('|%g', [Y], fs);
|
||||
Result += Format('%g|', [Y], fs);
|
||||
for i := 0 to High(YList) do
|
||||
Result += Format('|%g', [YList[i]], fs);
|
||||
Result += Format('|%s|%s', [IntToColorHex(Color), Text]);
|
||||
Result += Format('%g|', [YList[i]], fs);
|
||||
Result += Format('%s|%s', [IntToColorHex(Color), Text]);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TListChartSourceStrings.GetCount: Integer;
|
||||
begin
|
||||
Result := FSource.Count;
|
||||
if not (csLoading in FSource.ComponentState) then
|
||||
Result := FSource.Count
|
||||
else
|
||||
if Assigned(FLoadingCache) then
|
||||
Result := FLoadingCache.Count
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
procedure TListChartSourceStrings.Insert(Index: Integer; const S: String);
|
||||
var
|
||||
item: PChartDataItem;
|
||||
begin
|
||||
if csLoading in FSource.ComponentState then begin
|
||||
if not Assigned(FLoadingCache) then
|
||||
FLoadingCache := TStringList.Create;
|
||||
FLoadingCache.Insert(Index, S);
|
||||
exit;
|
||||
end;
|
||||
|
||||
item := FSource.NewItem;
|
||||
FSource.FData.Insert(Index, item);
|
||||
Parse(S, item);
|
||||
try
|
||||
Parse(S, item);
|
||||
FSource.FData.Insert(Index, item);
|
||||
except
|
||||
Dispose(item);
|
||||
raise;
|
||||
end;
|
||||
FSource.UpdateCachesAfterAdd(item^.X, item^.Y);
|
||||
end;
|
||||
|
||||
@ -350,20 +384,33 @@ var
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
// Note: this method is called only when component loading is fully finished -
|
||||
// so FSource.XCount and FSource.YCount are already properly estabilished
|
||||
|
||||
parts := Split(AString);
|
||||
try
|
||||
if (FSource.XCount = 1) and (FSource.YCount + 3 < Cardinal(parts.Count)) then
|
||||
FSource.YCount := parts.Count - 3;
|
||||
// There should be XCount + YCount .. XCount + YCount + 2 (for Color and Text)
|
||||
// parts of the string
|
||||
if (Cardinal(parts.Count) <> FSource.XCount + FSource.YCount + 2) then begin
|
||||
if Length(AString) > 20 then AString := Copy(AString, 1, 20) + '...';
|
||||
raise EListSourceStringFormatError.CreateFmt(
|
||||
rsListSourceStringFormatError,
|
||||
[IfThen(FSource.Name <> '', FSource.Name, FSource.ClassName), AString]);
|
||||
end;
|
||||
|
||||
with ADataItem^ do begin
|
||||
X := StrToFloatOrDateTimeDef(NextPart);
|
||||
if FSource.XCount > 1 then
|
||||
if FSource.XCount > 0 then begin
|
||||
X := StrToFloatOrDateTimeDef(NextPart);
|
||||
for i := 0 to High(XList) do
|
||||
XList[i] := StrToFloatOrDateTimeDef(NextPart);
|
||||
end else
|
||||
X := NaN;
|
||||
if FSource.YCount > 0 then begin
|
||||
Y := StrToFloatOrDateTimeDef(NextPart);
|
||||
for i := 0 to High(YList) do
|
||||
YList[i] := StrToFloatOrDateTimeDef(NextPart);
|
||||
end;
|
||||
end else
|
||||
Y := NaN;
|
||||
Color := StrToIntDef(NextPart, clTAColor);
|
||||
Text := NextPart;
|
||||
end;
|
||||
@ -384,10 +431,22 @@ end;
|
||||
|
||||
procedure TListChartSourceStrings.SetUpdateState(AUpdating: Boolean);
|
||||
begin
|
||||
if AUpdating then
|
||||
FSource.BeginUpdate
|
||||
else
|
||||
FSource.EndUpdate;
|
||||
if not (csLoading in FSource.ComponentState) then
|
||||
if AUpdating then
|
||||
FSource.BeginUpdate
|
||||
else
|
||||
FSource.EndUpdate;
|
||||
end;
|
||||
|
||||
procedure TListChartSourceStrings.LoadingFinished;
|
||||
begin
|
||||
// csLoading in FSource.ComponentState is already cleared
|
||||
if Assigned(FLoadingCache) then
|
||||
try
|
||||
Assign(FLoadingCache);
|
||||
finally
|
||||
FreeAndNil(FLoadingCache);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TListChartSource }
|
||||
@ -781,6 +840,12 @@ begin
|
||||
Notify;
|
||||
end;
|
||||
|
||||
procedure TListChartSource.Loaded;
|
||||
begin
|
||||
inherited; // clears csLoading in ComponentState
|
||||
(FDataPoints as TListChartSourceStrings).LoadingFinished;
|
||||
end;
|
||||
|
||||
{ TMWCRandomGenerator }
|
||||
|
||||
function TMWCRandomGenerator.Get: LongWord;
|
||||
|
@ -369,9 +369,9 @@ begin
|
||||
oldSeparator := DefaultFormatSettings.DecimalSeparator;
|
||||
try
|
||||
DefaultFormatSettings.DecimalSeparator := ':';
|
||||
FSource.DataPoints.Add('3:5');
|
||||
FSource.DataPoints.Add('3:5|?|?|');
|
||||
AssertEquals(3.5, FSource[0]^.X);
|
||||
FSource.DataPoints[0] := '4.5';
|
||||
FSource.DataPoints[0] := '4.5|?|?|';
|
||||
AssertEquals(4.5, FSource[0]^.X);
|
||||
finally
|
||||
DefaultFormatSettings.DecimalSeparator := oldSeparator;
|
||||
@ -453,9 +453,81 @@ procedure TListSourceTest.Multi;
|
||||
begin
|
||||
FSource.Clear;
|
||||
AssertEquals(1, FSource.YCount);
|
||||
AssertEquals(1, FSource.YCount);
|
||||
|
||||
FSource.Add(1, 2);
|
||||
FSource.YCount := 2;
|
||||
AssertEquals([0], FSource[0]^.YList);
|
||||
|
||||
FSource.SetYList(0, [3]);
|
||||
AssertEquals(3, FSource[0]^.YList[0]);
|
||||
|
||||
FSource.DataPoints.Add('1|2|3|?|t');
|
||||
AssertEquals(1, FSource.XCount);
|
||||
AssertEquals(2, FSource.YCount);
|
||||
AssertEquals(1, FSource[1]^.X);
|
||||
AssertEquals(2, FSource[1]^.Y);
|
||||
AssertEquals(3, FSource[1]^.YList[0]);
|
||||
|
||||
try
|
||||
FSource.DataPoints.Add('10|20|30|40|?|');
|
||||
except
|
||||
on E: Exception do
|
||||
AssertTrue('Too many values', E is EListSourceStringFormatError);
|
||||
end;
|
||||
AssertEquals(2, FSource.Count);
|
||||
|
||||
try
|
||||
FSource.DataPoints.Add('10|20|?|');
|
||||
except
|
||||
on E: Exception do
|
||||
AssertTrue('Too few values', E is EListSourceStringFormatError);
|
||||
end;
|
||||
AssertEquals(2, FSource.Count);
|
||||
|
||||
try
|
||||
FSource.DataPoints.Add('10|20|30|?');
|
||||
except
|
||||
on E: Exception do
|
||||
AssertTrue('Text field missing', E is EListSourceStringFormatError);
|
||||
end;
|
||||
AssertEquals(2, FSource.Count);
|
||||
|
||||
try
|
||||
FSource.DataPoints.Add('10|20|30|t');
|
||||
except
|
||||
on E: Exception do
|
||||
AssertTrue('Color field missing', E is EListSourceStringFormatError);
|
||||
end;
|
||||
AssertEquals(2, FSource.Count);
|
||||
|
||||
try
|
||||
FSource.AddXYList(4, []);
|
||||
except
|
||||
on E: Exception do
|
||||
AssertTrue('Empty YList', E is TListChartSource.EYListEmptyError);
|
||||
end;
|
||||
|
||||
FSource.Clear;
|
||||
FSource.XCount := 2;
|
||||
FSource.YCount := 3;
|
||||
FSource.AddXListYList([1, 2], [3, 4, 5]);
|
||||
AssertEquals(2, FSource.XCount);
|
||||
AssertEquals(3, FSource.YCount);
|
||||
AssertEquals(1, FSource[0]^.X);
|
||||
AssertEquals(2, FSource[0]^.XList[0]);
|
||||
AssertEquals(3, FSource[0]^.Y);
|
||||
AssertEquals(4, FSource[0]^.YList[0]);
|
||||
AssertEquals(5, FSource[0]^.YList[1]);
|
||||
|
||||
FSource.DataPoints.Add('10|20|30|40|50|?|t');
|
||||
AssertEquals(10, FSource[1]^.X);
|
||||
AssertEquals(20, FSource[1]^.XList[0]);
|
||||
AssertEquals(30, FSource[1]^.Y);
|
||||
AssertEquals(40, FSource[1]^.YList[0]);
|
||||
AssertEquals(50, FSource[1]^.YList[1]);
|
||||
|
||||
(*
|
||||
FSource.SetYList(0, [3, 4]);
|
||||
AssertEquals('Extra items are chopped', [3], FSource[0]^.YList);
|
||||
FSource.DataPoints.Add('1|2|3|4|?|t');
|
||||
@ -478,6 +550,7 @@ begin
|
||||
except on E: Exception do
|
||||
AssertTrue('Empty YList', E is TListChartSource.EYListEmptyError);
|
||||
end;
|
||||
*)
|
||||
end;
|
||||
|
||||
procedure TListSourceTest.SetUp;
|
||||
|
@ -24,9 +24,6 @@
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<IgnoreBinaries Value="False"/>
|
||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<FormatVersion Value="2"/>
|
||||
@ -85,7 +82,7 @@
|
||||
</CodeGeneration>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="4">
|
||||
<Exceptions Count="5">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
</Item1>
|
||||
@ -98,6 +95,9 @@
|
||||
<Item4>
|
||||
<Name Value="TListChartSource.EYListEmptyError"/>
|
||||
</Item4>
|
||||
<Item5>
|
||||
<Name Value="EListSourceStringFormatError"/>
|
||||
</Item5>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
||||
|
Loading…
Reference in New Issue
Block a user