dtanaloggauge.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. // SPDX-License-Identifier: LGPL-3.0-linking-exception
  2. {
  3. Part of BGRA Controls. Made by third party.
  4. For detailed information see readme.txt
  5. Site: https://sourceforge.net/p/bgra-controls/
  6. Wiki: http://wiki.lazarus.freepascal.org/BGRAControls
  7. Forum: http://forum.lazarus.freepascal.org/index.php/board,46.0.html
  8. }
  9. {******************************* CONTRIBUTOR(S) ******************************
  10. - Edivando S. Santos Brasil | mailedivando@gmail.com
  11. (Compatibility with delphi VCL 11/2018)
  12. ***************************** END CONTRIBUTOR(S) *****************************}
  13. unit DTAnalogGauge;
  14. {$I bgracontrols.inc}
  15. interface
  16. uses
  17. Classes, SysUtils, Graphics, {$IFDEF FPC}LResources, {$ELSE} BGRAGraphics, {$ENDIF}Forms, Controls, Dialogs, DTAnalogCommon,
  18. BCBaseCtrls, BGRABitmap, BGRABitmapTypes;
  19. type
  20. TDTGaugeStyle = (gsCustom, gsDark, gsLight);
  21. { TDTCustomAnalogGauge }
  22. TDTCustomAnalogGauge = class(TBGRAGraphicCtrl)
  23. private
  24. FFaceSettings: TDTFaceSettings;
  25. FGaugeStyle: TDTGaugeStyle;
  26. FNeedleSettings: TDTNeedleSettings;
  27. FPosition: integer;
  28. FResized: boolean;
  29. FGaugeBitmap: TBGRABitmap;
  30. FGaugeBodyBitmap: TBGRABitmap;
  31. FGaugeScaleBitmap: TBGRABitmap;
  32. FGaugeNeedleBitmap: TBGRABitmap;
  33. FScaleSettings: TDTScaleSettings;
  34. procedure SetFaceSettings(AValue: TDTFaceSettings);
  35. procedure DoChange({%H-}Sender: TObject);
  36. procedure SetGaugeStyle(AValue: TDTGaugeStyle);
  37. procedure SetNeedleSettings(AValue: TDTNeedleSettings);
  38. procedure SetPosition(AValue: integer);
  39. procedure SetScaleSettings(AValue: TDTScaleSettings);
  40. { Private declarations }
  41. protected
  42. { Protected declarations }
  43. procedure ResizeEvent({%H-}Sender: TObject);
  44. procedure ClearBitMap(var BitMap: TBGRABitmap);
  45. public
  46. { Public declarations }
  47. constructor Create(AOwner: TComponent); override;
  48. destructor Destroy; override;
  49. procedure Paint; override;
  50. procedure DrawGauge; virtual;
  51. procedure DrawGaugeBody; virtual;
  52. procedure DrawGaugeRange; virtual;
  53. procedure DrawGaugeFace; virtual;
  54. procedure DrawGaugeScale; virtual;
  55. procedure DrawGaugeNeedle; virtual;
  56. published
  57. { Published declarations }
  58. property Position: integer read FPosition write SetPosition;
  59. property FaceSettings: TDTFaceSettings read FFaceSettings write SetFaceSettings;
  60. property ScaleSettings: TDTScaleSettings read FScaleSettings write SetScaleSettings;
  61. property NeedleSettings: TDTNeedleSettings read FNeedleSettings write SetNeedleSettings;
  62. //property GaugeStyle: TDTGaugeStyle read FGaugeStyle write SetGaugeStyle;
  63. end;
  64. { TDTAnalogGauge }
  65. TDTAnalogGauge = class(TDTCustomAnalogGauge)
  66. private
  67. { Private declarations }
  68. protected
  69. { Protected declarations }
  70. public
  71. { Public declarations }
  72. published
  73. { Published declarations }
  74. property FaceSettings;
  75. property ScaleSettings;
  76. property NeedleSettings;
  77. end;
  78. {$IFDEF FPC}procedure Register;{$ENDIF}
  79. implementation
  80. {$IFDEF FPC}
  81. procedure Register;
  82. begin
  83. RegisterComponents('BGRA Controls', [TDTAnalogGauge]);
  84. end;
  85. {$ENDIF}
  86. { TDTCustomAnalogGauge }
  87. procedure TDTCustomAnalogGauge.ClearBitMap(var BitMap: TBGRABitmap);
  88. begin
  89. BitMap.Fill(BGRA(0, 0, 0, 0));
  90. end;
  91. constructor TDTCustomAnalogGauge.Create(AOwner: TComponent);
  92. begin
  93. inherited Create(AOwner);
  94. Width := 240;
  95. Height := 240;
  96. FScaleSettings := TDTScaleSettings.Create;
  97. ScaleSettings.OnChange := DoChange;
  98. FFaceSettings := TDTFaceSettings.Create;
  99. FaceSettings.OnChange := DoChange;
  100. FNeedleSettings := TDTNeedleSettings.Create;
  101. NeedleSettings.OnChange := DoChange;
  102. FGaugeBitmap := TBGRABitmap.Create(Width, Height);
  103. FGaugeBodyBitmap := TBGRABitmap.Create(Width, Height);
  104. FGaugeScaleBitmap := TBGRABitmap.Create(Width, Height);
  105. FGaugeNeedleBitmap := TBGRABitmap.Create(Width, Height);
  106. end;
  107. destructor TDTCustomAnalogGauge.Destroy;
  108. begin
  109. FScaleSettings.OnChange:=nil;
  110. FScaleSettings.Free;
  111. FFaceSettings.OnChange:=nil;
  112. FFaceSettings.Free;
  113. FGaugeBitmap.Free;
  114. FGaugeBodyBitmap.Free;
  115. FGaugeScaleBitmap.Free;
  116. FGaugeNeedleBitmap.Free;
  117. FNeedleSettings.OnChange:=nil;
  118. FNeedleSettings.Free;
  119. inherited Destroy;
  120. end;
  121. procedure TDTCustomAnalogGauge.DoChange(Sender: TObject);
  122. begin
  123. Invalidate;
  124. end;
  125. procedure TDTCustomAnalogGauge.SetGaugeStyle(AValue: TDTGaugeStyle);
  126. begin
  127. if FGaugeStyle = AValue then
  128. Exit;
  129. FGaugeStyle := AValue;
  130. DoChange(self);
  131. end;
  132. procedure TDTCustomAnalogGauge.SetNeedleSettings(AValue: TDTNeedleSettings);
  133. begin
  134. if FNeedleSettings = AValue then
  135. Exit;
  136. FNeedleSettings := AValue;
  137. DoChange(self);
  138. end;
  139. procedure TDTCustomAnalogGauge.DrawGauge;
  140. begin
  141. DrawGaugeBody;
  142. DrawGaugeFace;
  143. if FScaleSettings.EnableRangeIndicator then
  144. DrawGaugeRange;
  145. DrawGaugeScale;
  146. DrawGaugeNeedle;
  147. end;
  148. procedure TDTCustomAnalogGauge.DrawGaugeBody;
  149. var
  150. r: integer;
  151. origin: TDTOrigin;
  152. begin
  153. origin := Initializebitmap(FGaugeBodyBitmap, Width, Height);
  154. //// Keep circle insde frame
  155. r := round(origin.Radius * 0.95);
  156. // Draw Bitmap frame
  157. FGaugeBodyBitmap.FillEllipseAntialias(origin.CenterPoint.x,
  158. origin.CenterPoint.y,
  159. r, r, FFaceSettings.ColorFrame);
  160. // Draw thin antialiased border to smooth against background
  161. FGaugeBodyBitmap.EllipseAntialias(origin.CenterPoint.x,
  162. origin.CenterPoint.y,
  163. r, r, ColorToBGRA(clBlack, 120), 1);
  164. end;
  165. procedure TDTCustomAnalogGauge.DrawGaugeRange;
  166. var
  167. {%H-}r, w, h, Xo, Yo: integer;
  168. begin
  169. ClearBitMap(FGaugeScaleBitmap);
  170. w := Width;
  171. h := Height;
  172. FGaugeScaleBitmap.SetSize(w, h);
  173. { Set center point }
  174. Xo := w div 2;
  175. Yo := h div 2;
  176. // Determine radius. If canvas is rectangular then r = shortest length w or h
  177. r := yo;
  178. if xo > yo then
  179. r := yo;
  180. if xo < yo then
  181. r := xo;
  182. //j := (180 - FScaleSettings.Angle) / 2;
  183. end;
  184. procedure TDTCustomAnalogGauge.DrawGaugeFace;
  185. var
  186. w, h, r, Xo, Yo: integer;
  187. begin
  188. ClearBitMap(FGaugeScaleBitmap);
  189. w := Width;
  190. h := Height;
  191. FGaugeBodyBitmap.SetSize(w, h);
  192. //{ Set center point }
  193. Xo := w div 2;
  194. Yo := h div 2;
  195. // // Determine radius. If canvas is rectangular then r = shortest length w or h
  196. r := yo;
  197. if xo > yo then
  198. r := yo;
  199. if xo < yo then
  200. r := xo;
  201. // Keep circle insde frame
  202. r := round(r * 0.95) - 5;
  203. // Draw face background
  204. case FFaceSettings.FillStyle of
  205. fsGradient:
  206. FGaugeBodyBitmap.FillEllipseLinearColorAntialias(Xo, Yo, r, r, FFaceSettings.ColorStart, ColorToBGRA(FFaceSettings.ColorEnd));
  207. fsnone:
  208. FGaugeBodyBitmap.FillEllipseAntialias(Xo, Yo, r, r, FFaceSettings.ColorStart);
  209. end;
  210. //origin := Initializebitmap(FGaugeBodyBitmap, Width, Height);
  211. //// Keep circle insde frame
  212. //r := round(origin.Radius * 0.95) - 5;
  213. //// Draw face background
  214. //case FFaceSettings.FillStyle of
  215. // fsGradient:
  216. // FGaugeBodyBitmap.FillEllipseLinearColorAntialias(origin.CenterPoint.x, origin.CenterPoint.y, r, r, ColorToBGRA(FFaceSettings.ColorStart), ColorToBGRA(FFaceSettings.ColorEnd));
  217. // fsnone:
  218. // FGaugeBodyBitmap.FillEllipseAntialias(origin.CenterPoint.x, origin.CenterPoint.y, r, r, ColorToBGRA(FFaceSettings.ColorStart));
  219. //end;
  220. end;
  221. procedure TDTCustomAnalogGauge.DrawGaugeScale;
  222. var
  223. w, h, r, Xo, Yo, X, Y, Xt, Yt: integer;
  224. i, n: integer;
  225. j: single;
  226. begin
  227. w := Width;
  228. h := Height;
  229. FGaugeScaleBitmap.SetSize(w, h);
  230. ClearBitMap(FGaugeScaleBitmap);
  231. { Set center point }
  232. Xo := w div 2;
  233. Yo := h div 2;
  234. // Determine radius. If canvas is rectangular then r = shortest length w or h
  235. r := yo;
  236. if xo > yo then
  237. r := yo;
  238. if xo < yo then
  239. r := xo;
  240. j := (180 - FScaleSettings.Angle) / 2;
  241. // Draw SubTicks
  242. if FScaleSettings.EnableSubTicks then
  243. begin
  244. n := FScaleSettings.MainTickCount * FScaleSettings.SubTickCount;
  245. for i := 0 to n do
  246. begin
  247. // Calculate draw from point
  248. X := xo - Round(r * 0.85 * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
  249. Y := yo - Round(r * 0.85 * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
  250. // Calculate draw to point
  251. Xt := xo - Round(((r * 0.85) - FScaleSettings.LengthSubTick) * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
  252. Yt := yo - Round(((r * 0.85) - FScaleSettings.LengthSubTick) * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
  253. FGaugeScaleBitmap.DrawLineAntialias(x, y, xt, yt, FScaleSettings.TickColor, FScaleSettings.ThicknessSubTick);
  254. end;
  255. end;
  256. if FScaleSettings.EnableMainTicks then
  257. begin
  258. FGaugeScaleBitmap.FontName := FScaleSettings.TextFont;
  259. FGaugeScaleBitmap.FontHeight := FScaleSettings.TextSize;
  260. FGaugeScaleBitmap.FontQuality := fqFineAntialiasing;
  261. n := FScaleSettings.MainTickCount;
  262. for i := 0 to n do
  263. begin
  264. // Draw main ticks
  265. // Calculate draw from point
  266. X := xo - Round(r * 0.85 * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
  267. Y := yo - Round(r * 0.85 * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
  268. // Calculate draw to point
  269. Xt := xo - Round(((r * 0.85) - FScaleSettings.LengthMainTick) * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
  270. Yt := yo - Round(((r * 0.85) - FScaleSettings.LengthMainTick) * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
  271. FGaugeScaleBitmap.DrawLineAntialias(x, y, xt, yt, FScaleSettings.TickColor, FScaleSettings.ThicknessMainTick);
  272. // Draw text for main ticks
  273. Xt := xo - Round((r - FScaleSettings.LengthMainTick) * 0.7 * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
  274. Yt := yo - Round((r - FScaleSettings.LengthMainTick) * 0.7 * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
  275. FGaugeScaleBitmap.TextOut(Xt, Yt - (FGaugeScaleBitmap.FontHeight / 1.7),
  276. IntToStr(i * FScaleSettings.Maximum div FScaleSettings.MainTickCount),
  277. //ColorToBGRA(FScaleSettings.TickColor),
  278. FScaleSettings.TextColor,
  279. taCenter);
  280. end;
  281. end;
  282. end;
  283. procedure TDTCustomAnalogGauge.DrawGaugeNeedle;
  284. var
  285. w, h, Xo, Yo, X, Y: integer;
  286. j: single;
  287. begin
  288. ClearBitMap(FGaugeNeedleBitmap);
  289. w := Width;
  290. h := Height;
  291. FGaugeNeedleBitmap.SetSize(w, h);
  292. { Set center point }
  293. Xo := w div 2;
  294. Yo := h div 2;
  295. j := (180 - FScaleSettings.Angle) / 2;
  296. // Draw needle
  297. case FNeedleSettings.NeedleStyle of
  298. nsLine:
  299. begin
  300. X := xo - Round(FNeedleSettings.NeedleLength * cos((j + Position * FScaleSettings.Angle / FScaleSettings.Maximum) * Pi / 180));
  301. Y := yo - Round(FNeedleSettings.NeedleLength * sin((j + Position * FScaleSettings.Angle / FScaleSettings.Maximum) * Pi / 180));
  302. FGaugeNeedleBitmap.DrawLineAntialias(xo, yo, x, y,
  303. FNeedleSettings.NeedleColor,
  304. FScaleSettings.ThicknessMainTick);
  305. end;
  306. nsTriangle:
  307. begin
  308. end;
  309. end;
  310. // Draw cap over needle
  311. FGaugeNeedleBitmap.EllipseAntialias(Xo, Yo, FNeedleSettings.CapRadius,
  312. FNeedleSettings.CapRadius,
  313. FNeedleSettings.CapEdgeColor,
  314. 2, FNeedleSettings.CapColor);
  315. end;
  316. procedure TDTCustomAnalogGauge.SetFaceSettings(AValue: TDTFaceSettings);
  317. begin
  318. if FFaceSettings = AValue then
  319. Exit;
  320. FFaceSettings := AValue;
  321. DoChange(self);
  322. end;
  323. procedure TDTCustomAnalogGauge.SetPosition(AValue: integer);
  324. begin
  325. if FPosition = AValue then
  326. Exit;
  327. FPosition := AValue;
  328. DoChange(self);
  329. end;
  330. procedure TDTCustomAnalogGauge.SetScaleSettings(AValue: TDTScaleSettings);
  331. begin
  332. if FScaleSettings = AValue then
  333. Exit;
  334. FScaleSettings := AValue;
  335. DoChange(self);
  336. end;
  337. procedure TDTCustomAnalogGauge.ResizeEvent(Sender: TObject);
  338. begin
  339. FResized := True;
  340. end;
  341. procedure TDTCustomAnalogGauge.Paint;
  342. begin
  343. inherited Paint;
  344. ClearBitMap(FGaugeBitmap);
  345. FGaugeBitmap.SetSize(Width, Height);
  346. DrawGauge;
  347. FGaugeBitmap.BlendImage(0, 0, FGaugeBodyBitmap, boLinearBlend);
  348. FGaugeBitmap.BlendImage(0, 0, FGaugeScaleBitmap, boLinearBlend);
  349. FGaugeBitmap.BlendImage(0, 0, FGaugeNeedleBitmap, boLinearBlend);
  350. FGaugeBitmap.Draw(Canvas, 0, 0, False);
  351. end;
  352. end.