305 lines
7.3 KiB
ObjectPascal
305 lines
7.3 KiB
ObjectPascal
// SPDX-License-Identifier: LGPL-3.0-linking-exception
|
|
{
|
|
Part of BGRA Controls. Made by third party.
|
|
For detailed information see readme.txt
|
|
|
|
Site: https://sourceforge.net/p/bgra-controls/
|
|
Wiki: http://wiki.lazarus.freepascal.org/BGRAControls
|
|
Forum: http://forum.lazarus.freepascal.org/index.php/board,46.0.html
|
|
}
|
|
{******************************* CONTRIBUTOR(S) ******************************
|
|
- Edivando S. Santos Brasil | mailedivando@gmail.com
|
|
(Compatibility with delphi VCL 11/2018)
|
|
|
|
***************************** END CONTRIBUTOR(S) *****************************}
|
|
unit DTAnalogClock;
|
|
|
|
{$I bgracontrols.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, {$IFDEF FPC}LResources,{$ENDIF}
|
|
Forms, Controls, Graphics, Dialogs, ExtCtrls,
|
|
{$IFNDEF FPC}Types, BGRAGraphics, GraphType, FPImage, {$ENDIF}
|
|
BCBaseCtrls, BGRABitmap, BGRABitmapTypes, BGRAGradients;
|
|
|
|
type
|
|
TClockStyle = (stlBlue, stlGreen, stlWhite);
|
|
|
|
{ TDTCustomAnalogClock }
|
|
|
|
TDTCustomAnalogClock = class(TBGRAGraphicCtrl)
|
|
private
|
|
FClockStyle: TClockStyle;
|
|
FBitmap: TBGRABitmap;
|
|
FClockFace: TBGRABitmap;
|
|
FEnabled: boolean;
|
|
FMovingParts: TBGRABitmap;
|
|
FTimer: TTimer;
|
|
FResized: boolean;
|
|
procedure SetClockStyle(AValue: TClockStyle);
|
|
{ Private declarations }
|
|
protected
|
|
procedure SetEnabled(AValue: boolean); override;
|
|
{ Protected declarations }
|
|
procedure Paint; override;
|
|
procedure DrawClock; virtual;
|
|
procedure DrawClockFace; virtual;
|
|
procedure DrawMovingParts; virtual;
|
|
procedure SwitchTimer;
|
|
|
|
procedure TimerEvent({%H-}Sender: TObject);
|
|
procedure ResizeEvent({%H-}Sender: TObject);
|
|
public
|
|
{ Public declarations }
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
property Enabled: boolean read FEnabled write SetEnabled;// default False;
|
|
end;
|
|
|
|
TDTAnalogClock = class(TDTCustomAnalogClock)
|
|
private
|
|
{ Private declarations }
|
|
protected
|
|
{ Protected declarations }
|
|
public
|
|
{ Public declarations }
|
|
published
|
|
{ Published declarations }
|
|
//property ClockStyle;
|
|
property Enabled;
|
|
end;
|
|
|
|
{$IFDEF FPC}procedure Register;{$ENDIF}
|
|
|
|
implementation
|
|
|
|
{ TDTCustomAnalogClock }
|
|
|
|
constructor TDTCustomAnalogClock.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
|
|
OnResize := ResizeEvent;
|
|
|
|
Width := 128;
|
|
Height := 128;
|
|
|
|
FBitmap := TBGRABitmap.Create;
|
|
FClockFace := TBGRABitmap.Create;
|
|
FMovingParts := TBGRABitmap.Create;
|
|
|
|
FBitmap.SetSize(Width, Height);
|
|
|
|
DrawClockFace;
|
|
DrawMovingParts;
|
|
|
|
|
|
FTimer := TTimer.Create(Self);
|
|
FTimer.Interval := 1000;
|
|
FTimer.Enabled := FEnabled;
|
|
FTimer.OnTimer := TimerEvent;
|
|
|
|
end;
|
|
|
|
destructor TDTCustomAnalogClock.Destroy;
|
|
begin
|
|
FTimer.Enabled:=False;
|
|
FTimer.OnTimer:=nil;
|
|
FBitmap.Free;
|
|
FClockFace.Free;
|
|
FMovingParts.Free;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.DrawClock;
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.DrawClockFace;
|
|
var
|
|
img: TBGRABitmap;
|
|
A: integer;
|
|
w, h, r, Xo, Yo, X, Y, Xt, Yt: integer;
|
|
phong: TPhongShading;
|
|
begin
|
|
w := Width;
|
|
h := Height;
|
|
|
|
{ Set center point }
|
|
Xo := w div 2;
|
|
Yo := h div 2;
|
|
|
|
// Determine radius. If canvas is rectangular then r = shortest length w or h
|
|
r := yo;
|
|
|
|
if xo > yo then
|
|
r := yo;
|
|
|
|
if xo < yo then
|
|
r := xo;
|
|
|
|
img := TBGRABitmap.Create(w, h);
|
|
|
|
// Draw Bitmap frame
|
|
img.FillEllipseAntialias(Xo, Yo, r * 0.99, r * 0.99, BGRA(175, 175, 175));
|
|
|
|
// Draw Rounded/RIng type border using shading
|
|
phong := TPhongShading.Create;
|
|
phong.LightPosition := point(Xo, Yo);
|
|
phong.DrawSphere(img, rect(round(Xo - r * 0.98), round(Yo - r * 0.98), round(Xo + r * 0.98) + 1, round(Yo + r * 0.98) + 1), 4, BGRA(245, 245, 245));
|
|
phong.Free;
|
|
img.EllipseAntialias(Xo, Yo, r * 0.99, r * 0.99, ColorToBGRA(clBlack, 110), 1);
|
|
|
|
img.FillEllipseLinearColorAntialias(Xo, Yo, r * 0.88, r * 0.88, BGRA(0, 58, 81), BGRA(2, 94, 131));
|
|
|
|
// Draw Face frame
|
|
img.FillEllipseAntialias(Xo, Yo, r * 0.90, r * 0.90, BGRA(175, 175, 175));
|
|
|
|
// Draw face background
|
|
img.FillEllipseLinearColorAntialias(Xo, Yo, r * 0.88, r * 0.88, BGRA(0, 58, 81), BGRA(2, 94, 131));
|
|
|
|
// Draw Bitmap face
|
|
for A := 1 to 12 do
|
|
begin
|
|
X := Xo + Round(r * 0.80 * sin(30 * A * Pi / 180));
|
|
Y := Yo - Round(r * 0.80 * cos(30 * A * Pi / 180));
|
|
Xt := Xo + Round(r * 0.70 * sin(30 * A * Pi / 180));
|
|
Yt := Yo - Round(r * 0.70 * cos(30 * A * Pi / 180));
|
|
img.EllipseAntialias(x, y, (r * 0.02), (r * 0.02), BGRA(255, 255, 255, 200), 2, BGRA(2, 94, 131));
|
|
|
|
img.FontName := 'Calibri';
|
|
img.FontHeight := r div 8;
|
|
img.FontQuality := fqFineAntialiasing;
|
|
img.TextOut(Xt, Yt - (img.FontHeight / 1.7), IntToStr(A), BGRA(245, 245, 245), taCenter);
|
|
end;
|
|
|
|
FClockFace.Fill(BGRA(0, 0, 0, 0));
|
|
FClockFace.Assign(img);
|
|
|
|
img.Free;
|
|
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.DrawMovingParts;
|
|
var
|
|
img: TBGRABitmap;
|
|
w, h, r, Xo, Yo: integer;
|
|
Xs, Ys, Xm, Ym, Xh, Yh: integer;
|
|
th, tm, ts, tn: word;
|
|
begin
|
|
|
|
w := Width;
|
|
h := Height;
|
|
|
|
{ Set center point }
|
|
Xo := w div 2;
|
|
Yo := h div 2;
|
|
|
|
// Determine radius. If canvas is rectangular then r = shortest length w or h
|
|
r := yo;
|
|
|
|
if xo > yo then
|
|
r := yo;
|
|
|
|
if xo < yo then
|
|
r := xo;
|
|
|
|
//// Convert current time to integer values
|
|
decodetime(Time, th, tm, ts, tn);
|
|
|
|
//{ Set coordinates (length of arm) for seconds }
|
|
Xs := Xo + Round(r * 0.78 * Sin(ts * 6 * Pi / 180));
|
|
Ys := Yo - Round(r * 0.78 * Cos(ts * 6 * Pi / 180));
|
|
|
|
//{ Set coordinates (length of arm) for minutes }
|
|
Xm := Xo + Round(r * 0.68 * Sin(tm * 6 * Pi / 180));
|
|
Ym := Yo - Round(r * 0.68 * Cos(tm * 6 * Pi / 180));
|
|
|
|
//{ Set coordinates (length of arm) for hours }
|
|
Xh := Xo + Round(r * 0.50 * Sin((th * 30 + tm / 2) * Pi / 180));
|
|
Yh := Yo - Round(r * 0.50 * Cos((th * 30 + tm / 2) * Pi / 180));
|
|
|
|
img := TBGRABitmap.Create(w, h);
|
|
|
|
// Draw time hands
|
|
img.DrawLineAntialias(xo, yo, xs, ys, BGRA(255, 0, 0), r * 0.02);
|
|
img.DrawLineAntialias(xo, yo, xm, ym, BGRA(245, 245, 245), r * 0.03);
|
|
img.DrawLineAntialias(xo, yo, xh, yh, BGRA(245, 245, 245), r * 0.07);
|
|
img.DrawLineAntialias(xo, yo, xh, yh, BGRA(2, 94, 131), r * 0.04);
|
|
|
|
// Draw Bitmap centre dot
|
|
img.EllipseAntialias(Xo, Yo, r * 0.04, r * 0.04, BGRA(245, 245, 245, 255), r * 0.02, BGRA(210, 210, 210, 255));
|
|
|
|
// Clear bitmap first
|
|
FMovingParts.Fill(BGRA(0, 0, 0, 0));
|
|
FMovingParts.Assign(img);
|
|
|
|
img.Free;
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.SwitchTimer;
|
|
begin
|
|
FTimer.Enabled := Enabled;
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.Paint;
|
|
begin
|
|
inherited Paint;
|
|
|
|
FBitmap.SetSize(Width, Height);
|
|
FBitMap.Fill(BGRA(0, 0, 0, 0));
|
|
|
|
if FResized then
|
|
begin
|
|
DrawClockFace;
|
|
DrawMovingParts;
|
|
FResized := False;
|
|
end;
|
|
|
|
FBitmap.BlendImage(0, 0, FClockFace, boLinearBlend);
|
|
FBitmap.BlendImage(0, 0, FMovingParts, boLinearBlend);
|
|
|
|
FBitmap.Draw(Canvas, 0, 0, False);
|
|
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.ResizeEvent(Sender: TObject);
|
|
begin
|
|
FResized := True;
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.SetClockStyle(AValue: TClockStyle);
|
|
begin
|
|
if FClockStyle = AValue then
|
|
Exit;
|
|
FClockStyle := AValue;
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.SetEnabled(AValue: boolean);
|
|
begin
|
|
if FEnabled = AValue then
|
|
Exit;
|
|
FEnabled := AValue;
|
|
SwitchTimer;
|
|
end;
|
|
|
|
procedure TDTCustomAnalogClock.TimerEvent(Sender: TObject);
|
|
begin
|
|
DrawMovingParts;
|
|
Refresh;
|
|
end;
|
|
|
|
{$IFDEF FPC}
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents('BGRA Controls', [TDTAnalogClock]);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
|
|
end.
|