Browse Source

Added Analog Controls.
There is an -unfinished?- file DTAnalogGauge, it uses some properties that aren't published and nowhere..
DTAnalogClock crash -something related with the timer- and has some memory leaks, I've fixed them.

lainz 11 years ago
parent
commit
ef6db99a15

+ 35 - 11
bgracontrols.lpk

@@ -27,7 +27,7 @@
       </Other>
       </Other>
     </CompilerOptions>
     </CompilerOptions>
     <Version Major="3" Minor="1"/>
     <Version Major="3" Minor="1"/>
-    <Files Count="27">
+    <Files Count="32">
       <Item1>
       <Item1>
         <Filename Value="bcbasectrls.pas"/>
         <Filename Value="bcbasectrls.pas"/>
         <UnitName Value="BCBaseCtrls"/>
         <UnitName Value="BCBaseCtrls"/>
@@ -110,7 +110,7 @@
       <Item18>
       <Item18>
         <Filename Value="bgraresizespeedbutton.pas"/>
         <Filename Value="bgraresizespeedbutton.pas"/>
         <HasRegisterProc Value="True"/>
         <HasRegisterProc Value="True"/>
-        <UnitName Value="bgraresizespeedbutton"/>
+        <UnitName Value="BGRAResizeSpeedButton"/>
       </Item18>
       </Item18>
       <Item19>
       <Item19>
         <Filename Value="bgrashape.pas"/>
         <Filename Value="bgrashape.pas"/>
@@ -133,30 +133,54 @@
         <UnitName Value="BGRAVirtualScreen"/>
         <UnitName Value="BGRAVirtualScreen"/>
       </Item22>
       </Item22>
       <Item23>
       <Item23>
-        <Filename Value="ueknob.pas"/>
+        <Filename Value="dtanalogclock.pas"/>
         <HasRegisterProc Value="True"/>
         <HasRegisterProc Value="True"/>
-        <UnitName Value="uEKnob"/>
+        <UnitName Value="DTAnalogClock"/>
       </Item23>
       </Item23>
       <Item24>
       <Item24>
+        <Filename Value="dtanalogcommon.pp"/>
+        <UnitName Value="DTAnalogCommon"/>
+      </Item24>
+      <Item25>
+        <Filename Value="dtanaloggauge.pp"/>
+        <AddToUsesPkgSection Value="False"/>
+        <UnitName Value="DTAnalogGauge"/>
+      </Item25>
+      <Item26>
+        <Filename Value="dtthemedclock.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="dtthemedclock"/>
+      </Item26>
+      <Item27>
+        <Filename Value="dtthemedgauge.pp"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="dtthemedgauge"/>
+      </Item27>
+      <Item28>
+        <Filename Value="ueknob.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="uEKnob"/>
+      </Item28>
+      <Item29>
         <Filename Value="ueled.pas"/>
         <Filename Value="ueled.pas"/>
         <HasRegisterProc Value="True"/>
         <HasRegisterProc Value="True"/>
         <UnitName Value="ueled"/>
         <UnitName Value="ueled"/>
-      </Item24>
-      <Item25>
+      </Item29>
+      <Item30>
         <Filename Value="uemultiturn.pas"/>
         <Filename Value="uemultiturn.pas"/>
         <HasRegisterProc Value="True"/>
         <HasRegisterProc Value="True"/>
         <UnitName Value="uEMultiTurn"/>
         <UnitName Value="uEMultiTurn"/>
-      </Item25>
-      <Item26>
+      </Item30>
+      <Item31>
         <Filename Value="uerotimage.pas"/>
         <Filename Value="uerotimage.pas"/>
         <HasRegisterProc Value="True"/>
         <HasRegisterProc Value="True"/>
         <UnitName Value="uERotImage"/>
         <UnitName Value="uERotImage"/>
-      </Item26>
-      <Item27>
+      </Item31>
+      <Item32>
         <Filename Value="ueselector.pas"/>
         <Filename Value="ueselector.pas"/>
         <HasRegisterProc Value="True"/>
         <HasRegisterProc Value="True"/>
         <UnitName Value="uESelector"/>
         <UnitName Value="uESelector"/>
-      </Item27>
+      </Item32>
     </Files>
     </Files>
     <Type Value="RunAndDesignTime"/>
     <Type Value="RunAndDesignTime"/>
     <RequiredPkgs Count="2">
     <RequiredPkgs Count="2">

+ 5 - 1
bgracontrols.pas

@@ -11,7 +11,8 @@ uses
   BCLabel, BCPanel, BCRTTI, BCStylesForm, BCTools, BGRAFlashProgressBar, 
   BCLabel, BCPanel, BCRTTI, BCStylesForm, BCTools, BGRAFlashProgressBar, 
   BGRAGraphicControl, BGRAImageList, BGRAImageManipulation, BGRAKnob, 
   BGRAGraphicControl, BGRAImageList, BGRAImageManipulation, BGRAKnob, 
   BGRAResizeSpeedButton, BGRAShape, BGRASpeedButton, BGRASpriteAnimation, 
   BGRAResizeSpeedButton, BGRAShape, BGRASpeedButton, BGRASpriteAnimation, 
-  BGRAVirtualScreen, uEKnob, ueled, uEMultiTurn, uERotImage, uESelector, 
+  BGRAVirtualScreen, DTAnalogClock, DTAnalogCommon, dtthemedclock, 
+  dtthemedgauge, uEKnob, ueled, uEMultiTurn, uERotImage, uESelector, 
   LazarusPackageIntf;
   LazarusPackageIntf;
 
 
 implementation
 implementation
@@ -33,6 +34,9 @@ begin
   RegisterUnit('BGRASpeedButton', @BGRASpeedButton.Register);
   RegisterUnit('BGRASpeedButton', @BGRASpeedButton.Register);
   RegisterUnit('BGRASpriteAnimation', @BGRASpriteAnimation.Register);
   RegisterUnit('BGRASpriteAnimation', @BGRASpriteAnimation.Register);
   RegisterUnit('BGRAVirtualScreen', @BGRAVirtualScreen.Register);
   RegisterUnit('BGRAVirtualScreen', @BGRAVirtualScreen.Register);
+  RegisterUnit('DTAnalogClock', @DTAnalogClock.Register);
+  RegisterUnit('dtthemedclock', @dtthemedclock.Register);
+  RegisterUnit('dtthemedgauge', @dtthemedgauge.Register);
   RegisterUnit('uEKnob', @uEKnob.Register);
   RegisterUnit('uEKnob', @uEKnob.Register);
   RegisterUnit('ueled', @ueled.Register);
   RegisterUnit('ueled', @ueled.Register);
   RegisterUnit('uEMultiTurn', @uEMultiTurn.Register);
   RegisterUnit('uEMultiTurn', @uEMultiTurn.Register);

+ 5 - 1
docs/readme.txt

@@ -1,4 +1,4 @@
-BGRAControls v3.1.0.0
+BGRAControls v3.2.0.0
 
 
 Site: https://sourceforge.net/p/bgra-controls/
 Site: https://sourceforge.net/p/bgra-controls/
 Wiki: http://wiki.lazarus.freepascal.org/BGRAControls
 Wiki: http://wiki.lazarus.freepascal.org/BGRAControls
@@ -53,4 +53,8 @@ BGRA Controls
 
 
 == uEcontrols ==
 == uEcontrols ==
 - From http://sourceforge.net/projects/uecontrols/ version 5.14. Author Miguel Alberto Risco Castillo.
 - From http://sourceforge.net/projects/uecontrols/ version 5.14. Author Miguel Alberto Risco Castillo.
+- Changes: changed icon folder and components tab in register procedure, removed package units to add all the units in the bgracontrols package.
+
+== DT Analog Controls ==
+- From http://forum.lazarus.freepascal.org/index.php/topic,19700.msg118916.html#msg118916 Author digeo.
 - Changes: changed icon folder and components tab in register procedure, removed package units to add all the units in the bgracontrols package.
 - Changes: changed icon folder and components tab in register procedure, removed package units to add all the units in the bgracontrols package.

+ 288 - 0
dtanalogclock.pas

@@ -0,0 +1,288 @@
+unit DTAnalogClock;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
+  BGRABitmap, BGRABitmapTypes, BGRAGradients, DTAnalogCommon;
+
+type
+  TClockStyle = (stlBlue, stlGreen, stlWhite);
+
+  { TDTCustomAnalogClock }
+
+  TDTCustomAnalogClock = class(TGraphicControl)
+  private
+    FClockStyle: TClockStyle;
+    FBitmap: TBGRABitmap;
+    FClockFace: TBGRABitmap;
+    FEnabled: boolean;
+    FMovingParts: TBGRABitmap;
+    FTimer: TTimer;
+    FResized: boolean;
+    procedure SetClockStyle(AValue: TClockStyle);
+    procedure SetEnabled(AValue: boolean);
+    { Private declarations }
+  protected
+    { Protected declarations }
+    procedure Paint; override;
+    procedure DrawClock; virtual;
+    procedure DrawClockFace; virtual;
+    procedure DrawMovingParts; virtual;
+    procedure SwitchTimer;
+
+    procedure TimerEvent(Sender: TObject);
+    procedure ResizeEvent(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;
+
+procedure Register;
+
+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;
+  txt: TBGRACustomBitmap;
+  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;
+
+procedure Register;
+begin
+  {$I icons\dtanalogclock_icon.lrs}
+  RegisterComponents('BGRA Controls', [TDTAnalogClock]);
+end;
+
+
+end.

+ 856 - 0
dtanalogcommon.pp

@@ -0,0 +1,856 @@
+unit DTAnalogCommon;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
+  BGRABitmap, BGRABitmapTypes;
+
+type
+  TDTFillStyle = (fsnone, fsGradient{, fsTexture});
+
+  TDTNeedleStyle = (nsLine, nsTriangle{, nsLineExt, nsTriangleExt});
+
+  { TDTOrigin }
+
+  TDTOrigin = packed record
+    CenterPoint: TPoint;
+    Radius: integer;
+  end;
+
+  { TDTPointerCapSettings }
+
+  TDTPointerCapSettings = class(TPersistent)
+  private
+    FEdgeColor: TColor;
+    FEdgeThickness: integer;
+    FFillColor: TColor;
+    FOnChange: TNotifyEvent;
+    FRadius: integer;
+    procedure SetEdgeColor(AValue: TColor);
+    procedure SetEdgeThickness(AValue: integer);
+    procedure SetFillColor(AValue: TColor);
+    procedure SetOnChange(AValue: TNotifyEvent);
+    procedure SetRadius(AValue: integer);
+  protected
+  public
+    constructor Create;
+    destructor Destroy; override;
+    property OnChange: TNotifyEvent read FOnChange write SetOnChange;
+  published
+    property EdgeColor: TColor read FEdgeColor write SetEdgeColor;
+    property FillColor: TColor read FFillColor write SetFillColor;
+    property Radius: integer read FRadius write SetRadius;
+    property EdgeThickness: integer read FEdgeThickness write SetEdgeThickness;
+  end;
+
+  { TDTPointerSettings }
+
+  TDTPointerSettings = class(TPersistent)
+  private
+    FColor: TColor;
+    FLength: integer;
+    FOnChange: TNotifyEvent;
+    FThickness: integer;
+    procedure SetColor(AValue: TColor);
+    procedure SetLength(AValue: integer);
+    procedure SetOnChange(AValue: TNotifyEvent);
+    procedure SetThickness(AValue: integer);
+  protected
+  public
+    constructor Create;
+    destructor Destroy; override;
+    property OnChange: TNotifyEvent read FOnChange write SetOnChange;
+  published
+    property Color: TColor read FColor write SetColor;
+    property Length: integer read FLength write SetLength;
+    property Thickness: integer read FThickness write SetThickness;
+  end;
+
+  { TDTNeedleSettings }
+
+  TDTNeedleSettings = class(TPersistent)
+  private
+    FCapColor: TColor;
+    FCapEdgeColor: TColor;
+    FCapRadius: integer;
+    FNeedleColor: TColor;
+    FNeedleLength: integer;
+    FNeedleStyle: TDTNeedleStyle;
+    FOnChange: TNotifyEvent;
+    procedure SetCapColor(AValue: TColor);
+    procedure SetCapEdgeColor(AValue: TColor);
+    procedure SetCapRadius(AValue: integer);
+    procedure SetNeedleColor(AValue: TColor);
+    procedure SetNeedleLength(AValue: integer);
+    procedure SetNeedleStyle(AValue: TDTNeedleStyle);
+    procedure SetOnChange(AValue: TNotifyEvent);
+  protected
+  public
+    constructor Create;
+    destructor Destroy; override;
+    property OnChange: TNotifyEvent read FOnChange write SetOnChange;
+    property NeedleStyle: TDTNeedleStyle read FNeedleStyle write SetNeedleStyle;
+  published
+    property NeedleColor: TColor read FNeedleColor write SetNeedleColor;
+    property NeedleLength: integer read FNeedleLength write SetNeedleLength;
+    property CapRadius: integer read FCapRadius write SetCapRadius;
+    property CapColor: TColor read FCapColor write SetCapColor;
+    property CapEdgeColor: TColor read FCapEdgeColor write SetCapEdgeColor;
+  end;
+
+  { TDTScaleSettings }
+
+  TDTScaleSettings = class(TPersistent)
+  private
+    FEnableScaleText: boolean;
+    FMaximum: integer;
+    FTesting: boolean;
+    FTextFont: string;
+    FTextRadius: integer;
+    FTextSize: integer;
+    FTickColor: TColor;
+    FEnableMainTicks: boolean;
+    FEnableRangeIndicator: boolean;
+    FEnableSubTicks: boolean;
+    FLengthMainTick: integer;
+    FLengthSubTick: integer;
+    FMainTickCount: integer;
+    FMinimum: integer;
+    FOnChange: TNotifyEvent;
+    FSubTickCount: integer;
+    FTextColor: TColor;
+    FThicknessMainTick: integer;
+    FThicknessSubTick: integer;
+    procedure SetEnableScaleText(AValue: boolean);
+    procedure SetMaximum(AValue: integer);
+    procedure SetTesting(AValue: boolean);
+    procedure SetTextFont(AValue: string);
+    procedure SetTextRadius(AValue: integer);
+    procedure SetTextSize(AValue: integer);
+    procedure SetTickColor(AValue: TColor);
+    procedure SetEnableMainTicks(AValue: boolean);
+    procedure SetEnableRangeIndicator(AValue: boolean);
+    procedure SetEnableSubTicks(AValue: boolean);
+    procedure SetLengthMainTick(AValue: integer);
+    procedure SetLengthSubTick(AValue: integer);
+    procedure SetMainTickCount(AValue: integer);
+    procedure SetOnChange(AValue: TNotifyEvent);
+    procedure SetSubTickCount(AValue: integer);
+    procedure SetTextColor(AValue: TColor);
+    procedure SetThicknessMainTick(AValue: integer);
+    procedure SetThicknessSubTick(AValue: integer);
+  protected
+    property Testing: boolean read FTesting write SetTesting;
+  public
+    constructor Create;
+    destructor Destroy; override;
+    property OnChange: TNotifyEvent read FOnChange write SetOnChange;
+  published
+    property TickColor: TColor read FTickColor write SetTickColor;
+    property TextColor: TColor read FTextColor write SetTextColor;
+    property TextSize: integer read FTextSize write SetTextSize;
+    property TextFont: string read FTextFont write SetTextFont;
+    property EnableMainTicks: boolean read FEnableMainTicks write SetEnableMainTicks;
+    property EnableSubTicks: boolean read FEnableSubTicks write SetEnableSubTicks;
+    property EnableScaleText: boolean read FEnableScaleText write SetEnableScaleText;
+    property Maximum: integer read FMaximum write SetMaximum;
+    property MainTickCount: integer read FMainTickCount write SetMainTickCount;
+    property SubTickCount: integer read FSubTickCount write SetSubTickCount;
+    property LengthMainTick: integer read FLengthMainTick write SetLengthMainTick;
+    property LengthSubTick: integer read FLengthSubTick write SetLengthSubTick;
+    property ThicknessMainTick: integer read FThicknessMainTick write SetThicknessMainTick;
+    property ThicknessSubTick: integer read FThicknessSubTick write SetThicknessSubTick;
+    property TextRadius: integer read FTextRadius write SetTextRadius;
+
+    property EnableRangeIndicator: boolean read FEnableRangeIndicator write SetEnableRangeIndicator;
+    //property RangeMinValue: integer read FRangeMinValue write SetRangeMinValue;
+    //property RangeMidValue: integer read FRangeMidValue write SetRangeMidValue;
+    //property RangeMaxValue: integer read FRangeMaxValue write SetRangeMaxValue;
+    //property RangeMinColor: TColor read FRangeMinColor write SetRangeMinColor;
+    //property RangeMidColor: TColor read FRangeMidColor write SetRangeMidColor;
+    //property RangeMaxColor: TColor read FRangeMaxColor write SetRangeMaxColor;
+  end;
+
+  { TDTFaceSettings }
+
+  TDTFaceSettings = class(TPersistent)
+  private
+    FColorEnd: TColor;
+    FColorFrame: TColor;
+    FColorStart: TColor;
+    FFillStyle: TDTFillStyle;
+    FOnChange: TNotifyEvent;
+    procedure SetColorEnd(AValue: TColor);
+    procedure SetColorFrame(AValue: TColor);
+    procedure SetColorStart(AValue: TColor);
+    procedure SetFillStyle(AValue: TDTFillStyle);
+    procedure SetOnChange(AValue: TNotifyEvent);
+  protected
+  public
+    constructor Create;
+    destructor Destroy; override;
+    property OnChange: TNotifyEvent read FOnChange write SetOnChange;
+  published
+    property FillStyle: TDTFillStyle read FFillStyle write SetFillStyle;
+    property ColorFrame: TColor read FColorFrame write SetColorFrame;
+    property ColorStart: TColor read FColorStart write SetColorStart;
+    property ColorEnd: TColor read FColorEnd write SetColorEnd;
+  end;
+
+  { TDTBaseAnalogDevice }
+
+  TDTBaseAnalogDevice = class(TGraphicControl)
+  private
+    FFaceSettings: TDTFaceSettings;
+    FScaleSettings: TDTScaleSettings;
+    procedure SetFaceSettings(AValue: TDTFaceSettings);
+    procedure SetScaleSettings(AValue: TDTScaleSettings);
+  protected
+    procedure DoChange(Sender: TObject);
+  public
+    fGaugeBitmap: TBGRABitmap;
+    FFrameBitmap: TBGRABitmap;
+    FFaceBitmap: TBGRABitmap;
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    property FaceSettings: TDTFaceSettings read FFaceSettings write SetFaceSettings;
+    property ScaleSettings: TDTScaleSettings read FScaleSettings write SetScaleSettings;
+    procedure Paint; override;
+    procedure DrawGauge;
+    procedure DrawFrame;
+    procedure DrawFace;
+  end;
+
+function Initializebitmap(var Bitmap: TBGRABitmap; Width, Height: integer): TDTOrigin;
+
+implementation
+
+function Initializebitmap(var Bitmap: TBGRABitmap; Width, Height: integer): TDTOrigin;
+var
+  x, y: integer;
+begin
+
+  Bitmap.SetSize(Width, Height);
+
+  // Clear bitmap to transparent
+  BitMap.Fill(BGRA(0, 0, 0, 0));
+
+  // Get origin information
+  Result.CenterPoint.x := Width div 2;
+  Result.CenterPoint.y := Height div 2;
+
+  Result.Radius := Result.CenterPoint.y;
+
+  if Result.CenterPoint.x > Result.CenterPoint.y then
+    Result.Radius := Result.CenterPoint.y;
+
+  if Result.CenterPoint.x < Result.CenterPoint.y then
+    Result.Radius := Result.CenterPoint.x;
+
+end;
+
+{ TDTPointerCapSettings }
+
+procedure TDTPointerCapSettings.SetEdgeColor(AValue: TColor);
+begin
+  if FEdgeColor = AValue then
+    Exit;
+  FEdgeColor := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTPointerCapSettings.SetEdgeThickness(AValue: integer);
+begin
+  if FEdgeThickness = AValue then
+    Exit;
+  FEdgeThickness := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTPointerCapSettings.SetFillColor(AValue: TColor);
+begin
+  if FFillColor = AValue then
+    Exit;
+  FFillColor := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTPointerCapSettings.SetOnChange(AValue: TNotifyEvent);
+begin
+  if FOnChange = AValue then
+    Exit;
+  FOnChange := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTPointerCapSettings.SetRadius(AValue: integer);
+begin
+  if FRadius = AValue then
+    Exit;
+  FRadius := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+constructor TDTPointerCapSettings.Create;
+begin
+  FEdgeColor := $00CCDCDC;
+  FFillColor := $003F3F3F;
+  FRadius := 10;
+  FEdgeThickness := 1;
+end;
+
+destructor TDTPointerCapSettings.Destroy;
+begin
+  inherited Destroy;
+end;
+
+{ TDTPointerSettings }
+
+procedure TDTPointerSettings.SetColor(AValue: TColor);
+begin
+  if FColor = AValue then
+    Exit;
+  FColor := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTPointerSettings.SetLength(AValue: integer);
+begin
+  if FLength = AValue then
+    Exit;
+  FLength := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTPointerSettings.SetOnChange(AValue: TNotifyEvent);
+begin
+  if FOnChange = AValue then
+    Exit;
+  FOnChange := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTPointerSettings.SetThickness(AValue: integer);
+begin
+  if FThickness = AValue then
+    Exit;
+  FThickness := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+constructor TDTPointerSettings.Create;
+begin
+  FColor := BGRAToColor(BGRA(199, 199, 173));
+  FLength := 100;
+  FThickness := 3;
+end;
+
+destructor TDTPointerSettings.Destroy;
+begin
+  inherited Destroy;
+end;
+
+{ TDTBaseAnalogDevice }
+
+procedure TDTBaseAnalogDevice.SetFaceSettings(AValue: TDTFaceSettings);
+begin
+  if FFaceSettings = AValue then
+    Exit;
+  FFaceSettings := AValue;
+
+  DoChange(self);
+end;
+
+procedure TDTBaseAnalogDevice.SetScaleSettings(AValue: TDTScaleSettings);
+begin
+  if FScaleSettings = AValue then
+    Exit;
+  FScaleSettings := AValue;
+
+  DoChange(self);
+end;
+
+procedure TDTBaseAnalogDevice.DoChange(Sender: TObject);
+begin
+  Invalidate;
+end;
+
+constructor TDTBaseAnalogDevice.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+
+  Width := 240;
+  Height := 240;
+
+  FScaleSettings := TDTScaleSettings.Create;
+  ScaleSettings.OnChange := @DoChange;
+
+  ScaleSettings.TextRadius := round((Width * 0.6) / 2);
+
+  FFaceSettings := TDTFaceSettings.Create;
+  FaceSettings.OnChange := @DoChange;
+
+  FGaugeBitmap := TBGRABitmap.Create;
+  FFaceBitmap := TBGRABitmap.Create;
+  FFrameBitmap := TBGRABitmap.Create;
+
+end;
+
+destructor TDTBaseAnalogDevice.Destroy;
+begin
+  FScaleSettings.Free;
+  FFaceSettings.Free;
+
+  fGaugeBitmap.Free;
+  FFaceBitmap.Free;
+  FFrameBitmap.Free;
+  inherited Destroy;
+end;
+
+procedure TDTBaseAnalogDevice.Paint;
+begin
+  inherited Paint;
+  FGaugeBitmap.Fill(BGRA(0, 0, 0, 0));
+
+  fGaugeBitmap.SetSize(Width, Height);
+
+  DrawGauge;
+
+  FGaugeBitmap.BlendImage(0, 0, FFrameBitmap, boLinearBlend);
+  FGaugeBitmap.BlendImage(0, 0, FFaceBitmap, boLinearBlend);
+
+  FGaugeBitmap.Draw(Canvas, 0, 0, False);
+
+end;
+
+procedure TDTBaseAnalogDevice.DrawGauge;
+begin
+  DrawFrame;
+  DrawFace;
+end;
+
+procedure TDTBaseAnalogDevice.DrawFrame;
+var
+  Origin: TDTOrigin;
+  r: integer;
+begin
+
+  Origin := Initializebitmap(FFrameBitmap, Width, Height);
+
+  r := round(Origin.Radius * 0.95);
+
+  // Draw Bitmap frame
+  FFrameBitmap.FillEllipseAntialias(Origin.CenterPoint.x,
+    Origin.CenterPoint.y,
+    r, r, ColorToBGRA(FFaceSettings.ColorFrame));
+
+  // Draw thin antialiased border to smooth against background
+  FFrameBitmap.EllipseAntialias(Origin.CenterPoint.x,
+    Origin.CenterPoint.y,
+    r, r, ColorToBGRA(clBlack, 120), 1);
+
+end;
+
+procedure TDTBaseAnalogDevice.DrawFace;
+var
+  Origin: TDTOrigin;
+  r: integer;
+begin
+
+  Origin := Initializebitmap(FFaceBitmap, Width, Height);
+
+  r := round(Origin.Radius * 0.95) - 5;
+
+  case FFaceSettings.FillStyle of
+    fsGradient:
+      FFaceBitmap.FillEllipseLinearColorAntialias(Origin.CenterPoint.x, Origin.CenterPoint.y, r, r, ColorToBGRA(FFaceSettings.ColorStart), ColorToBGRA(FFaceSettings.ColorEnd));
+    fsnone:
+      FFaceBitmap.FillEllipseAntialias(Origin.CenterPoint.x, Origin.CenterPoint.y, r, r, ColorToBGRA(FFaceSettings.ColorStart));
+  end;
+
+end;
+
+{ TDTNeedleSettings }
+
+procedure TDTNeedleSettings.SetCapColor(AValue: TColor);
+begin
+  if FCapColor = AValue then
+    Exit;
+  FCapColor := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTNeedleSettings.SetCapEdgeColor(AValue: TColor);
+begin
+  if FCapEdgeColor = AValue then
+    Exit;
+  FCapEdgeColor := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTNeedleSettings.SetCapRadius(AValue: integer);
+begin
+  if FCapRadius = AValue then
+    Exit;
+  FCapRadius := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTNeedleSettings.SetNeedleColor(AValue: TColor);
+begin
+  if FNeedleColor = AValue then
+    Exit;
+  FNeedleColor := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTNeedleSettings.SetNeedleLength(AValue: integer);
+begin
+  if FNeedleLength = AValue then
+    Exit;
+  FNeedleLength := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTNeedleSettings.SetNeedleStyle(AValue: TDTNeedleStyle);
+begin
+  if FNeedleStyle = AValue then
+    Exit;
+  FNeedleStyle := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTNeedleSettings.SetOnChange(AValue: TNotifyEvent);
+begin
+  if FOnChange = AValue then
+    Exit;
+  FOnChange := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+constructor TDTNeedleSettings.Create;
+begin
+  FCapColor := BGRAToColor(BGRA(63, 63, 63));
+  FCapEdgeColor := BGRAToColor(BGRA(220, 220, 204));
+  FCapRadius := 10;
+
+  FNeedleStyle := nsLine;
+  FNeedleColor := BGRAToColor(BGRA(255, 81, 81));
+  FNeedleLength := 100;
+end;
+
+destructor TDTNeedleSettings.Destroy;
+begin
+  inherited Destroy;
+end;
+
+{ TDTScaleSettings }
+
+constructor TDTScaleSettings.Create;
+begin
+  FTickColor := BGRAToColor(bgra(223, 196, 125));
+  FTextColor := BGRAToColor(bgra(140, 208, 211));
+  FTextFont := 'Calibri';
+  FTextSize := 15;
+  FEnableMainTicks := True;
+  FEnableSubTicks := True;
+  FEnableScaleText := True;
+  FMainTickCount := 10;
+  FSubTickCount := 5;
+  FMaximum := 100;
+  FMinimum := 0;
+  FLengthMainTick := 15;
+  FLengthSubTick := 8;
+  FThicknessMainTick := 3;
+  FThicknessSubTick := 1;
+
+end;
+
+destructor TDTScaleSettings.Destroy;
+begin
+  inherited Destroy;
+end;
+
+procedure TDTScaleSettings.SetTextFont(AValue: string);
+begin
+  if FTextFont = AValue then
+    Exit;
+  FTextFont := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetEnableScaleText(AValue: boolean);
+begin
+  if FEnableScaleText = AValue then
+    Exit;
+  FEnableScaleText := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetMaximum(AValue: integer);
+begin
+  if FMaximum = AValue then
+    Exit;
+  FMaximum := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetTesting(AValue: boolean);
+begin
+  if FTesting = AValue then
+    Exit;
+  FTesting := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetTextRadius(AValue: integer);
+begin
+  if FTextRadius = AValue then
+    Exit;
+  FTextRadius := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetTextSize(AValue: integer);
+begin
+  if FTextSize = AValue then
+    Exit;
+  FTextSize := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetTickColor(AValue: TColor);
+begin
+  if FTickColor = AValue then
+    Exit;
+  FTickColor := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetEnableMainTicks(AValue: boolean);
+begin
+  if FEnableMainTicks = AValue then
+    Exit;
+  FEnableMainTicks := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetEnableRangeIndicator(AValue: boolean);
+begin
+  if FEnableRangeIndicator = AValue then
+    Exit;
+  FEnableRangeIndicator := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetEnableSubTicks(AValue: boolean);
+begin
+  if FEnableSubTicks = AValue then
+    Exit;
+  FEnableSubTicks := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetLengthMainTick(AValue: integer);
+begin
+  if FLengthMainTick = AValue then
+    Exit;
+  FLengthMainTick := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetLengthSubTick(AValue: integer);
+begin
+  if FLengthSubTick = AValue then
+    Exit;
+  FLengthSubTick := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetMainTickCount(AValue: integer);
+begin
+  if FMainTickCount = AValue then
+    Exit;
+  FMainTickCount := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetOnChange(AValue: TNotifyEvent);
+begin
+  if FOnChange = AValue then
+    Exit;
+  FOnChange := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetSubTickCount(AValue: integer);
+begin
+  if FSubTickCount = AValue then
+    Exit;
+  FSubTickCount := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetTextColor(AValue: TColor);
+begin
+  if FTextColor = AValue then
+    Exit;
+  FTextColor := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetThicknessMainTick(AValue: integer);
+begin
+  if FThicknessMainTick = AValue then
+    Exit;
+  FThicknessMainTick := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTScaleSettings.SetThicknessSubTick(AValue: integer);
+begin
+  if FThicknessSubTick = AValue then
+    Exit;
+  FThicknessSubTick := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+{ TDTFaceSettings }
+
+constructor TDTFaceSettings.Create;
+begin
+  FColorFrame := BGRAToColor(BGRA(35, 35, 35));
+  FColorStart := BGRAToColor(BGRA(63, 63, 63));
+  FColorEnd := BGRAToColor(BGRA(93, 93, 93));
+  FFillStyle := fsGradient;
+end;
+
+destructor TDTFaceSettings.Destroy;
+begin
+  inherited Destroy;
+end;
+
+procedure TDTFaceSettings.SetColorEnd(AValue: TColor);
+begin
+  if FColorEnd = AValue then
+    Exit;
+  FColorEnd := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTFaceSettings.SetColorFrame(AValue: TColor);
+begin
+  if FColorFrame = AValue then
+    Exit;
+  FColorFrame := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTFaceSettings.SetColorStart(AValue: TColor);
+begin
+  if FColorStart = AValue then
+    Exit;
+  FColorStart := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTFaceSettings.SetFillStyle(AValue: TDTFillStyle);
+begin
+  if FFillStyle = AValue then
+    Exit;
+  FFillStyle := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+procedure TDTFaceSettings.SetOnChange(AValue: TNotifyEvent);
+begin
+  if FOnChange = AValue then
+    Exit;
+  FOnChange := AValue;
+
+  if Assigned(FOnChange) then
+    FOnChange(Self);
+end;
+
+{ TDTBackGround }
+
+end.

+ 457 - 0
dtanaloggauge.pp

@@ -0,0 +1,457 @@
+unit DTAnalogGauge;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, DTAnalogCommon,
+  BGRABitmap, BGRABitmapTypes;
+
+type
+
+  TDTGaugeStyle = (gsCustom, gsDark, gsLight);
+
+
+  { TDTCustomAnalogGauge }
+
+  TDTCustomAnalogGauge = class(TGraphicControl)
+  private
+    FFaceSettings: TDTFaceSettings;
+    FGaugeStyle: TDTGaugeStyle;
+    FNeedleSettings: TDTNeedleSettings;
+    FPosition: integer;
+    FResized: boolean;
+    FGaugeBitmap: TBGRABitmap;
+    FGaugeBodyBitmap: TBGRABitmap;
+    FGaugeScaleBitmap: TBGRABitmap;
+    FGaugeNeedleBitmap: TBGRABitmap;
+    FScaleSettings: TDTScaleSettings;
+    procedure SetFaceSettings(AValue: TDTFaceSettings);
+    procedure DoChange(Sender: TObject);
+    procedure SetGaugeStyle(AValue: TDTGaugeStyle);
+    procedure SetNeedleSettings(AValue: TDTNeedleSettings);
+    procedure SetPosition(AValue: integer);
+    procedure SetScaleSettings(AValue: TDTScaleSettings);
+    { Private declarations }
+  protected
+    { Protected declarations }
+    procedure ResizeEvent(Sender: TObject);
+    procedure ClearBitMap(var BitMap: TBGRABitmap);
+  public
+    { Public declarations }
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure Paint; override;
+    procedure DrawGauge; virtual;
+    procedure DrawGaugeBody; virtual;
+    procedure DrawGaugeRange; virtual;
+    procedure DrawGaugeFace; virtual;
+    procedure DrawGaugeScale; virtual;
+    procedure DrawGaugeNeedle; virtual;
+  published
+    { Published declarations }
+    property Position: integer read FPosition write SetPosition;
+    property FaceSettings: TDTFaceSettings read FFaceSettings write SetFaceSettings;
+    property ScaleSettings: TDTScaleSettings read FScaleSettings write SetScaleSettings;
+    property NeedleSettings: TDTNeedleSettings read FNeedleSettings write SetNeedleSettings;
+    //property GaugeStyle: TDTGaugeStyle read FGaugeStyle write SetGaugeStyle;
+  end;
+
+  { TDTAnalogGauge }
+
+  TDTAnalogGauge = class(TDTCustomAnalogGauge)
+  private
+    { Private declarations }
+  protected
+    { Protected declarations }
+  public
+    { Public declarations }
+  published
+    { Published declarations }
+    property FaceSettings;
+    property ScaleSettings;
+    property NeedleSettings;
+  end;
+
+procedure Register;
+
+implementation
+
+procedure Register;
+begin
+  RegisterComponents('BGRA Controls', [TDTAnalogGauge]);
+end;
+
+{ TDTCustomAnalogGauge }
+
+procedure TDTCustomAnalogGauge.ClearBitMap(var BitMap: TBGRABitmap);
+begin
+  BitMap.Fill(BGRA(0, 0, 0, 0));
+end;
+
+constructor TDTCustomAnalogGauge.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+
+  Width := 240;
+  Height := 240;
+
+  FScaleSettings := TDTScaleSettings.Create;
+  ScaleSettings.OnChange := @DoChange;
+
+  FFaceSettings := TDTFaceSettings.Create;
+  FaceSettings.OnChange := @DoChange;
+
+  FNeedleSettings := TDTNeedleSettings.Create;
+  NeedleSettings.OnChange := @DoChange;
+
+  FGaugeBitmap := TBGRABitmap.Create(Width, Height);
+  FGaugeBodyBitmap := TBGRABitmap.Create(Width, Height);
+  FGaugeScaleBitmap := TBGRABitmap.Create(Width, Height);
+  FGaugeNeedleBitmap := TBGRABitmap.Create(Width, Height);
+
+end;
+
+destructor TDTCustomAnalogGauge.Destroy;
+begin
+  FScaleSettings.OnChange:=nil;
+  FScaleSettings.Free;
+  FFaceSettings.OnChange:=nil;
+  FFaceSettings.Free;
+  FGaugeBitmap.Free;
+  FGaugeBodyBitmap.Free;
+  FGaugeScaleBitmap.Free;
+  FGaugeNeedleBitmap.Free;
+  FNeedleSettings.OnChange:=nil;
+  FNeedleSettings.Free;
+  inherited Destroy;
+end;
+
+procedure TDTCustomAnalogGauge.DoChange(Sender: TObject);
+begin
+  Invalidate;
+end;
+
+procedure TDTCustomAnalogGauge.SetGaugeStyle(AValue: TDTGaugeStyle);
+begin
+  if FGaugeStyle = AValue then
+    Exit;
+  FGaugeStyle := AValue;
+
+  DoChange(self);
+
+end;
+
+procedure TDTCustomAnalogGauge.SetNeedleSettings(AValue: TDTNeedleSettings);
+begin
+  if FNeedleSettings = AValue then
+    Exit;
+  FNeedleSettings := AValue;
+
+  DoChange(self);
+
+end;
+
+procedure TDTCustomAnalogGauge.DrawGauge;
+begin
+  DrawGaugeBody;
+  DrawGaugeFace;
+
+  if FScaleSettings.EnableRangeIndicator then
+    DrawGaugeRange;
+
+  DrawGaugeScale;
+  DrawGaugeNeedle;
+end;
+
+procedure TDTCustomAnalogGauge.DrawGaugeBody;
+var
+  w, h, r, Xo, Yo: integer;
+  origin: TDTOrigin;
+begin
+
+  origin := Initializebitmap(FGaugeBodyBitmap, Width, Height);
+
+  //// Keep circle insde frame
+  r := round(origin.Radius * 0.95);
+
+  // Draw Bitmap frame
+  FGaugeBodyBitmap.FillEllipseAntialias(origin.CenterPoint.x,
+    origin.CenterPoint.y,
+    r, r, ColorToBGRA(FFaceSettings.ColorFrame));
+
+  // Draw thin antialiased border to smooth against background
+  FGaugeBodyBitmap.EllipseAntialias(origin.CenterPoint.x,
+    origin.CenterPoint.y,
+    r, r, ColorToBGRA(clBlack, 120), 1);
+
+end;
+
+procedure TDTCustomAnalogGauge.DrawGaugeRange;
+var
+  w, h, r, Xo, Yo, X, Y, Xt, Yt: integer;
+  n: integer;
+  j: single;
+begin
+
+  ClearBitMap(FGaugeScaleBitmap);
+
+  w := Width;
+  h := Height;
+
+  FGaugeScaleBitmap.SetSize(w, h);
+
+  { 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;
+
+  //j := (180 - FScaleSettings.Angle) / 2;
+
+end;
+
+procedure TDTCustomAnalogGauge.DrawGaugeFace;
+var
+  w, h, r, Xo, Yo: integer;
+  origin: TDTOrigin;
+begin
+  ClearBitMap(FGaugeScaleBitmap);
+
+  w := Width;
+  h := Height;
+
+  FGaugeBodyBitmap.SetSize(w, h);
+
+  //{ 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;
+
+  // Keep circle insde frame
+  r := round(r * 0.95) - 5;
+
+  // Draw face background
+  case FFaceSettings.FillStyle of
+    fsGradient:
+      FGaugeBodyBitmap.FillEllipseLinearColorAntialias(Xo, Yo, r, r, ColorToBGRA(FFaceSettings.ColorStart), ColorToBGRA(FFaceSettings.ColorEnd));
+    fsnone:
+      FGaugeBodyBitmap.FillEllipseAntialias(Xo, Yo, r, r, ColorToBGRA(FFaceSettings.ColorStart));
+  end;
+
+
+  //origin := Initializebitmap(FGaugeBodyBitmap, Width, Height);
+
+  //// Keep circle insde frame
+  //r := round(origin.Radius * 0.95) - 5;
+
+  //// Draw face background
+  //case FFaceSettings.FillStyle of
+  //  fsGradient:
+  //    FGaugeBodyBitmap.FillEllipseLinearColorAntialias(origin.CenterPoint.x, origin.CenterPoint.y, r, r, ColorToBGRA(FFaceSettings.ColorStart), ColorToBGRA(FFaceSettings.ColorEnd));
+  //  fsnone:
+  //    FGaugeBodyBitmap.FillEllipseAntialias(origin.CenterPoint.x, origin.CenterPoint.y, r, r, ColorToBGRA(FFaceSettings.ColorStart));
+  //end;
+
+end;
+
+procedure TDTCustomAnalogGauge.DrawGaugeScale;
+var
+  w, h, r, Xo, Yo, X, Y, Xt, Yt: integer;
+  i, n: integer;
+  j: single;
+begin
+
+  w := Width;
+  h := Height;
+
+  FGaugeScaleBitmap.SetSize(w, h);
+
+  ClearBitMap(FGaugeScaleBitmap);
+
+  { 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;
+
+  j := (180 - FScaleSettings.Angle) / 2;
+
+  // Draw SubTicks
+  if FScaleSettings.EnableSubTicks then
+  begin
+
+    n := FScaleSettings.MainTickCount * FScaleSettings.SubTickCount;
+
+    for i := 0 to n do
+    begin
+      // Calculate draw from point
+      X := xo - Round(r * 0.85 * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
+      Y := yo - Round(r * 0.85 * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
+
+      // Calculate draw to point
+      Xt := xo - Round(((r * 0.85) - FScaleSettings.LengthSubTick) * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
+      Yt := yo - Round(((r * 0.85) - FScaleSettings.LengthSubTick) * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
+
+      FGaugeScaleBitmap.DrawLineAntialias(x, y, xt, yt, ColorToBGRA(FScaleSettings.TickColor), FScaleSettings.ThicknessSubTick);
+
+    end;
+  end;
+
+  if FScaleSettings.EnableMainTicks then
+  begin
+
+    FGaugeScaleBitmap.FontName := FScaleSettings.TextFont;
+    FGaugeScaleBitmap.FontHeight := FScaleSettings.TextSize;
+    FGaugeScaleBitmap.FontQuality := fqFineAntialiasing;
+
+    n := FScaleSettings.MainTickCount;
+
+    for i := 0 to n do
+    begin
+      // Draw main ticks
+      // Calculate draw from point
+      X := xo - Round(r * 0.85 * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
+      Y := yo - Round(r * 0.85 * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
+
+      // Calculate draw to point
+      Xt := xo - Round(((r * 0.85) - FScaleSettings.LengthMainTick) * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
+      Yt := yo - Round(((r * 0.85) - FScaleSettings.LengthMainTick) * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
+
+      FGaugeScaleBitmap.DrawLineAntialias(x, y, xt, yt, ColorToBGRA(FScaleSettings.TickColor), FScaleSettings.ThicknessMainTick);
+
+      // Draw text for main ticks
+      Xt := xo - Round((r - FScaleSettings.LengthMainTick) * 0.7 * cos((j + i * FScaleSettings.Angle / n) * Pi / 180));
+      Yt := yo - Round((r - FScaleSettings.LengthMainTick) * 0.7 * sin((j + i * FScaleSettings.Angle / n) * Pi / 180));
+
+      FGaugeScaleBitmap.TextOut(Xt, Yt - (FGaugeScaleBitmap.FontHeight / 1.7),
+        IntToStr(i * FScaleSettings.Maximum div FScaleSettings.MainTickCount),
+        //ColorToBGRA(FScaleSettings.TickColor),
+        ColorToBGRA(FScaleSettings.TextColor),
+        taCenter);
+    end;
+  end;
+end;
+
+procedure TDTCustomAnalogGauge.DrawGaugeNeedle;
+var
+  w, h, Xo, Yo, X, Y: integer;
+  j: single;
+begin
+
+  ClearBitMap(FGaugeNeedleBitmap);
+
+  w := Width;
+  h := Height;
+
+  FGaugeNeedleBitmap.SetSize(w, h);
+
+  { Set center point }
+  Xo := w div 2;
+  Yo := h div 2;
+
+  j := (180 - FScaleSettings.Angle) / 2;
+
+  // Draw needle
+  case FNeedleSettings.NeedleStyle of
+    nsLine:
+    begin
+
+      X := xo - Round(FNeedleSettings.NeedleLength * cos((j + Position * FScaleSettings.Angle / FScaleSettings.Maximum) * Pi / 180));
+      Y := yo - Round(FNeedleSettings.NeedleLength * sin((j + Position * FScaleSettings.Angle / FScaleSettings.Maximum) * Pi / 180));
+
+      FGaugeNeedleBitmap.DrawLineAntialias(xo, yo, x, y,
+        ColorToBGRA(FNeedleSettings.NeedleColor),
+        FScaleSettings.ThicknessMainTick);
+    end;
+    nsTriangle:
+    begin
+
+    end;
+  end;
+
+  // Draw cap over needle
+  FGaugeNeedleBitmap.EllipseAntialias(Xo, Yo, FNeedleSettings.CapRadius,
+    FNeedleSettings.CapRadius,
+    ColorToBGRA(FNeedleSettings.CapEdgeColor),
+    2, ColorToBGRA(FNeedleSettings.CapColor));
+
+end;
+
+procedure TDTCustomAnalogGauge.SetFaceSettings(AValue: TDTFaceSettings);
+begin
+  if FFaceSettings = AValue then
+    Exit;
+  FFaceSettings := AValue;
+
+  DoChange(self);
+
+end;
+
+procedure TDTCustomAnalogGauge.SetPosition(AValue: integer);
+begin
+  if FPosition = AValue then
+    Exit;
+  FPosition := AValue;
+
+  DoChange(self);
+
+end;
+
+procedure TDTCustomAnalogGauge.SetScaleSettings(AValue: TDTScaleSettings);
+begin
+  if FScaleSettings = AValue then
+    Exit;
+  FScaleSettings := AValue;
+
+  DoChange(self);
+
+end;
+
+procedure TDTCustomAnalogGauge.ResizeEvent(Sender: TObject);
+begin
+  FResized := True;
+end;
+
+procedure TDTCustomAnalogGauge.Paint;
+begin
+  inherited Paint;
+
+  ClearBitMap(FGaugeBitmap);
+
+  FGaugeBitmap.SetSize(Width, Height);
+
+  DrawGauge;
+
+  FGaugeBitmap.BlendImage(0, 0, FGaugeBodyBitmap, boLinearBlend);
+  FGaugeBitmap.BlendImage(0, 0, FGaugeScaleBitmap, boLinearBlend);
+  FGaugeBitmap.BlendImage(0, 0, FGaugeNeedleBitmap, boLinearBlend);
+
+  FGaugeBitmap.Draw(Canvas, 0, 0, False);
+
+end;
+
+end.

+ 307 - 0
dtthemedclock.pas

@@ -0,0 +1,307 @@
+unit dtthemedclock;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, ExtCtrls, LResources, Forms, Controls, Graphics, Dialogs, DTAnalogCommon,
+  BGRABitmap, BGRABitmapTypes;
+
+type
+
+  { TDTCustomThemedClock }
+
+  TDTCustomThemedClock = class(TDTBaseAnalogDevice)
+  private
+    FClockFace: TBGRABitmap;
+    FPointerBitmap: TBGRABitmap;
+    FEnabled: boolean;
+    FHoursPointerSettings: TDTPointerSettings;
+    FMinutesPointerSettings: TDTPointerSettings;
+    FPointerCapSettings: TDTPointerCapSettings;
+    FPosition: integer;
+    FSecondsPointerSettings: TDTPointerSettings;
+    FTimer: TTimer;
+    procedure SetEnabled(AValue: boolean);
+    procedure SetHoursPointerSettings(AValue: TDTPointerSettings);
+    procedure SetMinutesPointerSettings(AValue: TDTPointerSettings);
+    procedure SetPointerCapSettings(AValue: TDTPointerCapSettings);
+    procedure SetPosition(AValue: integer);
+    procedure SetSecondsPointerSettings(AValue: TDTPointerSettings);
+    { Private declarations }
+  protected
+    { Protected declarations }
+    property SecondsPointerSettings: TDTPointerSettings read FSecondsPointerSettings write SetSecondsPointerSettings;
+    property MinutesPointerSettings: TDTPointerSettings read FMinutesPointerSettings write SetMinutesPointerSettings;
+    property HoursPointerSettings: TDTPointerSettings read FHoursPointerSettings write SetHoursPointerSettings;
+    property PointerCapSettings: TDTPointerCapSettings read FPointerCapSettings write SetPointerCapSettings;
+    property Position: integer read FPosition write SetPosition;
+    property Enabled: boolean read FEnabled write SetEnabled;
+    procedure TimerEvent(Sender: TObject);
+  public
+    { Public declarations }
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure Paint; override;
+    procedure DrawClock;
+    procedure DrawPointers;
+  end;
+
+  TDTThemedClock = class(TDTCustomThemedClock)
+  private
+    { Private declarations }
+  protected
+    { Protected declarations }
+  public
+    { Public declarations }
+  published
+    { Public declarations }
+    property SecondsPointerSettings;
+    property MinutesPointerSettings;
+    property HoursPointerSettings;
+    property PointerCapSettings;
+    property ScaleSettings;
+    property Position;
+    property Enabled;
+  end;
+
+procedure Register;
+
+implementation
+
+procedure Register;
+begin
+  RegisterComponents('BGRA Controls', [TDTThemedClock]);
+end;
+
+{ TDTCustomThemedClock }
+
+procedure TDTCustomThemedClock.SetPointerCapSettings(AValue: TDTPointerCapSettings);
+begin
+  if FPointerCapSettings = AValue then
+    Exit;
+  FPointerCapSettings := AValue;
+
+  DoChange(self);
+end;
+
+procedure TDTCustomThemedClock.SetHoursPointerSettings(AValue: TDTPointerSettings);
+begin
+  if FHoursPointerSettings = AValue then
+    Exit;
+  FHoursPointerSettings := AValue;
+
+  DoChange(self);
+end;
+
+procedure TDTCustomThemedClock.SetEnabled(AValue: boolean);
+begin
+  if FEnabled = AValue then
+    Exit;
+  FEnabled := AValue;
+
+  FTimer.Enabled := FEnabled;
+
+  DoChange(self);
+end;
+
+procedure TDTCustomThemedClock.SetMinutesPointerSettings(AValue: TDTPointerSettings);
+begin
+  if FMinutesPointerSettings = AValue then
+    Exit;
+  FMinutesPointerSettings := AValue;
+
+  DoChange(self);
+end;
+
+procedure TDTCustomThemedClock.SetPosition(AValue: integer);
+begin
+  if FPosition = AValue then
+    Exit;
+  FPosition := AValue;
+
+  DoChange(self);
+end;
+
+procedure TDTCustomThemedClock.SetSecondsPointerSettings(AValue: TDTPointerSettings);
+begin
+  if FSecondsPointerSettings = AValue then
+    Exit;
+  FSecondsPointerSettings := AValue;
+
+  DoChange(self);
+end;
+
+procedure TDTCustomThemedClock.TimerEvent(Sender: TObject);
+begin
+  DrawPointers;
+  DoChange(self);
+end;
+
+constructor TDTCustomThemedClock.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+
+  FSecondsPointerSettings := TDTPointerSettings.Create;
+  FSecondsPointerSettings.OnChange := @DoChange;
+  FMinutesPointerSettings := TDTPointerSettings.Create;
+  FMinutesPointerSettings.OnChange := @DoChange;
+  FHoursPointerSettings := TDTPointerSettings.Create;
+  FHoursPointerSettings.OnChange := @DoChange;
+
+  FPointerCapSettings := TDTPointerCapSettings.Create;
+  FPointerCapSettings.OnChange := @DoChange;
+
+  FClockFace := TBGRABitmap.Create;
+  FPointerBitmap := TBGRABitmap.Create;
+
+  FSecondsPointerSettings.Color := BGRAToColor(BGRA(255, 81, 81));
+  FSecondsPointerSettings.Length := 80;
+  FSecondsPointerSettings.Thickness := 3;
+
+  FMinutesPointerSettings.Color := BGRAToColor(BGRA(199, 199, 173));
+  FMinutesPointerSettings.Length := 80;
+  FMinutesPointerSettings.Thickness := 3;
+
+  FHoursPointerSettings.Color := BGRAToColor(BGRA(199, 199, 173));
+  FHoursPointerSettings.Length := 60;
+  FHoursPointerSettings.Thickness := 5;
+
+  FTimer := TTimer.Create(Self);
+  FTimer.Interval := 1000;
+  FTimer.Enabled := FEnabled;
+  FTimer.OnTimer := @TimerEvent;
+
+end;
+
+destructor TDTCustomThemedClock.Destroy;
+begin
+  FSecondsPointerSettings.OnChange:=nil;
+  FSecondsPointerSettings.Free;
+  FMinutesPointerSettings.OnChange:=nil;
+  FMinutesPointerSettings.Free;
+  FHoursPointerSettings.OnChange:=nil;
+  FHoursPointerSettings.Free;
+  FTimer.Enabled:=False;
+  FTimer.OnTimer:=nil;
+  FPointerCapSettings.OnChange:=nil;
+  FPointerCapSettings.Free;
+
+  FClockFace.Free;
+  FPointerBitmap.Free;
+
+  inherited Destroy;
+end;
+
+procedure TDTCustomThemedClock.Paint;
+begin
+  inherited Paint;
+
+  DrawClock;
+  DrawPointers;
+
+  FGaugeBitmap.BlendImage(0, 0, FClockFace, boLinearBlend);
+  FGaugeBitmap.BlendImage(0, 0, FPointerBitmap, boLinearBlend);
+
+  FGaugeBitmap.Draw(Canvas, 0, 0, False);
+end;
+
+procedure TDTCustomThemedClock.DrawClock;
+var
+  Origin: TDTOrigin;
+  r, i, x, y, xt, yt: integer;
+begin
+
+  Origin := Initializebitmap(FClockFace, Width, Height);
+
+  r := round(Origin.Radius * 0.85);
+
+  // Draw minor tick marks
+  if ScaleSettings.EnableSubTicks then
+  begin
+    for i := 1 to 60 do
+    begin
+      // Calculate draw from point
+      X := Origin.CenterPoint.x + Round(r * sin(6 * i * Pi / 180));
+      Y := Origin.CenterPoint.y - Round(r * cos(6 * i * Pi / 180));
+
+      // Calculate draw to point
+      xt := Origin.CenterPoint.x + Round((r - ScaleSettings.LengthSubTick) * sin(6 * i * Pi / 180));
+      yt := Origin.CenterPoint.y - Round((r - ScaleSettings.LengthSubTick) * cos(6 * i * Pi / 180));
+
+      FClockFace.DrawLineAntialias(x, y, xt, yt, ColorToBGRA(ScaleSettings.TickColor), ScaleSettings.ThicknessSubTick);
+    end;
+  end;
+
+  // Draw major tick marks
+  if ScaleSettings.EnableMainTicks then
+  begin
+    for i := 1 to 12 do
+    begin
+      // Calculate draw from point
+      X := Origin.CenterPoint.x + Round(r * sin(30 * i * Pi / 180));
+      Y := Origin.CenterPoint.y - Round(r * cos(30 * i * Pi / 180));
+
+      // Calculate draw to point
+      xt := Origin.CenterPoint.x + Round((r - ScaleSettings.LengthMainTick) * sin(30 * i * Pi / 180));
+      yt := Origin.CenterPoint.y - Round((r - ScaleSettings.LengthMainTick) * cos(30 * i * Pi / 180));
+
+      FClockFace.DrawLineAntialias(x, y, xt, yt, ColorToBGRA(ScaleSettings.TickColor), ScaleSettings.ThicknessMainTick);
+
+      if ScaleSettings.EnableScaleText then
+      begin
+        FClockFace.FontName := ScaleSettings.TextFont;
+        FClockFace.FontHeight := ScaleSettings.TextSize;
+        FClockFace.FontQuality := fqFineAntialiasing;
+
+        // Draw text for main ticks
+        xt := Origin.CenterPoint.x + Round(ScaleSettings.TextRadius * sin(30 * i * Pi / 180));
+        yt := Origin.CenterPoint.y - Round(ScaleSettings.TextRadius * cos(30 * i * Pi / 180));
+
+        FClockFace.TextOut(Xt, Yt - (FClockFace.FontHeight / 1.7), IntToStr(i), ColorToBGRA(ScaleSettings.TextColor), taCenter);
+      end;
+
+    end;
+  end;
+
+end;
+
+procedure TDTCustomThemedClock.DrawPointers;
+var
+  Origin: TDTOrigin;
+  r, i, x, y, xt, yt: integer;
+  Xs, Ys, Xm, Ym, Xh, Yh: integer;
+  th, tm, ts, tn: word;
+begin
+
+  Origin := Initializebitmap(FPointerBitmap, Width, Height);
+
+  r := round(Origin.Radius * 0.85);
+
+  //// Convert current time to integer values
+  decodetime(Time, th, tm, ts, tn);
+
+  //{ Set coordinates (length of arm) for seconds }
+  Xs := Origin.CenterPoint.x + Round(SecondsPointerSettings.Length * Sin(ts * 6 * Pi / 180));
+  Ys := Origin.CenterPoint.y - Round(SecondsPointerSettings.Length * Cos(ts * 6 * Pi / 180));
+
+  //{ Set coordinates (length of arm) for minutes }
+  Xm := Origin.CenterPoint.x + Round(MinutesPointerSettings.Length * Sin(tm * 6 * Pi / 180));
+  Ym := Origin.CenterPoint.y - Round(MinutesPointerSettings.Length * Cos(tm * 6 * Pi / 180));
+
+  //{ Set coordinates (length of arm) for hours }
+  Xh := Origin.CenterPoint.x + Round(HoursPointerSettings.Length * Sin((th * 30 + tm / 2) * Pi / 180));
+  Yh := Origin.CenterPoint.y - Round(HoursPointerSettings.Length * Cos((th * 30 + tm / 2) * Pi / 180));
+
+  FPointerBitmap.DrawLineAntialias(Origin.CenterPoint.x, Origin.CenterPoint.y, xs, ys, ColorToBGRA(SecondsPointerSettings.Color), SecondsPointerSettings.Thickness);
+  FPointerBitmap.DrawLineAntialias(Origin.CenterPoint.x, Origin.CenterPoint.y, xm, ym, ColorToBGRA(MinutesPointerSettings.Color), MinutesPointerSettings.Thickness);
+  FPointerBitmap.DrawLineAntialias(Origin.CenterPoint.x, Origin.CenterPoint.y, xh, yh, ColorToBGRA(HoursPointerSettings.Color), HoursPointerSettings.Thickness);
+
+  // Draw cap over needle
+  FPointerBitmap.EllipseAntialias(origin.CenterPoint.x, origin.CenterPoint.y, PointerCapSettings.Radius, PointerCapSettings.Radius, ColorToBGRA(PointerCapSettings.EdgeColor), 2, ColorToBGRA(PointerCapSettings.FillColor));
+
+
+end;
+
+end.

+ 238 - 0
dtthemedgauge.pp

@@ -0,0 +1,238 @@
+unit dtthemedgauge;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, DTAnalogCommon,
+  BGRABitmap, BGRABitmapTypes, DTAnalogClock;
+
+type
+
+  { TDTCustomThemedGauge }
+
+  TDTCustomThemedGauge = class(TDTBaseAnalogDevice)
+  private
+    FPointerCapSettings: TDTPointerCapSettings;
+    FPointerSettings: TDTPointerSettings;
+    FScaleBitmap: TBGRABitmap;
+    FPointerBitmap: TBGRABitmap;
+    FPosition: integer;
+    procedure SetPointerCapSettings(AValue: TDTPointerCapSettings);
+    procedure SetPointerSettings(AValue: TDTPointerSettings);
+    procedure SetPosition(AValue: integer);
+    { Private declarations }
+  protected
+    { Protected declarations }
+    property PointerSettings: TDTPointerSettings read FPointerSettings write SetPointerSettings;
+    property PointerCapSettings: TDTPointerCapSettings read FPointerCapSettings write SetPointerCapSettings;
+    property Position: integer read FPosition write SetPosition;
+  public
+    { Public declarations }
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure Paint; override;
+    procedure DrawScale;
+    procedure DrawPointer;
+  end;
+
+  { TDTThemedGauge }
+
+  TDTThemedGauge = class(TDTCustomThemedGauge)
+  private
+    { Private declarations }
+  protected
+    { Protected declarations }
+  public
+    { Public declarations }
+  published
+    { Published declarations }
+    property FaceSettings;
+    property ScaleSettings;
+    property PointerSettings;
+    property PointerCapSettings;
+    property Position;
+  end;
+
+procedure Register;
+
+implementation
+
+procedure Register;
+begin
+  RegisterComponents('BGRA Controls', [TDTThemedGauge]);
+end;
+
+{ TDTCustomThemedGauge }
+
+//procedure TDTCustomThemedGauge.SetNeedleSettings(AValue: TDTNeedleSettings);
+//begin
+//  if FNeedleSettings = AValue then
+//    Exit;
+//  FNeedleSettings := AValue;
+//
+//  DoChange(self);
+//end;
+//
+procedure TDTCustomThemedGauge.SetPointerCapSettings(AValue: TDTPointerCapSettings);
+begin
+  if FPointerCapSettings = AValue then
+    Exit;
+  FPointerCapSettings := AValue;
+
+  DoChange(self);
+end;
+
+procedure TDTCustomThemedGauge.SetPointerSettings(AValue: TDTPointerSettings);
+begin
+  if FPointerSettings = AValue then
+    Exit;
+  FPointerSettings := AValue;
+
+  DoChange(self);
+end;
+
+
+procedure TDTCustomThemedGauge.SetPosition(AValue: integer);
+begin
+  if FPosition = AValue then
+    Exit;
+  FPosition := AValue;
+
+  DoChange(self);
+end;
+
+constructor TDTCustomThemedGauge.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+
+  FPointerSettings := TDTPointerSettings.Create;
+  FPointerSettings.OnChange := @DoChange;
+  FPointerSettings.Color := BGRAToColor(BGRA(255, 81, 81));
+
+  FPointerCapSettings := TDTPointerCapSettings.Create;
+  FPointerCapSettings.OnChange := @DoChange;
+
+  FScaleBitmap := TBGRABitmap.Create;
+  FPointerBitmap := TBGRABitmap.Create;
+
+end;
+
+destructor TDTCustomThemedGauge.Destroy;
+begin
+  FPointerCapSettings.OnChange:=nil;
+  FPointerCapSettings.Free;
+  FPointerSettings.OnChange:=nil;
+  FPointerSettings.Free;
+
+  FScaleBitmap.Free;
+  FPointerBitmap.Free;
+  inherited Destroy;
+end;
+
+procedure TDTCustomThemedGauge.Paint;
+begin
+  inherited Paint;
+  DrawScale;
+  DrawPointer;
+
+  FGaugeBitmap.BlendImage(0, 0, FScaleBitmap, boLinearBlend);
+  FGaugeBitmap.BlendImage(0, 0, FPointerBitmap, boLinearBlend);
+
+  FGaugeBitmap.Draw(Canvas, 0, 0, False);
+
+end;
+
+procedure TDTCustomThemedGauge.DrawScale;
+var
+  Origin: TDTOrigin;
+  r, i, n, x, y, xt, yt: integer;
+  j: single;
+begin
+
+  Origin := Initializebitmap(FScaleBitmap, Width, Height);
+
+  r := round(Origin.Radius * 0.85);
+
+  //j := (180 - ScaleSettings.Angle) / 2;
+  j := (180 - 270) / 2;
+
+  // Draw SubTicks
+  if ScaleSettings.EnableSubTicks then
+  begin
+
+    n := ScaleSettings.MainTickCount * ScaleSettings.SubTickCount;
+
+    for i := 0 to n do
+    begin
+      // Calculate draw from point
+      X := Origin.CenterPoint.x - Round(r * cos((j + i * 270 / n) * Pi / 180));
+      Y := Origin.CenterPoint.y - Round(r * sin((j + i * 270 / n) * Pi / 180));
+
+      // Calculate draw to point
+      Xt := Origin.CenterPoint.x - Round((r - ScaleSettings.LengthSubTick) * cos((j + i * 270 / n) * Pi / 180));
+      Yt := Origin.CenterPoint.y - Round((r - ScaleSettings.LengthSubTick) * sin((j + i * 270 / n) * Pi / 180));
+
+      FScaleBitmap.DrawLineAntialias(x, y, xt, yt, ColorToBGRA(ScaleSettings.TickColor), ScaleSettings.ThicknessSubTick);
+
+    end;
+  end;
+
+  if ScaleSettings.EnableMainTicks then
+  begin
+
+    FScaleBitmap.FontName := ScaleSettings.TextFont;
+    FScaleBitmap.FontHeight := ScaleSettings.TextSize;
+    FScaleBitmap.FontQuality := fqFineAntialiasing;
+
+    n := ScaleSettings.MainTickCount;
+
+    for i := 0 to n do
+    begin
+      // Draw main ticks
+      // Calculate draw from point
+      X := Origin.CenterPoint.x - Round(r * cos((j + i * 270 / n) * Pi / 180));
+      Y := Origin.CenterPoint.y - Round(r * sin((j + i * 270 / n) * Pi / 180));
+
+      // Calculate draw to point
+      Xt := Origin.CenterPoint.x - Round((r - ScaleSettings.LengthMainTick) * cos((j + i * 270 / n) * Pi / 180));
+      Yt := Origin.CenterPoint.y - Round((r - ScaleSettings.LengthMainTick) * sin((j + i * 270 / n) * Pi / 180));
+
+      FScaleBitmap.DrawLineAntialias(x, y, xt, yt, ColorToBGRA(ScaleSettings.TickColor), ScaleSettings.ThicknessMainTick);
+
+      if ScaleSettings.EnableScaleText then
+      begin
+        // Draw text for main ticks
+        Xt := Origin.CenterPoint.x - Round(ScaleSettings.TextRadius * cos((j + i * 270 / n) * Pi / 180));
+        Yt := Origin.CenterPoint.y - Round(ScaleSettings.TextRadius * sin((j + i * 270 / n) * Pi / 180));
+
+        FScaleBitmap.TextOut(Xt, Yt - (FScaleBitmap.FontHeight / 1.7), IntToStr(i * ScaleSettings.Maximum div ScaleSettings.MainTickCount), ColorToBGRA(ScaleSettings.TextColor), taCenter);
+      end;
+    end;
+  end;
+end;
+
+procedure TDTCustomThemedGauge.DrawPointer;
+var
+  Origin: TDTOrigin;
+  r, i, n, x, y, xt, yt: integer;
+  j: single;
+begin
+
+  Origin := Initializebitmap(FPointerBitmap, Width, Height);
+
+  r := round(Origin.Radius * 0.85);
+
+  j := (180 - 270) / 2;
+
+  X := origin.CenterPoint.x - Round(PointerSettings.Length * cos((j + Position * 270 / ScaleSettings.Maximum) * Pi / 180));
+  Y := origin.CenterPoint.y - Round(PointerSettings.Length * sin((j + Position * 270 / ScaleSettings.Maximum) * Pi / 180));
+
+  FPointerBitmap.DrawLineAntialias(origin.CenterPoint.y, origin.CenterPoint.y, x, y, ColorToBGRA(PointerSettings.Color), PointerSettings.Thickness);
+
+  // Draw cap over needle
+  FPointerBitmap.EllipseAntialias(origin.CenterPoint.x, origin.CenterPoint.y, PointerCapSettings.Radius, PointerCapSettings.Radius, ColorToBGRA(PointerCapSettings.EdgeColor), 2, ColorToBGRA(PointerCapSettings.FillColor));
+end;
+
+end.

+ 56 - 0
icons/dtanalogclock_icon.lrs

@@ -0,0 +1,56 @@
+LazarusResources.Add('DTAnalogClock','PNG',[
+  #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#6#0#0#0#224'w='#248#0
+  +#0#0#4'sBIT'#8#8#8#8'|'#8'd'#136#0#0#0#9'pHYs'#0#0#10#17#0#0#10#17#1#216#209
+  +'>'#18#0#0#0#25'tEXtSoftware'#0'www.inkscape.org'#155#238'<'#26#0#0#4#172'ID'
+  +'ATH'#137#141'V'#207'oTU'#20#254#206'}'#247'u:'#157'N'#135#161#149'ii'#153
+  +#128'D'#139#245#7#136#4'J'#162#11'm'#148#152#184'0'#160#129#196#184'1'#145
+  +#153#13'l,'#196#127'A'#203'R'#19#158'.'#13#218'.'#140#1#131#9#139'&'#254#8'Z'
+  +#16'm$'#242'#'#184#16'+'#237#208#180'P'#134#153'a'#218'y'#247#158#227#226#189
+  +'y3'#3'%'#248#146#147#147'wg'#238#249#238#249#238'w'#206'y$"x'#216#147#203
+  +#229#250#28#199#217'E'#237#169#17'@'#13#139'r{ '#0#177#191#200#194'ST+NZk'
+  +#207'y'#158'WxX'#12'Z'#13' '#151#203#185':'#145#30's'#226#169#3#186#255#249
+  +'N'#149#202'&'#208#209#135'm'#253'q'#176#21'L'#253'U'#198#198'x'#17#255#254
+  +'}'#173#226#207'O'#151#201#148#198'yy'#233#136#231'y'#254'#'#1#242#249#252'V'
+  +#157#236#158'H<'#253'j6'#182'i8'#206'V`}'#129'5'#140#148'K'#176'Fp'#183#194
+  +#248'h_'#23#190#185'p'#15#167#127#171#130#22'~'#173#182'-~?'#131#218#157#253
+  +#199#143#31#255#163'9'#158'j~9'#244#193#135#163#177#204#230'3='#175#31#30#236
+  +#220#178';'#238'h'#130'r'#0#229#0#164#8'K'#203#130#219'U'#198'`'#175#134#163
+  +#128'K'#179#6'D'#128'I'#239#136#151#251#223#31#228#248#198'3'#7#15#29#29']'
+  +#21' '#159#207'oU'#137#238#209#238'='#135'3n2'#13#237'R'#20#152#136'@'#4#128
+  +#0'"'#194#208'z'#141'b'#149'1'#187'd'#1'"'#16#0'q'#187'P'#236'}/#'#206#218
+  +#209'|>'#191#181#5' '#151#203#185#186'3='#145#220#253'nF'#4#16#6#152#1'Hhu>C'
+  +'?'#212#167'qy'#206'<'#240#3#1'('#166#247'fD'#175#153#200#229'rn'#4#160';'
+  +#210'c'#177'''^'#203'"'#150#2'['#129'5!'#239'V ,'#16#17'@'#0#17#160'7'#169
+  +#144#238'P'#248's'#182#233'>'#165#225#216#233'B9'#241'R'#150'tj'#12#0#156'B'
+  +#161#208#231'$3'#159#180'?'#187'oMc'#131#128'Y'#192#12#176'm2'#22#188'0'#160
+  +#241#228':'#141#175#166#170'X'#169#9#196#6#255#171'g-V'#176'B}n'#251#202#229
+  +'M'#167'O'#158'8'#161#29#199#217#165#214'm'#235#180#166'q'#12'V'#0'Qpba'#128
+  +#173#132#6'<'#149#209#184#190'hQYf'#136#8'$'#164'1'#240#18'1Zq'#135':'#187
+  +#229#230'N%m'#169#17'$'#179#9#27'Rc|'#134#245#5#166#22#210#228'3'#172#9#0'\'
+  +#2'6?'#166'qi'#206#7#135#224#129#213#169'Dd+'#206'@'#162#134#206#17#173'H'#13
+  +'s'#188#23#240#5#194#128'R'#0'+'#137'nN$X'#183#229'['#240#175'|'#139'c'#215
+  +#20#252#236'+'#144#229#4'`%'#216'g'#5#224#24#132#157#8#172'F'#25#136#168#221
+  +#154'I'#247#236#204'v'#224#250#146#197#237'{'#12'Q'#4'('#128#194'd'#235'4'
+  +#149#166'O'#226#187'/'#23#0#0'o'#189#253#5#158#217#242'x'#192#141#11#136#6
+  +#254'Y'#176#152'q'#223#132'0'#144'Ik'#12#246#199'q'#245''''#221#163#129#128
+  +#227#128#14#137#248#143'4)hp'#221#242'H'#171'{'#128#178'`]'#131#205#226#207
+  +'W'#203#27#149'vA'#14'A'#145#4#197'CM'#27'E'#16#27'|'#3#7#246'|'#14#8#163#180
+  +#233#29#252#238#7#146'f'#19#222#157#27#11#222'Y0'#183'hp'#163'P'#197#6'2'#139
+  +#26'l'#166#164'T'#216'a'#147#27'@'#12'0'#1#20#130#212#17'D'#0'Qi<G'#3#16#1'~'
+  +'t'#251#131#172'E'#192#16'X'#8','#7'B'#144#208#187#246'&H'#204'/'#138'Li'#146
+  +'J3'#21#227#11'LH'#147#169#171#199#231'h-PR'#160'uk$R'#150'5'#247#213#138#13
+  +'hj'#231#217'J'#155#186'7'#169#172#181#231#156#210#197'r]'#146#17'H'#173'!'
+  +#213#0#156#195'Z'#224#8#160#1'"M'#181#18'XR.'#151'}'#223'?'#175'<'#207'+(sw'
+  +#220'Y'#186'P'#181#181' '#144#137#130'6g'#19'R`'#17'e'#180#26#136#181#130'.;'
+  +']'#213'\'#26#247'<'#175#160#0'@j'#197'#'#29'K?'#204#240'r'#177'Q\MV'#207#138
+  +'-P/'#200#251#173'~'#225#202#222#197'Z9;C\<'#18'5;'#207#243'|'#152';'#251#147
+  +#183#190#158'7uzZ2'#8'<[n'#149#180'i'#152'5'#193#233#215#203#169'y'#135#139
+  +#251#235#211#173'e'#162#29'<tt'#148')=z;'#185'7'#195'NWs'#239'k'#169#7#9#27
+  +'a'#189#209#177#13'N'#190#30#167#230'],'#29#251#236#211#143#143'E'#157'|'#181
+  +#145')'#206#154#137'b'#251#139#217'r'#219#246'x'#179'T{'#211#26#2'`n'#193#15
+  +#187'gPP]v'#186#218#141#179'3'#14#23#31#24#153#15#29#250#162'Sc'#150#146#7'*'
+  +'z'#168's'#153#6#18'+'#148#193#203#219'S'#16#8'&'#207#23#209#198#243'h'#231
+  +#27#149'.'#186'R'#214'\'#26'''.'#254#191#161#127#31'P'#159#227'8'#187#12'%G'
+  +#4#206'0'#139#238#1#24#138#204'"'#177'Li*='#242#179#229'?'#170'j'#174't'#211
+  +'R'#11#226#0#0#0#0'IEND'#174'B`'#130
+]);

+ 147 - 0
test/test_analog_controls/dtanalogdemo.lpi

@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="dtanalogdemo"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="2">
+      <Item1 Name="Debug" Default="True"/>
+      <Item2 Name="Release">
+        <CompilerOptions>
+          <Version Value="11"/>
+          <PathDelim Value="\"/>
+          <Target>
+            <Filename Value="dtanalogdemo"/>
+          </Target>
+          <SearchPaths>
+            <IncludeFiles Value="$(ProjOutDir)"/>
+            <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+          </SearchPaths>
+          <CodeGeneration>
+            <SmartLinkUnit Value="True"/>
+            <Optimizations>
+              <OptimizationLevel Value="3"/>
+            </Optimizations>
+          </CodeGeneration>
+          <Linking>
+            <Debugging>
+              <GenerateDebugInfo Value="False"/>
+            </Debugging>
+            <LinkSmart Value="True"/>
+            <Options>
+              <Win32>
+                <GraphicApplication Value="True"/>
+              </Win32>
+            </Options>
+          </Linking>
+          <Other>
+            <CompilerMessages>
+              <MsgFileName Value=""/>
+            </CompilerMessages>
+            <CompilerPath Value="$(CompPath)"/>
+          </Other>
+        </CompilerOptions>
+      </Item2>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="bgracontrols"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="LCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="dtanalogdemo.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="dtanalogdemo"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+        <UnitName Value="umain"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="dtanalogdemo"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <IncludeAssertionCode Value="True"/>
+      </SyntaxOptions>
+    </Parsing>
+    <CodeGeneration>
+      <Checks>
+        <IOChecks Value="True"/>
+        <RangeChecks Value="True"/>
+        <OverflowChecks Value="True"/>
+        <StackChecks Value="True"/>
+      </Checks>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <DebugInfoType Value="dsDwarf2Set"/>
+        <UseHeaptrc Value="True"/>
+        <UseExternalDbgSyms Value="True"/>
+      </Debugging>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+    <Other>
+      <CompilerMessages>
+        <MsgFileName Value=""/>
+      </CompilerMessages>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 21 - 0
test/test_analog_controls/dtanalogdemo.lpr

@@ -0,0 +1,21 @@
+program dtanalogdemo;
+
+{$mode objfpc}{$H+}
+
+uses
+  {$IFDEF UNIX}{$IFDEF UseCThreads}
+  cthreads,
+  {$ENDIF}{$ENDIF}
+  Interfaces, // this includes the LCL widgetset
+  Forms, umain
+  { you can add units after this };
+
+{$R *.res}
+
+begin
+  RequireDerivedFormResource := True;
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.
+

+ 103 - 0
test/test_analog_controls/umain.lfm

@@ -0,0 +1,103 @@
+object Form1: TForm1
+  Left = 424
+  Height = 351
+  Top = 168
+  Width = 810
+  Caption = 'Analog Controls Demo'
+  ClientHeight = 351
+  ClientWidth = 810
+  Color = clWhite
+  OnClose = FormClose
+  OnCreate = FormCreate
+  OnDestroy = FormDestroy
+  LCLVersion = '1.2.0.3'
+  object DTThemedGauge1: TDTThemedGauge
+    Left = 16
+    Height = 240
+    Top = 16
+    Width = 240
+    FaceSettings.FillStyle = fsGradient
+    FaceSettings.ColorFrame = 2302755
+    FaceSettings.ColorStart = 4144959
+    FaceSettings.ColorEnd = 6118749
+    ScaleSettings.TickColor = 8242399
+    ScaleSettings.TextColor = 13881484
+    ScaleSettings.TextSize = 15
+    ScaleSettings.TextFont = 'Calibri'
+    ScaleSettings.EnableMainTicks = True
+    ScaleSettings.EnableSubTicks = True
+    ScaleSettings.EnableScaleText = True
+    ScaleSettings.Maximum = 100
+    ScaleSettings.MainTickCount = 10
+    ScaleSettings.SubTickCount = 5
+    ScaleSettings.LengthMainTick = 15
+    ScaleSettings.LengthSubTick = 8
+    ScaleSettings.ThicknessMainTick = 3
+    ScaleSettings.ThicknessSubTick = 1
+    ScaleSettings.TextRadius = 72
+    ScaleSettings.EnableRangeIndicator = False
+    PointerSettings.Color = 5329407
+    PointerSettings.Length = 100
+    PointerSettings.Thickness = 3
+    PointerCapSettings.EdgeColor = 13425884
+    PointerCapSettings.FillColor = 4144959
+    PointerCapSettings.Radius = 10
+    PointerCapSettings.EdgeThickness = 1
+    Position = 0
+  end
+  object DTThemedClock1: TDTThemedClock
+    Left = 304
+    Height = 240
+    Top = 16
+    Width = 240
+    SecondsPointerSettings.Color = 5329407
+    SecondsPointerSettings.Length = 80
+    SecondsPointerSettings.Thickness = 3
+    MinutesPointerSettings.Color = 11388871
+    MinutesPointerSettings.Length = 80
+    MinutesPointerSettings.Thickness = 3
+    HoursPointerSettings.Color = 11388871
+    HoursPointerSettings.Length = 60
+    HoursPointerSettings.Thickness = 5
+    PointerCapSettings.EdgeColor = 13425884
+    PointerCapSettings.FillColor = 4144959
+    PointerCapSettings.Radius = 10
+    PointerCapSettings.EdgeThickness = 1
+    ScaleSettings.TickColor = 8242399
+    ScaleSettings.TextColor = 13881484
+    ScaleSettings.TextSize = 15
+    ScaleSettings.TextFont = 'Calibri'
+    ScaleSettings.EnableMainTicks = True
+    ScaleSettings.EnableSubTicks = True
+    ScaleSettings.EnableScaleText = True
+    ScaleSettings.Maximum = 100
+    ScaleSettings.MainTickCount = 10
+    ScaleSettings.SubTickCount = 5
+    ScaleSettings.LengthMainTick = 15
+    ScaleSettings.LengthSubTick = 8
+    ScaleSettings.ThicknessMainTick = 3
+    ScaleSettings.ThicknessSubTick = 1
+    ScaleSettings.TextRadius = 72
+    ScaleSettings.EnableRangeIndicator = False
+    Position = 0
+    Enabled = True
+  end
+  object TrackBar1: TTrackBar
+    Left = 16
+    Height = 25
+    Top = 264
+    Width = 236
+    Frequency = 5
+    Max = 100
+    OnChange = TrackBar1Change
+    Position = 0
+    TabOrder = 0
+  end
+  object DTAnalogClock1: TDTAnalogClock
+    Left = 557
+    Height = 240
+    Top = 16
+    Width = 237
+    Enabled = True
+  end
+end

+ 64 - 0
test/test_analog_controls/umain.pas

@@ -0,0 +1,64 @@
+unit umain;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
+  ComCtrls, ExtCtrls,
+
+  // DT Controls
+  dtthemedgauge, dtthemedclock, DTAnalogClock;
+
+type
+
+  { TForm1 }
+
+  TForm1 = class(TForm)
+    DTAnalogClock1: TDTAnalogClock;
+    DTClock1: TDTThemedClock;
+    DTThemedClock1: TDTThemedClock;
+    DTThemedGauge1: TDTThemedGauge;
+    TrackBar1: TTrackBar;
+    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
+    procedure FormCreate(Sender: TObject);
+    procedure FormDestroy(Sender: TObject);
+    procedure TrackBar1Change(Sender: TObject);
+  private
+    { private declarations }
+  public
+    { public declarations }
+  end;
+
+var
+  Form1: TForm1;
+
+implementation
+
+{$R *.lfm}
+
+{ TForm1 }
+
+procedure TForm1.TrackBar1Change(Sender: TObject);
+begin
+  DTThemedGauge1.Position := TrackBar1.Position;
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+begin
+
+end;
+
+procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
+begin
+
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+
+end;
+
+end.
+