mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-30 17:11:59 +02:00
TAChart: Fix incomplete support of multiple x values in TListChartSource and DataPointEditor. Issue #35089.
git-svn-id: trunk@60425 -
This commit is contained in:
parent
71a8ee49c6
commit
7c5fdfc1d4
@ -2,48 +2,50 @@ object DataPointsEditorForm: TDataPointsEditorForm
|
||||
Left = 418
|
||||
Height = 303
|
||||
Top = 235
|
||||
Width = 357
|
||||
Width = 288
|
||||
ClientHeight = 303
|
||||
ClientWidth = 357
|
||||
ClientWidth = 288
|
||||
OnCreate = FormCreate
|
||||
LCLVersion = '1.7'
|
||||
Position = poScreenCenter
|
||||
ShowHint = True
|
||||
LCLVersion = '2.1.0.0'
|
||||
object sgData: TStringGrid
|
||||
Left = 0
|
||||
Height = 257
|
||||
Top = 0
|
||||
Width = 357
|
||||
Left = 6
|
||||
Height = 251
|
||||
Top = 6
|
||||
Width = 276
|
||||
Align = alClient
|
||||
AutoFillColumns = True
|
||||
BorderSpacing.Around = 6
|
||||
Columns = <
|
||||
item
|
||||
Alignment = taRightJustify
|
||||
Title.Alignment = taCenter
|
||||
Title.Font.Style = [fsBold]
|
||||
Title.Caption = 'X'
|
||||
Width = 80
|
||||
Width = 63
|
||||
end
|
||||
item
|
||||
Alignment = taRightJustify
|
||||
Title.Alignment = taCenter
|
||||
Title.Font.Style = [fsBold]
|
||||
Title.Caption = 'Y'
|
||||
Width = 80
|
||||
Width = 63
|
||||
end
|
||||
item
|
||||
ButtonStyle = cbsEllipsis
|
||||
Title.Alignment = taCenter
|
||||
Title.Font.Style = [fsBold]
|
||||
Title.Caption = 'Color'
|
||||
Width = 80
|
||||
Width = 63
|
||||
end
|
||||
item
|
||||
Title.Alignment = taCenter
|
||||
Title.Font.Style = [fsBold]
|
||||
Title.Caption = 'Text'
|
||||
Width = 81
|
||||
Width = 63
|
||||
end>
|
||||
DefaultColWidth = 32
|
||||
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goRowMoving, goEditing, goAutoAddRows, goAlwaysShowEditor, goSmoothScroll, goFixedRowNumbering]
|
||||
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goRowMoving, goEditing, goAutoAddRows, goAlwaysShowEditor, goSmoothScroll, goFixedRowNumbering, goTruncCellHints, goCellEllipsis]
|
||||
PopupMenu = pmRows
|
||||
TabOrder = 0
|
||||
OnDrawCell = sgDataDrawCell
|
||||
@ -51,17 +53,17 @@ object DataPointsEditorForm: TDataPointsEditorForm
|
||||
OnPrepareCanvas = sgDataPrepareCanvas
|
||||
ColWidths = (
|
||||
32
|
||||
80
|
||||
80
|
||||
80
|
||||
81
|
||||
63
|
||||
63
|
||||
63
|
||||
63
|
||||
)
|
||||
end
|
||||
object ButtonPanel1: TButtonPanel
|
||||
Left = 6
|
||||
Height = 34
|
||||
Top = 263
|
||||
Width = 345
|
||||
Width = 276
|
||||
OKButton.Name = 'OKButton'
|
||||
OKButton.DefaultCaption = True
|
||||
HelpButton.Name = 'HelpButton'
|
||||
|
@ -41,9 +41,10 @@ type
|
||||
strict private
|
||||
FCurrentRow: Integer;
|
||||
FDataPoints: TStrings;
|
||||
FXCount: Integer;
|
||||
FYCount: Integer;
|
||||
public
|
||||
procedure InitData(AYCount: Integer; ADataPoints: TStrings);
|
||||
procedure InitData(AXCount, AYCount: Integer; ADataPoints: TStrings);
|
||||
procedure ExtractData(out AModified: Boolean);
|
||||
end;
|
||||
|
||||
@ -52,7 +53,7 @@ procedure Register;
|
||||
implementation
|
||||
|
||||
uses
|
||||
LCLIntf, Math, PropEdits,
|
||||
LCLIntf, LCLType, Math, PropEdits,
|
||||
TAChartStrConsts, TAChartUtils, TASources;
|
||||
|
||||
{$R *.lfm}
|
||||
@ -100,26 +101,47 @@ begin
|
||||
end;
|
||||
|
||||
procedure TDataPointsEditorForm.InitData(
|
||||
AYCount: Integer; ADataPoints: TStrings);
|
||||
AXCount, AYCount: Integer; ADataPoints: TStrings);
|
||||
var
|
||||
i: Integer;
|
||||
w: Integer;
|
||||
begin
|
||||
FXCount := AXCount;
|
||||
FYCount := AYCount;
|
||||
FDataPoints := ADataPoints;
|
||||
sgData.RowCount := Max(ADataPoints.Count + 1, 2);
|
||||
{ wp: What is this good for?
|
||||
for i := sgData.Columns.Count - 1 downto 0 do
|
||||
with sgData.Columns[i].Title do
|
||||
if (Caption[1] = 'Y') and (Caption <> 'Y') then
|
||||
sgData.Columns.Delete(i);
|
||||
for i := 2 to AYCount do begin
|
||||
}
|
||||
if AXCount > 1 then
|
||||
sgData.Columns[0].Title.Caption := 'X1';
|
||||
if AYCount > 1 then
|
||||
sgData.Columns[1].Title.Caption := 'Y1';
|
||||
for i := 2 to AYCount do
|
||||
with sgData.Columns.Add do begin
|
||||
Assign(sgData.Columns[1]);
|
||||
Title.Caption := 'Y' + IntToStr(i);
|
||||
Index := i;
|
||||
end;
|
||||
end;
|
||||
for i := 2 to AXCount do
|
||||
with sgData.Columns.Add do begin
|
||||
Assign(sgData.Columns[0]);
|
||||
Title.Caption := 'X' + IntToStr(i);
|
||||
Index := i - 1;
|
||||
end;
|
||||
for i := 0 to ADataPoints.Count - 1 do
|
||||
Split('|' + ADataPoints[i], sgData.Rows[i + 1])
|
||||
Split('|' + ADataPoints[i], sgData.Rows[i + 1]);
|
||||
|
||||
// Adjust column widths
|
||||
w := sgData.Canvas.TextWidth('$000000') + 3*varCellPadding + sgData.DefaultRowHeight;
|
||||
for i := 0 to sgData.Columns.Count-1 do
|
||||
sgData.Columns[i].Width := w;
|
||||
|
||||
Width := sgData.ColWidths[0] + sgData.Columns.Count * w + 2*sgData.Left +
|
||||
sgData.GridLineWidth * (sgData.Columns.Count-1);
|
||||
end;
|
||||
|
||||
procedure TDataPointsEditorForm.miDeleteRowClick(Sender: TObject);
|
||||
@ -158,7 +180,7 @@ procedure TDataPointsEditorForm.sgDataButtonClick(
|
||||
ASender: TObject; ACol, ARow: Integer);
|
||||
begin
|
||||
Unused(ASender);
|
||||
if (ARow < 1) or (ACol <> FYCount + 2) then exit;
|
||||
if (ARow < 1) or (ACol <> FXCount + FYCount + 1) then exit;
|
||||
cdItemColor.Color := StrToIntDef(sgData.Cells[ACol, ARow], clRed);
|
||||
if not cdItemColor.Execute then exit;
|
||||
sgData.Cells[ACol, ARow] := IntToColorHex(cdItemColor.Color);
|
||||
@ -170,12 +192,12 @@ var
|
||||
c: Integer;
|
||||
begin
|
||||
Unused(ASender, AState);
|
||||
if (ARow < 1) or (ACol <> FYCount + 2) then exit;
|
||||
if (ARow < 1) or (ACol <> FXCount + FYCount + 1) then exit;
|
||||
if not TryStrToInt(sgData.Cells[ACol, ARow], c) then exit;
|
||||
sgData.Canvas.Pen.Color := clBlack;
|
||||
sgData.Canvas.Brush.Color := c;
|
||||
InflateRect(ARect, -2, -2);
|
||||
ARect.Left := ARect.Right - 12;
|
||||
InflateRect(ARect, -varCellPadding, -varCellPadding);
|
||||
ARect.Left := ARect.Right - (ARect.Bottom - ARect.Top);;
|
||||
sgData.Canvas.Rectangle(ARect);
|
||||
end;
|
||||
|
||||
@ -201,8 +223,10 @@ begin
|
||||
with TDataPointsEditorForm.Create(nil) do
|
||||
try
|
||||
InitData(
|
||||
(GetComponent(0) as TListChartsource).XCount,
|
||||
(GetComponent(0) as TListChartSource).YCount,
|
||||
GetObjectValue as TStrings);
|
||||
GetObjectValue as TStrings
|
||||
);
|
||||
if ShowModal = mrOK then begin
|
||||
ExtractData(dataModified);
|
||||
if dataModified then Modified;
|
||||
|
@ -93,7 +93,7 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
GraphType, Math, LCLIntf, LCLType, IntfGraphics,
|
||||
GraphType, LCLIntf, LCLType, IntfGraphics,
|
||||
TAGeometry;
|
||||
|
||||
function CanvasGetFontOrientationFunc(AFont: TFPCustomFont): Integer;
|
||||
|
@ -1620,28 +1620,28 @@ begin
|
||||
if not RectIntersectsRect(ext, ParentChart.CurrentExtent) then exit;
|
||||
|
||||
lPen := TPen.Create;
|
||||
lPen.Assign(FPen);
|
||||
|
||||
if (AxisIndexX < 0) and (AxisIndexY < 0) then begin
|
||||
// Optimization: bypass transformations in the default case
|
||||
for i := 0 to Count - 1 do
|
||||
if GetVectorPoints(i, p1, p2) then begin
|
||||
lPen.Color := GetColor(i);
|
||||
DrawVector(ADrawer, p1, p2, lPen);
|
||||
end;
|
||||
end else begin
|
||||
for i := 0 to Count - 1 do
|
||||
if GetVectorPoints(i, p1, p2) then begin
|
||||
p1 := AxisToGraph(p1);
|
||||
p2 := AxisToGraph(p2);
|
||||
//p1 := DoublePoint(AxisToGraphX(p1.X), AxisToGraphY(p1.Y));
|
||||
//p2 := DoublePoint(AxisToGraphX(p2.X), AxisToGraphY(p2.Y));
|
||||
lPen.Color := GetColor(i);
|
||||
DrawVector(ADrawer, p1, p2, lPen);
|
||||
end;
|
||||
try
|
||||
lPen.Assign(FPen);
|
||||
if (AxisIndexX < 0) and (AxisIndexY < 0) then begin
|
||||
// Optimization: bypass transformations in the default case
|
||||
for i := 0 to Count - 1 do
|
||||
if GetVectorPoints(i, p1, p2) then begin
|
||||
lPen.Color := GetColor(i);
|
||||
DrawVector(ADrawer, p1, p2, lPen);
|
||||
end;
|
||||
end else begin
|
||||
for i := 0 to Count - 1 do
|
||||
if GetVectorPoints(i, p1, p2) then begin
|
||||
p1 := AxisToGraph(p1);
|
||||
p2 := AxisToGraph(p2);
|
||||
lPen.Color := GetColor(i);
|
||||
DrawVector(ADrawer, p1, p2, lPen);
|
||||
end;
|
||||
end;
|
||||
DrawLabels(ADrawer);
|
||||
finally
|
||||
lPen.Free;
|
||||
end;
|
||||
|
||||
lPen.Free;
|
||||
end;
|
||||
|
||||
procedure TFieldSeries.DrawVector(ADrawer: IChartDrawer;
|
||||
|
@ -1671,7 +1671,7 @@ var
|
||||
|
||||
procedure CollectPoints(AStart, AEnd: Integer);
|
||||
var
|
||||
i, j: Integer;
|
||||
i: Integer;
|
||||
a, b: TDoublePoint;
|
||||
singlePoint: Boolean;
|
||||
begin
|
||||
|
@ -41,6 +41,7 @@ type
|
||||
procedure SetYCount(AValue: Cardinal); override;
|
||||
public
|
||||
type
|
||||
EXListEmptyError = class(EChartError);
|
||||
EYListEmptyError = class(EChartError);
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
@ -49,6 +50,8 @@ type
|
||||
function Add(
|
||||
AX, AY: Double; const ALabel: String = '';
|
||||
AColor: TChartColor = clTAColor): Integer;
|
||||
function AddXListYList(const AX, AY: array of Double; ALabel: String = '';
|
||||
AColor: TChartColor = clTAColor): Integer;
|
||||
function AddXYList(
|
||||
AX: Double; const AY: array of Double; const ALabel: String = '';
|
||||
AColor: TChartColor = clTAColor): Integer;
|
||||
@ -68,6 +71,7 @@ type
|
||||
published
|
||||
property DataPoints: TStrings read FDataPoints write SetDataPoints;
|
||||
property Sorted: Boolean read FSorted write SetSorted default false;
|
||||
property XCount;
|
||||
property XErrorBarData;
|
||||
property YErrorBarData;
|
||||
property YCount;
|
||||
@ -301,6 +305,8 @@ begin
|
||||
fs.DecimalSeparator := '.';
|
||||
with FSource[Index]^ do begin
|
||||
Result := Format('%g', [X], fs);
|
||||
for i := 0 to High(XList) do
|
||||
Result += Format('|%g', [XList[i]], fs);
|
||||
if FSource.YCount > 0 then
|
||||
Result += Format('|%g', [Y], fs);
|
||||
for i := 0 to High(YList) do
|
||||
@ -344,10 +350,13 @@ var
|
||||
begin
|
||||
parts := Split(AString);
|
||||
try
|
||||
if FSource.YCount + 3 < Cardinal(parts.Count) then
|
||||
if (FSource.XCount = 1) and (FSource.YCount + 3 < Cardinal(parts.Count)) then
|
||||
FSource.YCount := parts.Count - 3;
|
||||
with ADataItem^ do begin
|
||||
X := StrToFloatOrDateTimeDef(NextPart);
|
||||
if FSource.XCount > 1 then
|
||||
for i := 0 to High(XList) do
|
||||
XList[i] := StrToFloatOrDateTimeDef(NextPart);
|
||||
if FSource.YCount > 0 then begin
|
||||
Y := StrToFloatOrDateTimeDef(NextPart);
|
||||
for i := 0 to High(YList) do
|
||||
@ -365,7 +374,7 @@ procedure TListChartSourceStrings.Put(Index: Integer; const S: String);
|
||||
begin
|
||||
FSource.BeginUpdate;
|
||||
try
|
||||
Parse(S, FSource[Index]);
|
||||
Parse(S, FSource[Index]);
|
||||
finally
|
||||
FSource.EndUpdate;
|
||||
end;
|
||||
@ -410,6 +419,20 @@ begin
|
||||
UpdateCachesAfterAdd(AX, AY);
|
||||
end;
|
||||
|
||||
function TListChartSource.AddXListYList(const AX, AY: array of Double;
|
||||
ALabel: String = ''; AColor: TChartColor = clTAColor): Integer;
|
||||
begin
|
||||
if Length(AX) = 0 then
|
||||
raise EXListEmptyError.Create('AddXListYList: XList is empty');
|
||||
if Length(AY) = 0 then
|
||||
raise EYListEmptyError.Create('AddXListYList: YList is empty');
|
||||
Result := Add(AX[0], AY[0], ALabel, AColor);
|
||||
if Length(AX) > 1 then
|
||||
SetXList(Result, AX[1..High(AX)]);
|
||||
if Length(AY) > 1 then
|
||||
SetYList(Result, AY[1..High(AY)]);
|
||||
end;
|
||||
|
||||
function TListChartSource.AddXYList(
|
||||
AX: Double; const AY: array of Double;
|
||||
const ALabel: String; AColor: TChartColor): Integer;
|
||||
|
Loading…
Reference in New Issue
Block a user