dtthemedclock.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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 | [email protected]
  11. (Compatibility with delphi VCL 11/2018)
  12. ***************************** END CONTRIBUTOR(S) *****************************}
  13. unit DTThemedClock;
  14. {$I bgracontrols.inc}
  15. interface
  16. uses
  17. Classes, SysUtils, ExtCtrls, {$IFDEF FPC}LResources,{$ENDIF} Forms, Controls, Graphics, Dialogs, DTAnalogCommon,
  18. {$IFNDEF FPC}Types, BGRAGraphics, GraphType, FPImage, {$ENDIF}
  19. BGRABitmap, BGRABitmapTypes;
  20. type
  21. { TDTCustomThemedClock }
  22. TDTCustomThemedClock = class(TDTBaseAnalogDevice)
  23. private
  24. FClockFace: TBGRABitmap;
  25. FPointerBitmap: TBGRABitmap;
  26. FEnabled: boolean;
  27. FHoursPointerSettings: TDTPointerSettings;
  28. FMinutesPointerSettings: TDTPointerSettings;
  29. FPointerCapSettings: TDTPointerCapSettings;
  30. FPosition: integer;
  31. FSecondsPointerSettings: TDTPointerSettings;
  32. FTimer: TTimer;
  33. procedure SetHoursPointerSettings(AValue: TDTPointerSettings);
  34. procedure SetMinutesPointerSettings(AValue: TDTPointerSettings);
  35. procedure SetPointerCapSettings(AValue: TDTPointerCapSettings);
  36. procedure SetPosition(AValue: integer);
  37. procedure SetSecondsPointerSettings(AValue: TDTPointerSettings);
  38. { Private declarations }
  39. protected
  40. procedure SetEnabled(AValue: boolean); override;
  41. { Protected declarations }
  42. property SecondsPointerSettings: TDTPointerSettings read FSecondsPointerSettings write SetSecondsPointerSettings;
  43. property MinutesPointerSettings: TDTPointerSettings read FMinutesPointerSettings write SetMinutesPointerSettings;
  44. property HoursPointerSettings: TDTPointerSettings read FHoursPointerSettings write SetHoursPointerSettings;
  45. property PointerCapSettings: TDTPointerCapSettings read FPointerCapSettings write SetPointerCapSettings;
  46. property Position: integer read FPosition write SetPosition;
  47. property Enabled: boolean read FEnabled write SetEnabled;
  48. procedure TimerEvent({%H-}Sender: TObject);
  49. public
  50. { Public declarations }
  51. constructor Create(AOwner: TComponent); override;
  52. destructor Destroy; override;
  53. procedure Paint; override;
  54. procedure DrawClock;
  55. procedure DrawPointers;
  56. end;
  57. TDTThemedClock = class(TDTCustomThemedClock)
  58. private
  59. { Private declarations }
  60. protected
  61. { Protected declarations }
  62. public
  63. { Public declarations }
  64. published
  65. { Public declarations }
  66. property SecondsPointerSettings;
  67. property MinutesPointerSettings;
  68. property HoursPointerSettings;
  69. property PointerCapSettings;
  70. property ScaleSettings;
  71. property Position;
  72. property Enabled;
  73. end;
  74. {$IFDEF FPC}procedure Register;{$ENDIF}
  75. implementation
  76. {$IFDEF FPC}
  77. procedure Register;
  78. begin
  79. RegisterComponents('BGRA Controls', [TDTThemedClock]);
  80. end;
  81. {$ENDIF}
  82. { TDTCustomThemedClock }
  83. procedure TDTCustomThemedClock.SetPointerCapSettings(AValue: TDTPointerCapSettings);
  84. begin
  85. if FPointerCapSettings = AValue then
  86. Exit;
  87. FPointerCapSettings := AValue;
  88. DoChange(self);
  89. end;
  90. procedure TDTCustomThemedClock.SetHoursPointerSettings(AValue: TDTPointerSettings);
  91. begin
  92. if FHoursPointerSettings = AValue then
  93. Exit;
  94. FHoursPointerSettings := AValue;
  95. DoChange(self);
  96. end;
  97. procedure TDTCustomThemedClock.SetEnabled(AValue: boolean);
  98. begin
  99. if FEnabled = AValue then
  100. Exit;
  101. FEnabled := AValue;
  102. FTimer.Enabled := FEnabled;
  103. DoChange(self);
  104. end;
  105. procedure TDTCustomThemedClock.SetMinutesPointerSettings(AValue: TDTPointerSettings);
  106. begin
  107. if FMinutesPointerSettings = AValue then
  108. Exit;
  109. FMinutesPointerSettings := AValue;
  110. DoChange(self);
  111. end;
  112. procedure TDTCustomThemedClock.SetPosition(AValue: integer);
  113. begin
  114. if FPosition = AValue then
  115. Exit;
  116. FPosition := AValue;
  117. DoChange(self);
  118. end;
  119. procedure TDTCustomThemedClock.SetSecondsPointerSettings(AValue: TDTPointerSettings);
  120. begin
  121. if FSecondsPointerSettings = AValue then
  122. Exit;
  123. FSecondsPointerSettings := AValue;
  124. DoChange(self);
  125. end;
  126. procedure TDTCustomThemedClock.TimerEvent(Sender: TObject);
  127. begin
  128. DrawPointers;
  129. DoChange(self);
  130. end;
  131. constructor TDTCustomThemedClock.Create(AOwner: TComponent);
  132. begin
  133. inherited Create(AOwner);
  134. FSecondsPointerSettings := TDTPointerSettings.Create;
  135. FSecondsPointerSettings.OnChange := DoChange;
  136. FMinutesPointerSettings := TDTPointerSettings.Create;
  137. FMinutesPointerSettings.OnChange := DoChange;
  138. FHoursPointerSettings := TDTPointerSettings.Create;
  139. FHoursPointerSettings.OnChange := DoChange;
  140. FPointerCapSettings := TDTPointerCapSettings.Create;
  141. FPointerCapSettings.OnChange := DoChange;
  142. FClockFace := TBGRABitmap.Create;
  143. FPointerBitmap := TBGRABitmap.Create;
  144. FSecondsPointerSettings.Color := BGRA(255, 81, 81);
  145. FSecondsPointerSettings.Length := 80;
  146. FSecondsPointerSettings.Thickness := 3;
  147. FMinutesPointerSettings.Color := BGRA(199, 199, 173);
  148. FMinutesPointerSettings.Length := 80;
  149. FMinutesPointerSettings.Thickness := 3;
  150. FHoursPointerSettings.Color := BGRA(199, 199, 173);
  151. FHoursPointerSettings.Length := 60;
  152. FHoursPointerSettings.Thickness := 5;
  153. FTimer := TTimer.Create(Self);
  154. FTimer.Interval := 1000;
  155. FTimer.Enabled := FEnabled;
  156. FTimer.OnTimer := TimerEvent;
  157. end;
  158. destructor TDTCustomThemedClock.Destroy;
  159. begin
  160. FSecondsPointerSettings.OnChange:=nil;
  161. FSecondsPointerSettings.Free;
  162. FMinutesPointerSettings.OnChange:=nil;
  163. FMinutesPointerSettings.Free;
  164. FHoursPointerSettings.OnChange:=nil;
  165. FHoursPointerSettings.Free;
  166. FTimer.Enabled:=False;
  167. FTimer.OnTimer:=nil;
  168. FPointerCapSettings.OnChange:=nil;
  169. FPointerCapSettings.Free;
  170. FClockFace.Free;
  171. FPointerBitmap.Free;
  172. inherited Destroy;
  173. end;
  174. procedure TDTCustomThemedClock.Paint;
  175. begin
  176. inherited Paint;
  177. DrawClock;
  178. DrawPointers;
  179. FGaugeBitmap.BlendImage(0, 0, FClockFace, boLinearBlend);
  180. FGaugeBitmap.BlendImage(0, 0, FPointerBitmap, boLinearBlend);
  181. FGaugeBitmap.Draw(Canvas, 0, 0, False);
  182. end;
  183. procedure TDTCustomThemedClock.DrawClock;
  184. var
  185. Origin: TDTOrigin;
  186. r, i, x, y, xt, yt: integer;
  187. begin
  188. Origin := Initializebitmap(FClockFace, Width, Height);
  189. r := round(Origin.Radius * 0.85);
  190. // Draw minor tick marks
  191. if ScaleSettings.EnableSubTicks then
  192. begin
  193. for i := 1 to 60 do
  194. begin
  195. // Calculate draw from point
  196. X := Origin.CenterPoint.x + Round(r * sin(6 * i * Pi / 180));
  197. Y := Origin.CenterPoint.y - Round(r * cos(6 * i * Pi / 180));
  198. // Calculate draw to point
  199. xt := Origin.CenterPoint.x + Round((r - ScaleSettings.LengthSubTick) * sin(6 * i * Pi / 180));
  200. yt := Origin.CenterPoint.y - Round((r - ScaleSettings.LengthSubTick) * cos(6 * i * Pi / 180));
  201. FClockFace.DrawLineAntialias(x, y, xt, yt, ScaleSettings.TickColor, ScaleSettings.ThicknessSubTick);
  202. end;
  203. end;
  204. // Draw major tick marks
  205. if ScaleSettings.EnableMainTicks then
  206. begin
  207. for i := 1 to 12 do
  208. begin
  209. // Calculate draw from point
  210. X := Origin.CenterPoint.x + Round(r * sin(30 * i * Pi / 180));
  211. Y := Origin.CenterPoint.y - Round(r * cos(30 * i * Pi / 180));
  212. // Calculate draw to point
  213. xt := Origin.CenterPoint.x + Round((r - ScaleSettings.LengthMainTick) * sin(30 * i * Pi / 180));
  214. yt := Origin.CenterPoint.y - Round((r - ScaleSettings.LengthMainTick) * cos(30 * i * Pi / 180));
  215. FClockFace.DrawLineAntialias(x, y, xt, yt, ScaleSettings.TickColor, ScaleSettings.ThicknessMainTick);
  216. if ScaleSettings.EnableScaleText then
  217. begin
  218. FClockFace.FontName := ScaleSettings.TextFont;
  219. FClockFace.FontHeight := ScaleSettings.TextSize;
  220. FClockFace.FontQuality := fqFineAntialiasing;
  221. // Draw text for main ticks
  222. xt := Origin.CenterPoint.x + Round(ScaleSettings.TextRadius * sin(30 * i * Pi / 180));
  223. yt := Origin.CenterPoint.y - Round(ScaleSettings.TextRadius * cos(30 * i * Pi / 180));
  224. FClockFace.TextOut(Xt, Yt - (FClockFace.FontHeight / 1.7), IntToStr(i), ScaleSettings.TextColor, taCenter);
  225. end;
  226. end;
  227. end;
  228. end;
  229. procedure TDTCustomThemedClock.DrawPointers;
  230. var
  231. Origin: TDTOrigin;
  232. {%H-}r: integer;
  233. Xs, Ys, Xm, Ym, Xh, Yh: integer;
  234. th, tm, ts, tn: word;
  235. begin
  236. Origin := Initializebitmap(FPointerBitmap, Width, Height);
  237. r := round(Origin.Radius * 0.85);
  238. //// Convert current time to integer values
  239. decodetime(Time, th, tm, ts, tn);
  240. //{ Set coordinates (length of arm) for seconds }
  241. Xs := Origin.CenterPoint.x + Round(SecondsPointerSettings.Length * Sin(ts * 6 * Pi / 180));
  242. Ys := Origin.CenterPoint.y - Round(SecondsPointerSettings.Length * Cos(ts * 6 * Pi / 180));
  243. //{ Set coordinates (length of arm) for minutes }
  244. Xm := Origin.CenterPoint.x + Round(MinutesPointerSettings.Length * Sin(tm * 6 * Pi / 180));
  245. Ym := Origin.CenterPoint.y - Round(MinutesPointerSettings.Length * Cos(tm * 6 * Pi / 180));
  246. //{ Set coordinates (length of arm) for hours }
  247. Xh := Origin.CenterPoint.x + Round(HoursPointerSettings.Length * Sin((th * 30 + tm / 2) * Pi / 180));
  248. Yh := Origin.CenterPoint.y - Round(HoursPointerSettings.Length * Cos((th * 30 + tm / 2) * Pi / 180));
  249. FPointerBitmap.DrawLineAntialias(Origin.CenterPoint.x, Origin.CenterPoint.y, xs, ys, SecondsPointerSettings.Color, SecondsPointerSettings.Thickness);
  250. FPointerBitmap.DrawLineAntialias(Origin.CenterPoint.x, Origin.CenterPoint.y, xm, ym, MinutesPointerSettings.Color, MinutesPointerSettings.Thickness);
  251. FPointerBitmap.DrawLineAntialias(Origin.CenterPoint.x, Origin.CenterPoint.y, xh, yh, HoursPointerSettings.Color, HoursPointerSettings.Thickness);
  252. // Draw cap over needle
  253. FPointerBitmap.EllipseAntialias(origin.CenterPoint.x, origin.CenterPoint.y, PointerCapSettings.Radius, PointerCapSettings.Radius, PointerCapSettings.EdgeColor, 2, ColorToBGRA(PointerCapSettings.FillColor));
  254. end;
  255. end.