atshapelinebgra.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. // SPDX-License-Identifier: LGPL-3.0-linking-exception
  2. {ATShapeLine is a component which paints line (directions: left-right, up-down, diagonals), with or without arrows at both sides. Line width is option. Line color and arrow color are options. It is Lazarus port of Delphi component TLine (renamed since TLine id is busy with TAChart).
  3. Original author: Gon Perez-Jimenez (Spain, 2002)
  4. Ported to Lazarus by: Alexey Torgashin (Russia)
  5. - I redone get/set of canvas.pen and canvas.brush: do it only inside Paint, before it was all accross the code, in getters, setters, etc. This gives crashes of IDE on changing props in Linux.
  6. - I added any linewidth for any direction with arrow1=true and arrow2=true.
  7. - I converted demo to Laz using ide converter.
  8. - Icon added to component-pallette to 'Misc'.
  9. For BGRAControls by: Lainz
  10. - Using BGRABitmap antialiased drawing (2020-09-09)
  11. 2025 - Massimo Magnano
  12. Fixed gtk draw outside area (Use Width/Height instead of Canvas.Width/Height)
  13. Added Color Property; Comments in English
  14. Lazarus: 1.6+}
  15. unit ATShapeLineBGRA;
  16. interface
  17. {$mode delphi}
  18. uses
  19. Graphics, SysUtils, Classes, Controls;
  20. type
  21. TShapeLineDirection = (drLeftRight, drUpDown, drTopLeftBottomRight, drTopRightBottomLeft);
  22. { TShapeLineBGRA }
  23. TShapeLineBGRA = class(TGraphicControl)
  24. private
  25. { Private declarations }
  26. FLineDir: TShapeLineDirection;
  27. FArrow1: Boolean;
  28. FArrow2: Boolean;
  29. FArrowFactor: Integer;
  30. FLineWidth: integer;
  31. FLineColor: TColor;
  32. FArrowColor: TColor;
  33. FLineStyle: TPenStyle;
  34. procedure SetArrowColor(AValue: TColor);
  35. procedure SetLineColor(AValue: TColor);
  36. procedure SetLineDir(AValue: TShapeLineDirection);
  37. procedure SetArrow1(Value: Boolean);
  38. procedure SetArrow2(Value: Boolean);
  39. procedure SetArrowFactor(Value: integer);
  40. procedure SetLineWidth(AValue: Integer);
  41. procedure SetLineStyle(aLineStyle: TPenStyle);
  42. protected
  43. { Protected declarations }
  44. procedure Paint; override;
  45. public
  46. { Public declarations }
  47. constructor Create(AOwner: TComponent); override;
  48. destructor Destroy; override;
  49. published
  50. { Published declarations }
  51. property Color;
  52. property DragCursor;
  53. property DragKind;
  54. property DragMode;
  55. property Align;
  56. property Anchors;
  57. property BorderSpacing;
  58. property ParentShowHint;
  59. property Hint;
  60. property ShowHint;
  61. property Visible;
  62. property PopupMenu;
  63. property Direction: TShapeLineDirection read FLineDir write SetLineDir default drLeftRight;
  64. property LineColor: TColor read FLineColor write SetLineColor;
  65. property ArrowColor: TColor read FArrowColor write SetArrowColor;
  66. property LineWidth: Integer read FLineWidth write SetLineWidth;
  67. property LineStyle: TPenStyle read FLineStyle write SetLineStyle default psSolid;
  68. property Arrow1: Boolean read FArrow1 write SetArrow1 default False;
  69. property Arrow2: Boolean read FArrow2 write SetArrow2 default False;
  70. property ArrowFactor: Integer read FArrowFactor write SetArrowFactor default 8;
  71. property OnDragDrop;
  72. property OnDragOver;
  73. property OnEndDrag;
  74. property OnEndDock;
  75. property OnMouseDown;
  76. property OnMouseMove;
  77. property OnMouseUp;
  78. property OnClick;
  79. property OnDblClick;
  80. end;
  81. procedure Register;
  82. implementation
  83. uses Math, BGRABitmap, BGRABitmapTypes;
  84. procedure Register;
  85. begin
  86. RegisterComponents('BGRA Controls', [TShapeLineBGRA]);
  87. end;
  88. { TShapeLineBGRA }
  89. constructor TShapeLineBGRA.Create(AOwner: TComponent);
  90. begin
  91. inherited Create(AOwner);
  92. ControlStyle := ControlStyle + [csReplicatable];
  93. Width:=110;
  94. Height:=30;
  95. FArrow1:=false;
  96. FArrow2:=false;
  97. FArrowFactor:=8;
  98. FArrowColor:=clBlack;
  99. FLineColor:=clBlack;
  100. FLineWidth:=1;
  101. FLineStyle:=psSolid;
  102. FLineDir:=drLeftRight;
  103. end;
  104. destructor TShapeLineBGRA.Destroy;
  105. begin
  106. inherited Destroy;
  107. end;
  108. procedure TShapeLineBGRA.SetArrowFactor(Value: integer);
  109. begin
  110. if Value <> FArrowFactor then begin
  111. FArrowFactor := Value;
  112. Invalidate;
  113. end;
  114. end;
  115. procedure TShapeLineBGRA.SetArrow1(Value: Boolean);
  116. begin
  117. if Value <> FArrow1 then begin
  118. FArrow1 := Value;
  119. Invalidate;
  120. end;
  121. end;
  122. procedure TShapeLineBGRA.SetArrow2(Value: Boolean);
  123. begin
  124. if Value <> FArrow2 then begin
  125. FArrow2 := Value;
  126. Invalidate;
  127. end;
  128. end;
  129. procedure TShapeLineBGRA.SetLineWidth(AValue: Integer);
  130. begin
  131. if AValue <> FLineWidth then
  132. begin
  133. FLineWidth := AValue;
  134. Invalidate;
  135. end;
  136. end;
  137. procedure TShapeLineBGRA.SetLineStyle(aLineStyle: TPenStyle);
  138. begin
  139. if aLineStyle <> FLineStyle then
  140. begin
  141. FLineStyle := aLineStyle;
  142. Invalidate;
  143. end;
  144. end;
  145. procedure TShapeLineBGRA.SetLineColor(AValue: TColor);
  146. begin
  147. if AValue <> FLineColor then
  148. begin
  149. FLineColor := AValue;
  150. Invalidate;
  151. end;
  152. end;
  153. procedure TShapeLineBGRA.SetArrowColor(AValue: TColor);
  154. begin
  155. if AValue <> FArrowColor then
  156. begin
  157. FArrowColor := AValue;
  158. Invalidate;
  159. end;
  160. end;
  161. procedure TShapeLineBGRA.SetLineDir(AValue: TShapeLineDirection);
  162. begin
  163. if AValue <> FLineDir then
  164. begin
  165. FLineDir := AValue;
  166. Invalidate;
  167. end;
  168. end;
  169. procedure TShapeLineBGRA.Paint;
  170. var
  171. start: Integer;
  172. p1,p2,p3: TPoint;
  173. H0,W0,H,W: Integer;
  174. Alfa: double;
  175. bgra: TBGRABitmap;
  176. begin
  177. inherited;
  178. try
  179. if (Color=Parent.Color) or (Color=clNone)
  180. then bgra := TBGRABitmap.Create(Width, Height, BGRAPixelTransparent)
  181. else bgra := TBGRABitmap.Create(Width, Height, ColorToBGRA(Color));
  182. bgra.CanvasBGRA.Pen.Color:= FLineColor;
  183. bgra.CanvasBGRA.Brush.Color:=FArrowColor;
  184. bgra.CanvasBGRA.Pen.Width:=FLineWidth;
  185. bgra.CanvasBGRA.Pen.Style:=FLineStyle;
  186. case FLineDir of
  187. drLeftRight:
  188. begin
  189. start := (Height -1) div 2;
  190. bgra.CanvasBGRA.Pen.Width:= FLineWidth;
  191. bgra.CanvasBGRA.MoveTo(IfThen(FArrow1, FArrowFactor), start);
  192. bgra.CanvasBGRA.LineTo(Width-IfThen(FArrow2, FArrowFactor), Start);
  193. bgra.CanvasBGRA.Pen.Width:= 1;
  194. if FArrow1 then begin
  195. //Left Arrow
  196. p1:=Point(0,start);
  197. p2:=Point(FArrowFactor,Start-FArrowFactor);
  198. p3:=Point(FArrowFactor,Start+FArrowFactor);
  199. bgra.CanvasBGRA.Polygon([p1,p2,p3]);
  200. end;
  201. if FArrow2 then begin
  202. //Right Arrow
  203. p1:=Point(Width-1, Start);
  204. p2:=Point(Width-(FArrowFactor+1),Start-FArrowFactor);
  205. p3:=Point(Width-(FArrowFactor+1),Start+FArrowFactor);
  206. bgra.CanvasBGRA.Polygon([p1,p2,p3]);
  207. end;
  208. end;
  209. drUpDown:
  210. begin
  211. start := (Width -1) div 2;
  212. bgra.CanvasBGRA.Pen.Width:= FLineWidth;
  213. bgra.CanvasBGRA.MoveTo(start, IfThen(FArrow1, FArrowFactor));
  214. bgra.CanvasBGRA.LineTo(start, Height-IfThen(FArrow2, FArrowFactor));
  215. bgra.CanvasBGRA.Pen.Width:= 1;
  216. if FArrow1 then begin
  217. //Up Arrow
  218. p1:=Point(start,0);
  219. p2:=Point(Start-FArrowFactor,FArrowFactor);
  220. p3:=Point(Start+FArrowFactor,FArrowFactor);
  221. bgra.CanvasBGRA.Polygon([p1,p2,p3]);
  222. end;
  223. if FArrow2 then begin
  224. //Down Arrow
  225. p1:=Point(start,Height-1);
  226. p2:=Point(Start-FArrowFactor,Height-(FArrowFactor+1));
  227. p3:=Point(Start+FArrowFactor,Height-(FArrowFactor+1));
  228. bgra.CanvasBGRA.Polygon([p1,p2,p3]);
  229. end;
  230. end;
  231. drTopLeftBottomRight:
  232. begin
  233. Alfa:= arctan2(Height, Width);
  234. bgra.CanvasBGRA.Pen.Width:= FLineWidth;
  235. bgra.CanvasBGRA.MoveTo(
  236. IfThen(FArrow1, Trunc(FArrowFactor*cos(Alfa))),
  237. IfThen(FArrow1, Trunc(FArrowFactor*sin(Alfa)))
  238. );
  239. bgra.CanvasBGRA.LineTo(
  240. Width-IfThen(FArrow2, Trunc(FArrowFactor*cos(Alfa))),
  241. Height-IfThen(FArrow2, Trunc(FArrowFactor*sin(Alfa)))
  242. );
  243. bgra.CanvasBGRA.Pen.Width:= 1;
  244. if FArrow1 and(Width>0)then begin
  245. //Up Arrow
  246. H0:=Round((FArrowFactor+1)*Sin(Alfa));
  247. W0:=Round((FArrowFactor+1)*Cos(Alfa));
  248. p1:=Point(0,0);
  249. W:=Round(W0+(FArrowFactor*Cos((Pi/2)-Alfa)));
  250. H:=Round(H0-(FArrowFactor*Sin((Pi/2)-Alfa)));
  251. if H<0 then H:=0;
  252. if W<0 then W:=0;
  253. p2:=Point(W,H);
  254. W:=Round(W0-(FArrowFactor*Cos((Pi/2)-Alfa)));
  255. H:=Round(H0+(FArrowFactor*Sin((Pi/2)-Alfa)));
  256. if H<0 then H:=0;
  257. if W<0 then W:=0;
  258. p3:=Point(W,H);
  259. bgra.CanvasBGRA.Polygon([p1,p2,p3]);
  260. end;
  261. if FArrow2 and(Width>0)then begin
  262. //Down Arrow
  263. H0:=Round((FArrowFactor+1)*Sin(Alfa));
  264. W0:=Round((FArrowFactor+1)*Cos(Alfa));
  265. p1:=Point(Width-1, Height-1);
  266. W:=Round(W0-(FArrowFactor*Cos((Pi/2)-Alfa)));
  267. H:=Round(H0+(FArrowFactor*Sin((Pi/2)-Alfa)));
  268. W:=Width-W-1;
  269. H:=Height-H-1;
  270. if H>=Height then H:=Height-1;
  271. if W>=Width then W:=Width-1;
  272. p2:=Point(W,H);
  273. W:=Round(W0+(FArrowFactor*Cos((Pi/2)-Alfa)));
  274. H:=Round(H0-(FArrowFactor*Sin((Pi/2)-Alfa)));
  275. W:=Width-W-1;
  276. H:=Height-H-1;
  277. if H>=Height then H:=Height-1;
  278. if W>=Width then W:=Width-1;
  279. p3:=Point(W,H);
  280. bgra.CanvasBGRA.Polygon([p1,p2,p3]);
  281. end;
  282. end;
  283. drTopRightBottomLeft:
  284. begin
  285. Alfa:= arctan2(Height, Width);
  286. bgra.CanvasBGRA.Pen.Width:= FLineWidth;
  287. bgra.CanvasBGRA.MoveTo(
  288. Width-IfThen(FArrow1, Trunc(FArrowFactor*cos(Alfa))),
  289. IfThen(FArrow1, Trunc(FArrowFactor*sin(Alfa)))
  290. );
  291. bgra.CanvasBGRA.LineTo(
  292. IfThen(FArrow2, Trunc(FArrowFactor*cos(Alfa))),
  293. Height-IfThen(FArrow2, Trunc(FArrowFactor*sin(Alfa)))
  294. );
  295. bgra.CanvasBGRA.Pen.Width:= 1;
  296. if FArrow1 and(Width>0)then begin
  297. H0:=Round((FArrowFactor+1)*Sin(Alfa));
  298. W0:=Round((FArrowFactor+1)*Cos(Alfa));
  299. p1:=Point(Width-1,0);
  300. W:=Round(W0+(FArrowFactor*Cos((Pi/2)-Alfa)));
  301. H:=Round(H0-(FArrowFactor*Sin((Pi/2)-Alfa)));
  302. W:=Width-W-1;
  303. if H<0 then H:=0;
  304. if W>=Width then W:=Width-1;
  305. p2:=Point(W,H);
  306. W:=Round(W0-(FArrowFactor*Cos((Pi/2)-Alfa)));
  307. H:=Round(H0+(FArrowFactor*Sin((Pi/2)-Alfa)));
  308. W:=Width-W-1;
  309. if H<0 then H:=0;
  310. if W>=Width then W:=Width-1;
  311. p3:=Point(W,H);
  312. bgra.CanvasBGRA.Polygon([p1,p2,p3]);
  313. end;
  314. if FArrow2 and(Width>0)then begin
  315. H0:=Round((FArrowFactor+1)*Sin(Alfa));
  316. W0:=Round((FArrowFactor+1)*Cos(Alfa));
  317. p1:=Point(0, Height-1);
  318. W:=Round(W0-(FArrowFactor*Cos((Pi/2)-Alfa)));
  319. H:=Round(H0+(FArrowFactor*Sin((Pi/2)-Alfa)));
  320. H:=Height-H-1;
  321. if H>=Height then H:=Height-1;
  322. if W<0 then W:=0;
  323. p2:=Point(W,H);
  324. W:=Round(W0+(FArrowFactor*Cos((Pi/2)-Alfa)));
  325. H:=Round(H0-(FArrowFactor*Sin((Pi/2)-Alfa)));
  326. H:=Height-H-1;
  327. if H>=Height then H:=Height-1;
  328. if W<0 then W:=0;
  329. p3:=Point(W,H);
  330. bgra.CanvasBGRA.Polygon([p1,p2,p3]);
  331. end;
  332. end;
  333. end;
  334. bgra.Draw(Canvas, 0, 0, False);
  335. finally
  336. bgra.Free;
  337. end;
  338. end;
  339. end.