Chart X grid, standard timeframes

This commit is contained in:
Michael Schimmel
2025-07-13 21:49:42 +02:00
parent 840904e42d
commit 4d67d9acbe
8 changed files with 619 additions and 165 deletions
+80 -14
View File
@@ -1,4 +1,4 @@
unit Myc.FMX.Chart.Series;
unit Myc.Fmx.Chart.Series;
interface
@@ -58,14 +58,14 @@ type
end;
{ TChartCustomLayer }
TChartCustomLayer<T> = class(TMycChart.TLayer)
TChartCustomLayer<T> = class abstract(TMycChart.TDataLayer)
private
FSeries: TChartSeriesProcessor<T>;
protected
function GetSeries: TMycChart.TSeries; override;
function GetValueRange(First, Last: Int64; out MinValue, MaxValue: Double): Boolean; override;
function GetValueRange(First, Last: Int64; out MinValue, MaxValue: Double): Boolean; override; abstract;
procedure Update; override;
procedure Paint(const Canvas: TCanvas; First, Last: Int64; const XForm, YForm: TFunc<Double, Single>); override;
procedure Paint(const Canvas: TCanvas; First, Last: Int64; const XForm, YForm: TFunc<Double, Single>); override; abstract;
public
constructor Create(AParent: TMycChart.TPanel; const ADataProvider: IMycDataProvider<T>);
destructor Destroy; override;
@@ -104,6 +104,30 @@ type
);
end;
{ TChartXAxisLayer }
TChartXAxisLayer<T> = class(TMycChart.TXAxisLayer)
private
FSeries: TChartSeriesProcessor<T>;
protected
function GetSeries: TMycChart.TSeries; override;
procedure Update; override;
function GetCaption(Idx: Int64): String; override; abstract;
public
constructor Create(AOwner: TMycChart; const ADataProvider: IMycDataProvider<T>);
destructor Destroy; override;
end;
{ TChartXAxisTimestampLayer }
TChartXAxisTimestampLayer = class(TChartXAxisLayer<TDateTime>)
private
FTimeframe: TTimeframe;
protected
// Provide a formatted timestamp string for a given data index.
function GetCaption(Idx: Int64): String; override; final;
public
constructor Create(AOwner: TMycChart; ATimeframe: TTimeframe; const ADataProvider: IMycDataProvider<TDateTime>);
end;
implementation
uses
@@ -320,19 +344,61 @@ begin
Result := FSeries;
end;
function TChartCustomLayer<T>.GetValueRange(First, Last: Int64; out MinValue, MaxValue: Double): Boolean;
begin
Result := false;
end;
procedure TChartCustomLayer<T>.Paint(const Canvas: TCanvas; First, Last: Int64; const XForm, YForm: TFunc<Double, Single>);
begin
// nope
end;
procedure TChartCustomLayer<T>.Update;
begin
FSeries.Update;
end;
{ TChartXAxisLayer }
constructor TChartXAxisLayer<T>.Create(AOwner: TMycChart; const ADataProvider: IMycDataProvider<T>);
begin
inherited Create(AOwner);
FSeries := TChartSeriesProcessor<T>.Create(ADataProvider, AOwner.Lookback.AsMutable);
end;
destructor TChartXAxisLayer<T>.Destroy;
begin
FSeries.Free;
inherited;
end;
function TChartXAxisLayer<T>.GetSeries: TMycChart.TSeries;
begin
Result := FSeries;
end;
procedure TChartXAxisLayer<T>.Update;
begin
FSeries.Update;
end;
constructor TChartXAxisTimestampLayer.Create(AOwner: TMycChart; ATimeframe: TTimeframe; const ADataProvider: IMycDataProvider<TDateTime>);
begin
inherited Create(AOwner, ADataProvider);
FTimeframe := ATimeframe;
end;
function TChartXAxisTimestampLayer.GetCaption(Idx: Int64): String;
var
dt: TDateTime;
formatStr: string;
begin
Result := '';
if (Idx >= 0) and (Idx < FSeries.Count) then
begin
dt := FSeries.Data[Idx];
// Choose format based on the series timeframe.
if FTimeframe >= D then // Daily, Weekly, Monthly, Yearly
formatStr := 'dd.mm.yyyy'
else if FTimeframe >= M then // Hourly + Minutes
formatStr := 'dd.mm.yyyy hh:nn'
else // Seconds
formatStr := 'dd.mm.yyyy hh:nn:ss';
Result := FormatDateTime(formatStr, dt);
end;
end;
end.