mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-21 18:08:39 +02:00
TAChart: Start implementation of IChartDrawer interface
git-svn-id: trunk@29519 -
This commit is contained in:
parent
09d05b6a3c
commit
2acf57df8d
@ -21,7 +21,10 @@ unit TADrawUtils;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, Graphics, SysUtils, Types;
|
Classes, Graphics, FPCanvas, SysUtils, Types;
|
||||||
|
|
||||||
|
type
|
||||||
|
TChartColor = -$7FFFFFFF-1..$7FFFFFFF;
|
||||||
|
|
||||||
const
|
const
|
||||||
Colors: array [1..15] of TColor = (
|
Colors: array [1..15] of TColor = (
|
||||||
@ -29,6 +32,8 @@ const
|
|||||||
clTeal, clNavy, clMaroon, clLime, clOlive, clPurple, clSilver, clAqua);
|
clTeal, clNavy, clMaroon, clLime, clOlive, clPurple, clSilver, clAqua);
|
||||||
|
|
||||||
type
|
type
|
||||||
|
//TCanvas = TFPCustomCanvas;
|
||||||
|
|
||||||
TPenBrushFont = set of (pbfPen, pbfBrush, pbfFont);
|
TPenBrushFont = set of (pbfPen, pbfBrush, pbfFont);
|
||||||
|
|
||||||
{ TPenBrushFontRecall }
|
{ TPenBrushFontRecall }
|
||||||
@ -45,6 +50,35 @@ type
|
|||||||
procedure Recall;
|
procedure Recall;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
IChartDrawer = interface
|
||||||
|
function GetCanvas: TCanvas;
|
||||||
|
procedure PrepareSimplePen(AColor: TChartColor);
|
||||||
|
procedure Rectangle(const ARect: TRect);
|
||||||
|
procedure SetBrush(APen: TFPCustomBrush);
|
||||||
|
procedure SetBrushParams(AStyle: TBrushStyle; AColor: TChartColor);
|
||||||
|
procedure SetPen(APen: TFPCustomPen);
|
||||||
|
|
||||||
|
property Brush: TFPCustomBrush write SetBrush;
|
||||||
|
property Canvas: TCanvas read GetCanvas;
|
||||||
|
property Pen: TFPCustomPen write SetPen;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TCanvasDrawer }
|
||||||
|
|
||||||
|
TCanvasDrawer = class(TInterfacedObject, IChartDrawer)
|
||||||
|
private
|
||||||
|
FCanvas: TCanvas;
|
||||||
|
procedure SetBrush(ABrush: TFPCustomBrush);
|
||||||
|
procedure SetPen(APen: TFPCustomPen);
|
||||||
|
public
|
||||||
|
constructor Create(ACanvas: TCanvas);
|
||||||
|
function GetCanvas: TCanvas;
|
||||||
|
|
||||||
|
procedure PrepareSimplePen(AColor: TChartColor);
|
||||||
|
procedure Rectangle(const ARect: TRect);
|
||||||
|
procedure SetBrushParams(AStyle: TBrushStyle; AColor: TChartColor);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure DrawLineDepth(ACanvas: TCanvas; AX1, AY1, AX2, AY2, ADepth: Integer);
|
procedure DrawLineDepth(ACanvas: TCanvas; AX1, AY1, AX2, AY2, ADepth: Integer);
|
||||||
procedure DrawLineDepth(ACanvas: TCanvas; const AP1, AP2: TPoint; ADepth: Integer);
|
procedure DrawLineDepth(ACanvas: TCanvas; const AP1, AP2: TPoint; ADepth: Integer);
|
||||||
|
|
||||||
@ -175,6 +209,45 @@ begin
|
|||||||
Result := ACanvas.TextHeight(TYPICAL_TEXT);
|
Result := ACanvas.TextHeight(TYPICAL_TEXT);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TCanvasDrawer }
|
||||||
|
|
||||||
|
constructor TCanvasDrawer.Create(ACanvas: TCanvas);
|
||||||
|
begin
|
||||||
|
FCanvas := ACanvas;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCanvasDrawer.GetCanvas: TCanvas;
|
||||||
|
begin
|
||||||
|
Result := FCanvas;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCanvasDrawer.PrepareSimplePen(AColor: TChartColor);
|
||||||
|
begin
|
||||||
|
TADrawUtils.PrepareSimplePen(FCanvas, AColor);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCanvasDrawer.Rectangle(const ARect: TRect);
|
||||||
|
begin
|
||||||
|
FCanvas.Rectangle(ARect);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCanvasDrawer.SetBrush(ABrush: TFPCustomBrush);
|
||||||
|
begin
|
||||||
|
FCanvas.Brush.Assign(ABrush);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCanvasDrawer.SetBrushParams(
|
||||||
|
AStyle: TBrushStyle; AColor: TChartColor);
|
||||||
|
begin
|
||||||
|
FCanvas.Brush.Style := AStyle;
|
||||||
|
FCanvas.Brush.Color := AColor;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCanvasDrawer.SetPen(APen: TFPCustomPen);
|
||||||
|
begin
|
||||||
|
FCanvas.Pen.Assign(APen);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPenBrushFontRecall }
|
{ TPenBrushFontRecall }
|
||||||
|
|
||||||
constructor TPenBrushFontRecall.Create(ACanvas: TCanvas; AParams: TPenBrushFont);
|
constructor TPenBrushFontRecall.Create(ACanvas: TCanvas; AParams: TPenBrushFont);
|
||||||
|
@ -29,7 +29,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Graphics, Classes, Controls, LCLType, SysUtils,
|
Graphics, Classes, Controls, LCLType, SysUtils,
|
||||||
TAChartAxis, TAChartUtils, TALegend, TATypes;
|
TAChartAxis, TAChartUtils, TADrawUtils, TALegend, TATypes;
|
||||||
|
|
||||||
type
|
type
|
||||||
TChart = class;
|
TChart = class;
|
||||||
@ -78,7 +78,8 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
public
|
public
|
||||||
procedure Draw(ACanvas: TCanvas); virtual; abstract;
|
procedure Draw(ADrawer: IChartDrawer); virtual;
|
||||||
|
procedure Draw(ACanvas: TCanvas); virtual;
|
||||||
function IsEmpty: Boolean; virtual; abstract;
|
function IsEmpty: Boolean; virtual; abstract;
|
||||||
procedure MovePoint(var AIndex: Integer; const ANewPos: TPoint); virtual;
|
procedure MovePoint(var AIndex: Integer; const ANewPos: TPoint); virtual;
|
||||||
|
|
||||||
@ -214,8 +215,8 @@ type
|
|||||||
procedure VisitSources(
|
procedure VisitSources(
|
||||||
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData);
|
AVisitor: TChartOnSourceVisitor; AAxis: TChartAxis; var AData);
|
||||||
protected
|
protected
|
||||||
procedure Clear(ACanvas: TCanvas; const ARect: TRect);
|
procedure Clear(ADrawer: IChartDrawer; const ARect: TRect);
|
||||||
procedure DisplaySeries(ACanvas: TCanvas);
|
procedure DisplaySeries(ADrawer: IChartDrawer);
|
||||||
procedure DrawBackWall(ACanvas: TCanvas);
|
procedure DrawBackWall(ACanvas: TCanvas);
|
||||||
procedure DrawTitleFoot(ACanvas: TCanvas);
|
procedure DrawTitleFoot(ACanvas: TCanvas);
|
||||||
procedure MouseDown(
|
procedure MouseDown(
|
||||||
@ -251,6 +252,7 @@ type
|
|||||||
function Clone: TChart;
|
function Clone: TChart;
|
||||||
procedure CopyToClipboardBitmap;
|
procedure CopyToClipboardBitmap;
|
||||||
procedure DeleteSeries(ASeries: TBasicChartSeries);
|
procedure DeleteSeries(ASeries: TBasicChartSeries);
|
||||||
|
procedure Draw(ADrawer: IChartDrawer; const ARect: TRect);
|
||||||
procedure DrawLegendOn(ACanvas: TCanvas; var ARect: TRect);
|
procedure DrawLegendOn(ACanvas: TCanvas; var ARect: TRect);
|
||||||
function GetFullExtent: TDoubleRect;
|
function GetFullExtent: TDoubleRect;
|
||||||
procedure PaintOnCanvas(ACanvas: TCanvas; ARect: TRect);
|
procedure PaintOnCanvas(ACanvas: TCanvas; ARect: TRect);
|
||||||
@ -354,7 +356,7 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Clipbrd, Dialogs, GraphMath, LCLProc, LResources, Math, TADrawUtils, Types;
|
Clipbrd, Dialogs, GraphMath, LCLProc, LResources, Math, Types;
|
||||||
|
|
||||||
function CompareZPosition(AItem1, AItem2: Pointer): Integer;
|
function CompareZPosition(AItem1, AItem2: Pointer): Integer;
|
||||||
begin
|
begin
|
||||||
@ -539,41 +541,10 @@ end;
|
|||||||
|
|
||||||
procedure TChart.PaintOnCanvas(ACanvas: TCanvas; ARect: TRect);
|
procedure TChart.PaintOnCanvas(ACanvas: TCanvas; ARect: TRect);
|
||||||
var
|
var
|
||||||
i: Integer;
|
drawer: IChartDrawer;
|
||||||
legendItems: TChartLegendItems = nil;
|
|
||||||
legendRect: TRect;
|
|
||||||
begin
|
begin
|
||||||
Clear(ACanvas, ARect);
|
drawer := TCanvasDrawer.Create(ACanvas);
|
||||||
|
Draw(drawer, ARect);
|
||||||
FClipRect := ARect;
|
|
||||||
InflateRect(FClipRect, -2, -2);
|
|
||||||
|
|
||||||
for i := 0 to AxisList.Count - 1 do
|
|
||||||
with AxisList[i] do
|
|
||||||
if Transformations <> nil then
|
|
||||||
Transformations.SetChart(Self);
|
|
||||||
for i := 0 to SeriesCount - 1 do
|
|
||||||
Series[i].BeforeDraw;
|
|
||||||
|
|
||||||
if not FIsZoomed then
|
|
||||||
FLogicalExtent := GetFullExtent;
|
|
||||||
FCurrentExtent := FLogicalExtent;
|
|
||||||
DrawTitleFoot(ACanvas);
|
|
||||||
if Legend.Visible then
|
|
||||||
PrepareLegend(ACanvas, legendItems, FClipRect, legendRect);
|
|
||||||
try
|
|
||||||
PrepareAxis(ACanvas);
|
|
||||||
DrawBackWall(ACanvas);
|
|
||||||
DisplaySeries(ACanvas);
|
|
||||||
if Legend.Visible then
|
|
||||||
Legend.Draw(ACanvas, legendItems, legendRect);
|
|
||||||
finally
|
|
||||||
legendItems.Free;
|
|
||||||
end;
|
|
||||||
DrawReticule(ACanvas);
|
|
||||||
|
|
||||||
for i := 0 to SeriesCount - 1 do
|
|
||||||
Series[i].AfterDraw;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChart.PrepareLegend(
|
procedure TChart.PrepareLegend(
|
||||||
@ -652,19 +623,18 @@ begin
|
|||||||
rY.UpdateMinMax(@YImageToGraph);
|
rY.UpdateMinMax(@YImageToGraph);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChart.Clear(ACanvas: TCanvas; const ARect: TRect);
|
procedure TChart.Clear(ADrawer: IChartDrawer; const ARect: TRect);
|
||||||
var
|
var
|
||||||
defaultDrawing: Boolean = true;
|
defaultDrawing: Boolean = true;
|
||||||
begin
|
begin
|
||||||
PrepareSimplePen(ACanvas, Color);
|
ADrawer.PrepareSimplePen(Color);
|
||||||
ACanvas.Brush.Color := Color;
|
ADrawer.SetBrushParams(bsSolid, Color);
|
||||||
ACanvas.Brush.Style := bsSolid;
|
if (ADrawer.Canvas <> nil) and Assigned(OnBeforeDrawBackground) then
|
||||||
if Assigned(OnBeforeDrawBackground) then
|
OnBeforeDrawBackground(Self, ADrawer.Canvas, ARect, defaultDrawing);
|
||||||
OnBeforeDrawBackground(Self, ACanvas, ARect, defaultDrawing);
|
|
||||||
if defaultDrawing then
|
if defaultDrawing then
|
||||||
ACanvas.Rectangle(ARect);
|
ADrawer.Rectangle(ARect);
|
||||||
if Assigned(OnAfterDrawBackground) then
|
if (ADrawer.Canvas <> nil) and Assigned(OnAfterDrawBackground) then
|
||||||
OnAfterDrawBackground(Self, ACanvas, ARect);
|
OnAfterDrawBackground(Self, ADrawer.Canvas, ARect);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChart.ClearSeries;
|
procedure TChart.ClearSeries;
|
||||||
@ -901,7 +871,7 @@ begin
|
|||||||
PaintOnCanvas(ACanvas, Rect);
|
PaintOnCanvas(ACanvas, Rect);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChart.DisplaySeries(ACanvas: TCanvas);
|
procedure TChart.DisplaySeries(ADrawer: IChartDrawer);
|
||||||
|
|
||||||
procedure OffsetDrawArea(AZPos, ADepth: Integer);
|
procedure OffsetDrawArea(AZPos, ADepth: Integer);
|
||||||
begin
|
begin
|
||||||
@ -928,27 +898,66 @@ begin
|
|||||||
with TBasicChartSeries(seriesInZOrder[i]) do begin
|
with TBasicChartSeries(seriesInZOrder[i]) do begin
|
||||||
if not Active then continue;
|
if not Active then continue;
|
||||||
// Interleave axises with series according to ZPosition.
|
// Interleave axises with series according to ZPosition.
|
||||||
AxisList.Draw(ACanvas, FClipRect, Self, ZPosition, d, axisIndex);
|
AxisList.Draw(ADrawer.Canvas, FClipRect, Self, ZPosition, d, axisIndex);
|
||||||
OffsetDrawArea(Min(ZPosition, d), Min(Depth, d));
|
OffsetDrawArea(Min(ZPosition, d), Min(Depth, d));
|
||||||
ACanvas.ClipRect := FClipRect;
|
ADrawer.Canvas.ClipRect := FClipRect;
|
||||||
ACanvas.Clipping := true;
|
ADrawer.Canvas.Clipping := true;
|
||||||
try
|
try
|
||||||
try
|
try
|
||||||
Draw(ACanvas);
|
Draw(ADrawer);
|
||||||
except
|
except
|
||||||
Active := false;
|
Active := false;
|
||||||
raise;
|
raise;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
OffsetDrawArea(-Min(ZPosition, d), -Min(Depth, d));
|
OffsetDrawArea(-Min(ZPosition, d), -Min(Depth, d));
|
||||||
ACanvas.Clipping := false;
|
ADrawer.Canvas.Clipping := false;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
seriesInZOrder.Free;
|
seriesInZOrder.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
AxisList.Draw(ACanvas, FClipRect, Self, MaxInt, d, axisIndex);
|
AxisList.Draw(ADrawer.Canvas, FClipRect, Self, MaxInt, d, axisIndex);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TChart.Draw(ADrawer: IChartDrawer; const ARect: TRect);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
legendItems: TChartLegendItems = nil;
|
||||||
|
legendRect: TRect;
|
||||||
|
begin
|
||||||
|
Clear(ADrawer, ARect);
|
||||||
|
|
||||||
|
FClipRect := ARect;
|
||||||
|
InflateRect(FClipRect, -2, -2);
|
||||||
|
|
||||||
|
for i := 0 to AxisList.Count - 1 do
|
||||||
|
with AxisList[i] do
|
||||||
|
if Transformations <> nil then
|
||||||
|
Transformations.SetChart(Self);
|
||||||
|
for i := 0 to SeriesCount - 1 do
|
||||||
|
Series[i].BeforeDraw;
|
||||||
|
|
||||||
|
if not FIsZoomed then
|
||||||
|
FLogicalExtent := GetFullExtent;
|
||||||
|
FCurrentExtent := FLogicalExtent;
|
||||||
|
DrawTitleFoot(ADrawer.Canvas);
|
||||||
|
if Legend.Visible then
|
||||||
|
PrepareLegend(ADrawer.Canvas, legendItems, FClipRect, legendRect);
|
||||||
|
try
|
||||||
|
PrepareAxis(ADrawer.Canvas);
|
||||||
|
DrawBackWall(ADrawer.Canvas);
|
||||||
|
DisplaySeries(ADrawer);
|
||||||
|
if Legend.Visible then
|
||||||
|
Legend.Draw(ADrawer.Canvas, legendItems, legendRect);
|
||||||
|
finally
|
||||||
|
legendItems.Free;
|
||||||
|
end;
|
||||||
|
DrawReticule(ADrawer.Canvas);
|
||||||
|
|
||||||
|
for i := 0 to SeriesCount - 1 do
|
||||||
|
Series[i].AfterDraw;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChart.DrawReticule(ACanvas: TCanvas);
|
procedure TChart.DrawReticule(ACanvas: TCanvas);
|
||||||
@ -1260,6 +1269,17 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TBasicChartSeries.Draw(ADrawer: IChartDrawer);
|
||||||
|
begin
|
||||||
|
Draw(ADrawer.Canvas);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBasicChartSeries.Draw(ACanvas: TCanvas);
|
||||||
|
begin
|
||||||
|
Unused(ACanvas);
|
||||||
|
raise EChartError(ClassName + '.Draw not implemented');
|
||||||
|
end;
|
||||||
|
|
||||||
function TBasicChartSeries.GraphToAxisX(AX: Double): Double;
|
function TBasicChartSeries.GraphToAxisX(AX: Double): Double;
|
||||||
begin
|
begin
|
||||||
Result := AX;
|
Result := AX;
|
||||||
|
Loading…
Reference in New Issue
Block a user