TAChart: Start implementation of IChartDrawer interface

git-svn-id: trunk@29519 -
This commit is contained in:
ask 2011-02-13 12:45:10 +00:00
parent 09d05b6a3c
commit 2acf57df8d
2 changed files with 149 additions and 56 deletions

View File

@ -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);

View File

@ -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;