dtanaloggauge.pp 12 KB

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