mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-27 00:23:53 +02:00
218 lines
5.2 KiB
ObjectPascal
218 lines
5.2 KiB
ObjectPascal
{
|
|
*****************************************************************************
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
|
|
Authors: Alexander Klenin
|
|
|
|
}
|
|
unit TADiagramDrawing;
|
|
|
|
{$MODE ObjFPC}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, FPCanvas,
|
|
TADrawUtils, TADiagram;
|
|
|
|
type
|
|
TDiaContextDrawer = class(TDiaContext)
|
|
private
|
|
FDrawer: IChartDrawer;
|
|
public
|
|
property Drawer: IChartDrawer read FDrawer write FDrawer;
|
|
end;
|
|
|
|
IDiaDrawerDecorator = interface
|
|
['{A2AB054F-D725-401D-A249-18BF03CFF6FA}']
|
|
procedure Apply(ADrawer: IChartDrawer);
|
|
end;
|
|
|
|
TDiaBrushDecorator = class(TDiaDecorator, IDiaDrawerDecorator)
|
|
private
|
|
FBrush: TFPCustomBrush;
|
|
public
|
|
constructor Create(AOwner: TDiaDecoratorList);
|
|
destructor Destroy; override;
|
|
procedure Apply(ADrawer: IChartDrawer);
|
|
property Brush: TFPCustomBrush read FBrush;
|
|
end;
|
|
|
|
TDiaFontDecorator = class(TDiaDecorator, IDiaDrawerDecorator)
|
|
private
|
|
FFont: TFPCustomFont;
|
|
public
|
|
constructor Create(AOwner: TDiaDecoratorList);
|
|
destructor Destroy; override;
|
|
procedure Apply(ADrawer: IChartDrawer);
|
|
property Font: TFPCustomFont read FFont;
|
|
end;
|
|
|
|
TDiaPenDecorator = class(TDiaDecorator, IDiaDrawerDecorator)
|
|
private
|
|
FPen: TFPCustomPen;
|
|
public
|
|
constructor Create(AOwner: TDiaDecoratorList);
|
|
destructor Destroy; override;
|
|
procedure Apply(ADrawer: IChartDrawer);
|
|
property Pen: TFPCustomPen read FPen;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Math, Types, SysUtils,
|
|
TAGeometry;
|
|
|
|
function ToImage(const AP: TDiaPoint): TPoint; inline;
|
|
begin
|
|
Result := RoundPoint(AP.AsUnits(duPixels));
|
|
end;
|
|
|
|
procedure DrawDiaBox(ASelf: TDiaBox);
|
|
var
|
|
id: IChartDrawer;
|
|
d: IDiaDecorator;
|
|
begin
|
|
id := (ASelf.Owner.Context as TDiaContextDrawer).Drawer;
|
|
id.PrepareSimplePen($000000);
|
|
id.SetBrushColor($FFFFFF);
|
|
for d in ASelf.Decorators do
|
|
if d is IDiaDrawerDecorator then
|
|
(d as IDiaDrawerDecorator).Apply(id);
|
|
with ASelf do
|
|
id.Polygon([
|
|
ToImage(FTopLeft), ToImage(FTopRight),
|
|
ToImage(FBottomRight), ToImage(FBottomLeft)
|
|
], 0, 4);
|
|
id.TextOut.Pos(ToImage(ASelf.FTopLeft) + Point(4, 4)).Text(ASelf.Caption).Done;
|
|
end;
|
|
|
|
procedure DrawEndPoint(
|
|
ADrawer: IChartDrawer; AEndPoint: TDiaEndPoint;
|
|
const APos: TPoint; AAngle: Double);
|
|
var
|
|
da: Double;
|
|
diag: Integer;
|
|
pt1, pt2: TPoint;
|
|
d: IDiaDecorator;
|
|
begin
|
|
ADrawer.SetPenParams(psSolid, $000000);
|
|
ADrawer.SetBrushColor($FFFFFF);
|
|
for d in AEndPoint.Decorators do
|
|
if d is IDiaDrawerDecorator then
|
|
(d as IDiaDrawerDecorator).Apply(ADrawer);
|
|
da := ArcTan2(AEndPoint.Width.Value, AEndPoint.Length.Value);
|
|
|
|
diag := -Round(Sqrt(Sqr(AEndPoint.Length.Value) + Sqr(AEndPoint.Width.Value)));
|
|
pt1 := APos + RotatePointX(diag, AAngle - da);
|
|
pt2 := APos + RotatePointX(diag, AAngle + da);
|
|
case AEndPoint.Shape of
|
|
depsClosedArrow: ADrawer.Polygon([pt1, APos, pt2], 0, 3);
|
|
depsOpenArrow: ADrawer.Polyline([pt1, APos, pt2], 0, 3);
|
|
end;
|
|
end;
|
|
|
|
procedure DrawDiaLink(ASelf: TDiaLink);
|
|
var
|
|
id: IChartDrawer;
|
|
startPos, endPos, p: TPoint;
|
|
d: IDiaDecorator;
|
|
begin
|
|
if (ASelf.Start.Connector = nil) or (ASelf.Finish.Connector = nil) then exit;
|
|
id := (ASelf.Owner.Context as TDiaContextDrawer).Drawer;
|
|
id.PrepareSimplePen($000000);
|
|
for d in ASelf.Decorators do
|
|
if d is IDiaDrawerDecorator then
|
|
(d as IDiaDrawerDecorator).Apply(id);
|
|
startPos := ToImage(ASelf.Start.Connector.ActualPos);
|
|
endPos := ToImage(ASelf.Finish.Connector.ActualPos);
|
|
case ASelf.Routing of
|
|
dlrStraight: begin
|
|
id.Line(startPos, endPos);
|
|
p := startPos;
|
|
end;
|
|
dlrXThenY: begin
|
|
p := Point(endPos.X, startPos.Y);
|
|
id.Polyline([startPos, p, endPos], 0, 3);
|
|
end;
|
|
dlrYThenX: begin
|
|
p := Point(startPos.X, endPos.Y);
|
|
id.Polyline([startPos, p, endPos], 0, 3);
|
|
end;
|
|
end;
|
|
if ASelf.Start.Shape <> depsNone then
|
|
with p - endPos do
|
|
DrawEndPoint(id, ASelf.Start, startPos, ArcTan2(Y, X));
|
|
if ASelf.Finish.Shape <> depsNone then
|
|
with endPos - p do
|
|
DrawEndPoint(id, ASelf.Finish, endPos, ArcTan2(Y, X));
|
|
end;
|
|
|
|
{ TDiaBrushDecorator }
|
|
|
|
procedure TDiaBrushDecorator.Apply(ADrawer: IChartDrawer);
|
|
begin
|
|
ADrawer.Brush := Brush;
|
|
end;
|
|
|
|
constructor TDiaBrushDecorator.Create(AOwner: TDiaDecoratorList);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FBrush := TFPCustomBrush.Create;
|
|
end;
|
|
|
|
destructor TDiaBrushDecorator.Destroy;
|
|
begin
|
|
FreeAndNil(FBrush);
|
|
inherited;
|
|
end;
|
|
|
|
{ TDiaFontDecorator }
|
|
|
|
procedure TDiaFontDecorator.Apply(ADrawer: IChartDrawer);
|
|
begin
|
|
ADrawer.Font := Font;
|
|
end;
|
|
|
|
constructor TDiaFontDecorator.Create(AOwner: TDiaDecoratorList);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FFont := TFPCustomFont.Create;
|
|
end;
|
|
|
|
destructor TDiaFontDecorator.Destroy;
|
|
begin
|
|
FreeAndNil(FFont);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ TDiaPenDecorator }
|
|
|
|
procedure TDiaPenDecorator.Apply(ADrawer: IChartDrawer);
|
|
begin
|
|
ADrawer.Pen := Pen;
|
|
end;
|
|
|
|
constructor TDiaPenDecorator.Create(AOwner: TDiaDecoratorList);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FPen := TFPCustomPen.Create;
|
|
FPen.Mode := pmCopy;
|
|
end;
|
|
|
|
destructor TDiaPenDecorator.Destroy;
|
|
begin
|
|
FreeAndNil(FPen);
|
|
inherited;
|
|
end;
|
|
|
|
initialization
|
|
TDiaBox.FInternalDraw := @DrawDiaBox;
|
|
TDiaLink.FInternalDraw := @DrawDiaLink;
|
|
|
|
end.
|
|
|