Browse Source

Added Material Design package units. Added bgramacos package units. Added BCImageButton demo. v 5.0.

lainz 7 years ago
parent
commit
d0c5cc6a64
34 changed files with 4570 additions and 5 deletions
  1. 844 0
      bcmdbutton.pas
  2. 820 0
      bcmdbuttonfocus.pas
  3. 14 2
      bgracontrols.lpk
  4. 4 1
      bgracontrols.pas
  5. BIN
      test/test_bcimagebutton_3dbutton/boton3d.png
  6. 83 0
      test/test_bcimagebutton_3dbutton/test_drawing.lpi
  7. 21 0
      test/test_bcimagebutton_3dbutton/test_drawing.lpr
  8. 45 0
      test/test_bcimagebutton_3dbutton/umain.lfm
  9. 41 0
      test/test_bcimagebutton_3dbutton/umain.pas
  10. 169 0
      test/test_bgramacos/button/bgramacosbutton.lpi
  11. 22 0
      test/test_bgramacos/button/bgramacosbutton.lpr
  12. 81 0
      test/test_bgramacos/button/bgramacosdraw.pas
  13. 19 0
      test/test_bgramacos/button/umain.lfm
  14. 66 0
      test/test_bgramacos/button/umain.pas
  15. BIN
      test/test_materialdesign/drawings/test.ico
  16. 81 0
      test/test_materialdesign/drawings/test.lpi
  17. 22 0
      test/test_materialdesign/drawings/test.lpr
  18. 43 0
      test/test_materialdesign/drawings/umain.lfm
  19. 71 0
      test/test_materialdesign/drawings/umain.pas
  20. 164 0
      test/test_materialdesign/mdbutton/test.lpi
  21. 23 0
      test/test_materialdesign/mdbutton/test.lpr
  22. 780 0
      test/test_materialdesign/mdbutton/umain.lfm
  23. 163 0
      test/test_materialdesign/mdbutton/umain.pas
  24. BIN
      test/test_materialdesign/mdbutton_tab/test.ico
  25. 132 0
      test/test_materialdesign/mdbutton_tab/test.lpi
  26. 22 0
      test/test_materialdesign/mdbutton_tab/test.lpr
  27. 276 0
      test/test_materialdesign/mdbutton_tab/umain.lfm
  28. 105 0
      test/test_materialdesign/mdbutton_tab/umain.pas
  29. BIN
      test/test_materialdesign/mdbuttonfocus/test.ico
  30. 82 0
      test/test_materialdesign/mdbuttonfocus/test.lpi
  31. 22 0
      test/test_materialdesign/mdbuttonfocus/test.lpr
  32. 296 0
      test/test_materialdesign/mdbuttonfocus/umain.lfm
  33. 57 0
      test/test_materialdesign/mdbuttonfocus/umain.pas
  34. 2 2
      update_bgracontrols_force.json

+ 844 - 0
bcmdbutton.pas

@@ -0,0 +1,844 @@
+unit BCMDButton;
+
+{$mode objfpc}{$H+}
+
+// Set this to show number of repaint in each MDBUTTON
+{ $DEFINE MDBUTTON_DEBUG}
+
+// Set this to animate only a MDBUTTON at a time
+{ $DEFINE MDBUTTON_ANIMATEONLYONE}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
+  BGRABitmap, BGRABitmapTypes, ExtCtrls, Math, Types, BGRABlend;
+
+var
+  // Default icons for Check Box
+  BCMDBUTTONBALLOTBOX: string = '☐'; // '✗'
+  BCMDBUTTONBALLOTBOXWITHCHECK: string = '☑'; // '✓'
+
+  // Default icons for Radio Button
+  BCMDBUTTONRADIOBUTTON: string = '🔘';
+  BCMDBUTTONRADIOBUTTONCIRCLE: string = '◯';
+
+  // Characters that can be used on systems that lack of the previous unicode symbols
+  {BCMDBUTTONBALLOTBOX: string = '[  ]';
+  BCMDBUTTONBALLOTBOXWITHCHECK: string = '[X]';
+  BCMDBUTTONRADIOBUTTON: string = '[O]';
+  BCMDBUTTONRADIOBUTTONCIRCLE: string = '[  ]';}
+
+  // Animation speed
+  // Possible values: between 0 and 1
+  // 0 is an infinite animation that display nothing (only redraw itself)
+  // 1 is the faster animation (like no animation, from 0 to 1 in 1 frame)
+  // Recommended values: between 0.01 (slow) and 0.1 (fast), default 0.04
+  // Hint: turn on debug to see how much frames are rendered
+  BCMDBUTTONANIMATIONSPEED: double = 0.04;
+
+  // Global enable/disable animations
+  BCMDBUTTONANIMATION: boolean = True;
+
+const
+  // Timer speed: default 15 (a bit more than 60 fps)
+  // Other values: 16 (60 fps) 20 (50 fps) 25 (40 fps) 33 (30 fps)
+  // Hint: 15 is the smoothest -tested- value on Windows, even if 16 is closer to 60 fps
+  //       * values below 15 are not noticeable
+  //       * higher values are not smooth
+  // Hint: changing this doesn't change the ammount of frames rendered,
+  //       only changes the time between frames
+  // Hint: if you decrease MDBUTTONTIMERSPEED, increase BCMDBUTTONANIMATIONSPEED
+  //       to keep a smooth animation
+  BCMDBUTTONTIMERSPEED: integer = 15;
+
+type
+  TBCMDButtonState = (mdbsNormal, mdbsHover, mdbsActive);
+  TBCMDButtonKind = (mdbkNormal, mdbkToggle, mdbkToggleGroup, mdbkCheckBox,
+    mdbkRadioButton, mdbkTab);
+
+  { TBCMDButtonStyle }
+
+  TBCMDButtonStyle = class(TPersistent)
+  private
+    FColor: TColor;
+    FOnChange: TNotifyEvent;
+    FTextColor: TColor;
+    procedure SetFColor(AValue: TColor);
+    procedure SetFTextColor(AValue: TColor);
+  public
+    property OnChange: TNotifyEvent read FOnChange write FOnChange;
+  public
+    constructor Create;
+  published
+    property Color: TColor read FColor write SetFColor;
+    property TextColor: TColor read FTextColor write SetFTextColor;
+  end;
+
+  { TCustomBCMDButton }
+
+  TCustomBCMDButton = class(TGraphicControl)
+  private
+    FChecked: boolean;
+    FKind: TBCMDButtonKind;
+    {$IFDEF MDBUTTON_DEBUG}
+    FCount: integer;
+    {$ENDIF}
+    FRounding: integer;
+    FTextAutoSize: boolean;
+    FTextProportional: boolean;
+    FTextProportionalRatio: single;
+    FTimer: TTimer;
+    FPercent: double;
+    FCircleSize: double;
+    FCX, FCY: integer;
+    FAlphaPercent: double;
+    FAlignment: TAlignment;
+    FAnimation: boolean;
+    FState: TBCMDButtonState;
+    FStyleActive: TBCMDButtonStyle;
+    FStyleDisabled: TBCMDButtonStyle;
+    FStyleHover: TBCMDButtonStyle;
+    FStyleNormal: TBCMDButtonStyle;
+    FTextLayout: TTextLayout;
+    procedure OnChangeStyle(Sender: TObject);
+    procedure SetFAlignment(AValue: TAlignment);
+    procedure SetFAnimation(AValue: boolean);
+    procedure SetFChecked(AValue: boolean);
+    procedure SetFKind(AValue: TBCMDButtonKind);
+    procedure SetFStyleActive(AValue: TBCMDButtonStyle);
+    procedure SetFStyleDisabled(AValue: TBCMDButtonStyle);
+    procedure SetFStyleHover(AValue: TBCMDButtonStyle);
+    procedure SetFStyleNormal(AValue: TBCMDButtonStyle);
+    procedure SetFTextAutoSize(AValue: boolean);
+    procedure SetFTextLayout(AValue: TTextLayout);
+    procedure SetFTextProportional(AValue: boolean);
+    procedure SetFTextProportionalRatio(AValue: single);
+  protected
+    procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
+    {%H-}WithThemeSpace: boolean); override;
+    procedure Paint; override;
+    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
+      X, Y: integer); override;
+    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override;
+    procedure MouseEnter; override;
+    procedure MouseLeave; override;
+    procedure RealSetText(const Value: TCaption); override;
+    procedure OnTimer(Sender: TObject);
+    procedure OnStartTimer(Sender: TObject);
+    procedure OnStopTimer(Sender: TObject);
+    function easeInOutQuad(t: double): double;
+    function easeOutQuad(t: double): double;
+    procedure UncheckOthers;
+    class function GetControlClassDefaultSize: TSize; override;
+    function GetRealCaption: string;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure SelectAll;
+    procedure UnselectAll;
+    procedure InvertSelection;
+    function GetSelected: TStringList;
+  published
+    property Animation: boolean read FAnimation write SetFAnimation default False;
+    property Alignment: TAlignment read FAlignment write SetFAlignment default taCenter;
+    property TextLayout: TTextLayout
+      read FTextLayout write SetFTextLayout default tlCenter;
+    property StyleNormal: TBCMDButtonStyle read FStyleNormal write SetFStyleNormal;
+    property StyleHover: TBCMDButtonStyle read FStyleHover write SetFStyleHover;
+    property StyleActive: TBCMDButtonStyle read FStyleActive write SetFStyleActive;
+    property StyleDisabled: TBCMDButtonStyle read FStyleDisabled write SetFStyleDisabled;
+    property Checked: boolean read FChecked write SetFChecked default False;
+    property Kind: TBCMDButtonKind read FKind write SetFKind default mdbkNormal;
+    // If text size is used to measure buttons
+    // Disable it if you use the buttons in a grid, for example
+    property TextAutoSize: boolean read FTextAutoSize write SetFTextAutoSize;
+    // Enable it if you want that text size grows with height
+    property TextProportional: boolean read FTextProportional write SetFTextProportional;
+    // Each character font height proportional to height of control
+    // Set it in conjunction with TextProportional, values recommended between 0...1
+    property TextProportionalRatio: single read FTextProportionalRatio
+      write SetFTextProportionalRatio;
+  end;
+
+  TBCMDButton = class(TCustomBCMDButton)
+    property Action;
+    property Align;
+    property Anchors;
+    property AutoSize;
+    property BidiMode;
+    property BorderSpacing;
+    //property Cancel;
+    property Caption;
+    property Color;
+    property Constraints;
+    //property Default;
+    property DragCursor;
+    property DragKind;
+    property DragMode;
+    property Enabled;
+    property Font;
+    property ParentBidiMode;
+    //property ModalResult;
+    property OnChangeBounds;
+    property OnClick;
+    property OnContextPopup;
+    property OnDragDrop;
+    property OnDragOver;
+    property OnEndDrag;
+    //property OnEnter;
+    //property OnExit;
+    //property OnKeyDown;
+    //property OnKeyPress;
+    //property OnKeyUp;
+    property OnMouseDown;
+    property OnMouseEnter;
+    property OnMouseLeave;
+    property OnMouseMove;
+    property OnMouseUp;
+    property OnMouseWheel;
+    property OnMouseWheelDown;
+    property OnMouseWheelUp;
+    property OnResize;
+    property OnStartDrag;
+    //property OnUTF8KeyPress;
+    property ParentFont;
+    property ParentShowHint;
+    property PopupMenu;
+    property ShowHint;
+    //property TabOrder;
+    //property TabStop;
+    property Visible;
+  end;
+
+procedure Register;
+
+implementation
+
+{$IFDEF MDBUTTON_ANIMATEONLYONE}
+var
+  MDAnimating: TCustomMDButton;
+
+{$ENDIF}
+
+procedure Register;
+begin
+  RegisterComponents('BGRA Controls', [TBCMDButton]);
+end;
+
+{ TBCMDButtonStyle }
+
+procedure TBCMDButtonStyle.SetFColor(AValue: TColor);
+begin
+  if FColor = AValue then
+    Exit;
+  FColor := AValue;
+  if Assigned(FOnChange) then
+    OnChange(Self);
+end;
+
+procedure TBCMDButtonStyle.SetFTextColor(AValue: TColor);
+begin
+  if FTextColor = AValue then
+    Exit;
+  FTextColor := AValue;
+  if Assigned(FOnChange) then
+    OnChange(Self);
+end;
+
+constructor TBCMDButtonStyle.Create;
+begin
+  inherited Create;
+  FColor := clWhite;
+  FTextColor := clBlack;
+end;
+
+{ TCustomBCMDButton }
+
+procedure TCustomBCMDButton.SetFStyleActive(AValue: TBCMDButtonStyle);
+begin
+  if FStyleActive = AValue then
+    Exit;
+  FStyleActive := AValue;
+end;
+
+procedure TCustomBCMDButton.SetFAlignment(AValue: TAlignment);
+begin
+  if FAlignment = AValue then
+    Exit;
+  FAlignment := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.SetFAnimation(AValue: boolean);
+begin
+  if FAnimation = AValue then
+    Exit;
+  FAnimation := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.SetFChecked(AValue: boolean);
+begin
+  if FChecked = AValue then
+    Exit;
+  FChecked := AValue;
+  if FChecked and (FKind in [mdbkToggleGroup, mdbkRadioButton, mdbkTab]) then
+    UncheckOthers;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.SetFKind(AValue: TBCMDButtonKind);
+begin
+  if FKind = AValue then
+    Exit;
+  FKind := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.OnChangeStyle(Sender: TObject);
+begin
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.SetFStyleDisabled(AValue: TBCMDButtonStyle);
+begin
+  if FStyleDisabled = AValue then
+    Exit;
+  FStyleDisabled := AValue;
+end;
+
+procedure TCustomBCMDButton.SetFStyleHover(AValue: TBCMDButtonStyle);
+begin
+  if FStyleHover = AValue then
+    Exit;
+  FStyleHover := AValue;
+end;
+
+procedure TCustomBCMDButton.SetFStyleNormal(AValue: TBCMDButtonStyle);
+begin
+  if FStyleNormal = AValue then
+    Exit;
+  FStyleNormal := AValue;
+end;
+
+procedure TCustomBCMDButton.SetFTextAutoSize(AValue: boolean);
+begin
+  if FTextAutoSize = AValue then
+    Exit;
+  FTextAutoSize := AValue;
+end;
+
+procedure TCustomBCMDButton.SetFTextLayout(AValue: TTextLayout);
+begin
+  if FTextLayout = AValue then
+    Exit;
+  FTextLayout := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.SetFTextProportional(AValue: boolean);
+begin
+  if FTextProportional=AValue then Exit;
+  FTextProportional:=AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.SetFTextProportionalRatio(AValue: single);
+begin
+  if FTextProportionalRatio=AValue then Exit;
+  FTextProportionalRatio:=AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.CalculatePreferredSize(
+  var PreferredWidth, PreferredHeight: integer; WithThemeSpace: boolean);
+var
+  bmp: TBGRABitmap;
+  s: TSize;
+begin
+  bmp := TBGRABitmap.Create;
+  bmp.FontName := Font.Name;
+  if FTextProportional then
+    bmp.FontHeight := Round(Height * FTextProportionalRatio)
+  else
+    bmp.FontHeight := 0;
+  bmp.FontAntialias := True;
+  bmp.FontQuality := fqSystemClearType;
+  bmp.FontStyle := Font.Style;
+  s := bmp.TextSize(GetRealCaption);
+  if FTextAutoSize then
+  begin
+    PreferredWidth := s.Width + 26 + BorderSpacing.InnerBorder;
+    PreferredHeight := s.Height + 10 + BorderSpacing.InnerBorder;
+  end
+  else
+  begin
+    PreferredWidth := BorderSpacing.InnerBorder;
+    PreferredHeight := BorderSpacing.InnerBorder;
+  end;
+  bmp.Free;
+end;
+
+procedure TCustomBCMDButton.Paint;
+var
+  bmp: TBGRABitmap;
+  iTemp: integer;
+  alpha: byte;
+  tempState: TBCMDButtonState;
+  tempText: string;
+  tempRounding: integer;
+  tempColor, hoverColor: TBGRAPixel;
+begin
+  bmp := TBGRABitmap.Create(Width, Height);
+  bmp.FontName := Font.Name;
+  if FTextProportional then
+    bmp.FontHeight := Round(Height * FTextProportionalRatio)
+  else
+    bmp.FontHeight := 0;
+  bmp.FontAntialias := True;
+  bmp.FontQuality := fqSystemClearType;
+  bmp.FontStyle := Font.Style;
+  tempState := FState;
+
+  if Kind = mdbkTab then
+    tempRounding := 0
+  else
+    tempRounding := FRounding;
+
+  if FChecked then
+    tempState := mdbsActive
+  else
+    tempState := FState;
+
+  tempText := GetRealCaption;
+
+  // Enabled
+  if Enabled then
+  begin
+    if not FTimer.Enabled then
+    begin
+      case tempState of
+        mdbsNormal:
+        begin
+          bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+            FStyleNormal.Color,
+            FStyleNormal.Color);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleNormal.TextColor);
+        end;
+        mdbsHover:
+        begin
+          bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+            FStyleHover.Color, FStyleHover.Color);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleHover.TextColor);
+        end;
+        mdbsActive:
+        begin
+          if not FAnimation then
+          begin
+            if FKind in [mdbkNormal] then
+              bmp.RoundRect(0, 0, Width, Height, tempRounding,
+                tempRounding, FStyleActive.Color,
+                FStyleActive.Color)
+            else
+              bmp.RoundRect(0, 0, Width, Height, tempRounding,
+                tempRounding, FStyleHover.Color,
+                FStyleHover.Color);
+          end
+          else
+            bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+              FStyleHover.Color,
+              FStyleHover.Color);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleActive.TextColor);
+        end;
+      end;
+    end
+    else
+    begin
+      iTemp := round(FCircleSize * easeOutQuad(FPercent));
+      alpha := round(easeInOutQuad(FAlphaPercent) * 255);
+      case tempState of
+        mdbsNormal:
+        begin
+          bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+            FStyleNormal.Color,
+            FStyleNormal.Color);
+          if FPercent < 1 then
+            tempColor := FStyleHover.Color
+          else
+          begin
+            tempColor := FStyleNormal.Color;
+            hoverColor := ColorToBGRA(FStyleHover.Color, alpha);
+            PutPixels(@tempColor, @hoverColor, 1, dmDrawWithTransparency, 255);
+          end;
+          bmp.FillEllipseAntialias(FCX, FCY, iTemp,
+            iTemp, tempColor);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleNormal.TextColor);
+        end;
+        mdbsHover, mdbsActive:
+        begin
+          bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+            FStyleHover.Color, FStyleHover.Color);
+          if FPercent < 1 then
+            tempColor := FStyleActive.Color
+          else
+          begin
+            tempColor := FStyleHover.Color;
+            hoverColor := ColorToBGRA(FStyleActive.Color, alpha);
+            PutPixels(@tempColor, @hoverColor, 1, dmDrawWithTransparency, 255);
+          end;
+          bmp.FillEllipseAntialias(FCX, FCY, iTemp,
+            iTemp, tempColor);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleHover.TextColor);
+        end;
+      end;
+    end;
+  end
+  // Disabled
+  else
+  begin
+    if FChecked then
+    begin
+      bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+        FStyleHover.Color, FStyleHover.Color);
+    end
+    else
+      bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+        FStyleDisabled.Color, FStyleDisabled.Color);
+    bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+      Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+      tempText, Alignment,
+      TextLayout, FStyleDisabled.TextColor);
+  end;
+
+  // Tab
+  if Kind = mdbkTab then
+  begin
+    if FTimer.Enabled then
+    begin
+      iTemp := round((bmp.Width div 2) * easeInOutQuad(FPercent));
+      bmp.Rectangle((bmp.Width div 2) - iTemp, bmp.Height - 2,
+        (bmp.Width div 2) + iTemp, bmp.Height, $00BB513F, dmSet);
+    end
+    else
+    begin
+      if FChecked then
+        bmp.Rectangle(0, bmp.Height - 2, bmp.Width, bmp.Height, $00BB513F, dmSet);
+    end;
+  end;
+
+  {$IFDEF MDBUTTON_DEBUG}
+  bmp.FontHeight := 10;
+  bmp.TextOut(0, 0, FCount.ToString, BGRA(255, 0, 0, 255));
+  FCount += 1;
+  {$ENDIF}
+  bmp.Draw(Canvas, 0, 0, False);
+  bmp.Free;
+  inherited Paint;
+end;
+
+procedure TCustomBCMDButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
+  X, Y: integer);
+begin
+  inherited MouseDown(Button, Shift, X, Y);
+  FState := mdbsActive;
+  if FAnimation and BCMDBUTTONANIMATION then
+  begin
+    FCircleSize := max(round(Width / 1.5) + abs((Width div 2) - X),
+      round(Height / 1.5) + abs((Height div 2) - Y));
+    FCX := X;
+    FCY := Y;
+    FTimer.Enabled := False;
+    FTimer.Enabled := True;
+    {$IFDEF MDBUTTON_ANIMATEONLYONE}
+    MDAnimating := Self;
+    {$ENDIF}
+  end;
+  if FKind in [mdbkToggle, mdbkToggleGroup, mdbkCheckBox, mdbkRadioButton, mdbkTab] then
+  begin
+    FChecked := not FChecked;
+    if FKind in [mdbkToggleGroup, mdbkRadioButton, mdbkTab] then
+    begin
+      FChecked := True;
+      UncheckOthers;
+    end;
+  end;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
+  X, Y: integer);
+begin
+  inherited MouseUp(Button, Shift, X, Y);
+  if (x > 0) and (x < Width) and (y > 0) and (y < Height) and (FState = mdbsActive) then
+    FState := mdbsHover
+  else
+    FState := mdbsNormal;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.MouseEnter;
+begin
+  inherited MouseEnter;
+  FState := mdbsHover;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.MouseLeave;
+begin
+  inherited MouseLeave;
+  FState := mdbsNormal;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.RealSetText(const Value: TCaption);
+begin
+  inherited RealSetText(Value);
+  InvalidatePreferredSize;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButton.OnTimer(Sender: TObject);
+begin
+  {$IFDEF MDBUTTON_ANIMATEONLYONE}
+  if MDAnimating = Self then
+  begin
+  {$ENDIF}
+    FPercent += BCMDBUTTONANIMATIONSPEED;
+    if FPercent < 0 then
+      FPercent := 0
+    else if FPercent > 1 then
+      FPercent := 1;
+
+    if FPercent = 1 then
+    begin
+      FAlphaPercent -= BCMDBUTTONANIMATIONSPEED;
+      if FAlphaPercent < 0 then
+        FAlphaPercent := 0
+      else if FAlphaPercent > 1 then
+        FAlphaPercent := 1;
+    end;
+  {$IFDEF MDBUTTON_ANIMATEONLYONE}
+  end
+  else
+    FTimer.Enabled := False;
+  {$ENDIF}
+
+  Invalidate;
+  if (FPercent >= 1) and (FAlphaPercent <= 0) then
+    FTimer.Enabled := False;
+end;
+
+procedure TCustomBCMDButton.OnStartTimer(Sender: TObject);
+begin
+  FPercent := 0;
+  FAlphaPercent := 1;
+end;
+
+procedure TCustomBCMDButton.OnStopTimer(Sender: TObject);
+begin
+
+end;
+
+function TCustomBCMDButton.easeInOutQuad(t: double): double;
+begin
+  if t < 0.5 then
+    Result := 2 * t * t
+  else
+    Result := -1 + (4 - 2 * t) * t;
+end;
+
+function TCustomBCMDButton.easeOutQuad(t: double): double;
+begin
+  Result := t * (2 - t);
+end;
+
+procedure TCustomBCMDButton.UncheckOthers;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  if Parent is TWinControl then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] <> Self) and (control.Controls[i] is TCustomBCMDButton) then
+        if (TCustomBCMDButton(control.Controls[i]).Kind in
+          [mdbkToggleGroup, mdbkRadioButton, mdbkTab]) then
+          TCustomBCMDButton(control.Controls[i]).Checked := False;
+  end;
+end;
+
+class function TCustomBCMDButton.GetControlClassDefaultSize: TSize;
+begin
+  Result.CX := 75;
+  Result.CY := 25;
+end;
+
+function TCustomBCMDButton.GetRealCaption: string;
+var
+  tempText: string = '';
+begin
+  tempText := Caption;
+
+  case FKind of
+    mdbkCheckBox:
+    begin
+      if Length(Caption) > 0 then
+        tempText := ' ' + Caption;
+      if FChecked then
+        tempText := BCMDBUTTONBALLOTBOXWITHCHECK + tempText
+      else
+        tempText := BCMDBUTTONBALLOTBOX + tempText;
+    end;
+    mdbkRadioButton:
+    begin
+      if Length(Caption) > 0 then
+        tempText := ' ' + Caption;
+      if FChecked then
+        tempText := BCMDBUTTONRADIOBUTTON + tempText
+      else
+        tempText := BCMDBUTTONRADIOBUTTONCIRCLE + tempText;
+    end;
+  end;
+  result := tempText;
+end;
+
+constructor TCustomBCMDButton.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  {$IFDEF DEBUG}
+  FCount := 0;
+  {$ENDIF}
+  // State
+  FState := mdbsNormal;
+  FChecked := False;
+  FKind := mdbkNormal;
+  // Text
+  FTextAutoSize := True;
+  FAlignment := taCenter;
+  FTextLayout := tlCenter;
+  FTextProportional := False;
+  FTextProportionalRatio := 0.5;
+  // Style
+  FRounding := 6;
+  FStyleNormal := TBCMDButtonStyle.Create;
+  FStyleNormal.OnChange := @OnChangeStyle;
+  FStyleHover := TBCMDButtonStyle.Create;
+  FStyleHover.OnChange := @OnChangeStyle;
+  FStyleActive := TBCMDButtonStyle.Create;
+  FStyleActive.OnChange := @OnChangeStyle;
+  FStyleDisabled := TBCMDButtonStyle.Create;
+  FStyleDisabled.OnChange := @OnChangeStyle;
+  // Default Style
+  FStyleHover.Color := RGBToColor(220, 220, 220);
+  FStyleActive.Color := RGBToColor(198, 198, 198);
+  FStyleDisabled.TextColor := RGBToColor(163, 163, 163);
+  // Animation
+  FAnimation := False;
+  FTimer := TTimer.Create(Self);
+  FTimer.Enabled := False;
+  FTimer.Interval := BCMDBUTTONTIMERSPEED;
+  FTimer.OnTimer := @OnTimer;
+  FTimer.OnStartTimer := @OnStartTimer;
+  FTimer.OnStopTimer := @OnStopTimer;
+  // Setup default sizes
+  with GetControlClassDefaultSize do
+    SetInitialBounds(0, 0, CX, CY);
+end;
+
+destructor TCustomBCMDButton.Destroy;
+begin
+  FTimer.OnTimer := nil;
+  FTimer.OnStartTimer := nil;
+  FTimer.OnStopTimer := nil;
+  FTimer.Enabled := False;
+  FStyleNormal.Free;
+  FStyleHover.Free;
+  FStyleActive.Free;
+  FStyleDisabled.Free;
+  inherited Destroy;
+end;
+
+procedure TCustomBCMDButton.SelectAll;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  if (Parent <> nil) and (Parent is TWinControl) then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] is TCustomBCMDButton) then
+        if (TCustomBCMDButton(control.Controls[i]).Kind in
+          [mdbkToggle, mdbkCheckBox]) then
+          TCustomBCMDButton(control.Controls[i]).Checked := True;
+  end;
+end;
+
+procedure TCustomBCMDButton.UnselectAll;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  if (Parent <> nil) and (Parent is TWinControl) then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] is TCustomBCMDButton) then
+        if (TCustomBCMDButton(control.Controls[i]).Kind in
+          [mdbkToggle, mdbkCheckBox]) then
+          TCustomBCMDButton(control.Controls[i]).Checked := False;
+  end;
+end;
+
+procedure TCustomBCMDButton.InvertSelection;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  if (Parent <> nil) and (Parent is TWinControl) then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] is TCustomBCMDButton) then
+        if (TCustomBCMDButton(control.Controls[i]).Kind in
+          [mdbkToggle, mdbkCheckBox]) then
+          TCustomBCMDButton(control.Controls[i]).Checked :=
+            not TCustomBCMDButton(control.Controls[i]).Checked;
+  end;
+end;
+
+function TCustomBCMDButton.GetSelected: TStringList;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  Result := TStringList.Create;
+  if (Parent <> nil) and (Parent is TWinControl) then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] is TCustomBCMDButton) then
+        if TCustomBCMDButton(control.Controls[i]).Checked then
+          Result.AddObject(TCustomBCMDButton(control.Controls[i]).Caption,
+            TCustomBCMDButton(control.Controls[i]));
+  end;
+end;
+
+end.

+ 820 - 0
bcmdbuttonfocus.pas

@@ -0,0 +1,820 @@
+unit BCMDButtonFocus;
+
+{$mode objfpc}{$H+}
+
+// Set this to show number of repaint in each MDBUTTON
+{ $DEFINE MDBUTTON_DEBUG}
+
+// Set this to animate only a MDBUTTON at a time
+{ $DEFINE MDBUTTON_ANIMATEONLYONE}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
+  BGRABitmap, BGRABitmapTypes, ExtCtrls, Math, Types, BGRABlend, BCMDButton,
+  LMessages, LCLType;
+
+type
+
+  { TCustomBCMDButtonFocus }
+
+  TCustomBCMDButtonFocus = class(TCustomControl)
+  private
+    FChecked: boolean;
+    FKind: TBCMDButtonKind;
+    {$IFDEF MDBUTTON_DEBUG}
+    FCount: integer;
+    {$ENDIF}
+    FRounding: integer;
+    FTextAutoSize: boolean;
+    FTextProportional: boolean;
+    FTextProportionalRatio: single;
+    FTimer: TTimer;
+    FPercent: double;
+    FCircleSize: double;
+    FCX, FCY: integer;
+    FAlphaPercent: double;
+    FAlignment: TAlignment;
+    FAnimation: boolean;
+    FState: TBCMDButtonState;
+    FStyleActive: TBCMDButtonStyle;
+    FStyleDisabled: TBCMDButtonStyle;
+    FStyleHover: TBCMDButtonStyle;
+    FStyleNormal: TBCMDButtonStyle;
+    FTextLayout: TTextLayout;
+    procedure OnChangeStyle(Sender: TObject);
+    procedure SetFAlignment(AValue: TAlignment);
+    procedure SetFAnimation(AValue: boolean);
+    procedure SetFChecked(AValue: boolean);
+    procedure SetFKind(AValue: TBCMDButtonKind);
+    procedure SetFStyleActive(AValue: TBCMDButtonStyle);
+    procedure SetFStyleDisabled(AValue: TBCMDButtonStyle);
+    procedure SetFStyleHover(AValue: TBCMDButtonStyle);
+    procedure SetFStyleNormal(AValue: TBCMDButtonStyle);
+    procedure SetFTextAutoSize(AValue: boolean);
+    procedure SetFTextLayout(AValue: TTextLayout);
+    procedure SetFTextProportional(AValue: boolean);
+    procedure SetFTextProportionalRatio(AValue: single);
+  protected
+    // START / MDBUTTONFOCUS ONLY
+    procedure WMSetFocus(var Message: TLMSetFocus); message LM_SETFOCUS;
+    procedure WMKillFocus(var Message: TLMKillFocus); message LM_KILLFOCUS;
+    procedure UpdateFocus(AFocused: boolean);
+    procedure KeyDown(var Key: word; Shift: TShiftState); override;
+    procedure KeyUp(var Key: word; Shift: TShiftState); override;
+    // END / MDBUTTONFOCUS ONLY
+    procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
+    {%H-}WithThemeSpace: boolean); override;
+    procedure Paint; override;
+    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
+      X, Y: integer); override;
+    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override;
+    procedure MouseEnter; override;
+    procedure MouseLeave; override;
+    procedure RealSetText(const Value: TCaption); override;
+    procedure OnTimer(Sender: TObject);
+    procedure OnStartTimer(Sender: TObject);
+    procedure OnStopTimer(Sender: TObject);
+    function easeInOutQuad(t: double): double;
+    function easeOutQuad(t: double): double;
+    procedure UncheckOthers;
+    class function GetControlClassDefaultSize: TSize; override;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
+    procedure SelectAll;
+    procedure UnselectAll;
+    procedure InvertSelection;
+    function GetSelected: TStringList;
+  published
+    property Animation: boolean read FAnimation write SetFAnimation default False;
+    property Alignment: TAlignment read FAlignment write SetFAlignment default taCenter;
+    property TextLayout: TTextLayout
+      read FTextLayout write SetFTextLayout default tlCenter;
+    property StyleNormal: TBCMDButtonStyle read FStyleNormal write SetFStyleNormal;
+    property StyleHover: TBCMDButtonStyle read FStyleHover write SetFStyleHover;
+    property StyleActive: TBCMDButtonStyle read FStyleActive write SetFStyleActive;
+    property StyleDisabled: TBCMDButtonStyle read FStyleDisabled write SetFStyleDisabled;
+    property Checked: boolean read FChecked write SetFChecked default False;
+    property Kind: TBCMDButtonKind read FKind write SetFKind default mdbkNormal;
+    // If text size is used to measure buttons
+    // Disable it if you use the buttons in a grid, for example
+    property TextAutoSize: boolean read FTextAutoSize write SetFTextAutoSize;
+    // Enable it if you want that text size grows with height
+    property TextProportional: boolean read FTextProportional write SetFTextProportional;
+    // Each character font height proportional to height of control
+    // Set it in conjunction with TextProportional, values recommended between 0...1
+    property TextProportionalRatio: single read FTextProportionalRatio
+      write SetFTextProportionalRatio;
+  end;
+
+  TBCMDButtonFocus = class(TCustomBCMDButtonFocus)
+    property Action;
+    property Align;
+    property Anchors;
+    property AutoSize;
+    property BidiMode;
+    property BorderSpacing;
+    //property Cancel;
+    property Caption;
+    property Color;
+    property Constraints;
+    //property Default;
+    property DragCursor;
+    property DragKind;
+    property DragMode;
+    property Enabled;
+    property Font;
+    property ParentBidiMode;
+    //property ModalResult;
+    property OnChangeBounds;
+    property OnClick;
+    property OnContextPopup;
+    property OnDragDrop;
+    property OnDragOver;
+    property OnEndDrag;
+    //property OnEnter;
+    //property OnExit;
+    //property OnKeyDown;
+    //property OnKeyPress;
+    //property OnKeyUp;
+    property OnMouseDown;
+    property OnMouseEnter;
+    property OnMouseLeave;
+    property OnMouseMove;
+    property OnMouseUp;
+    property OnMouseWheel;
+    property OnMouseWheelDown;
+    property OnMouseWheelUp;
+    property OnResize;
+    property OnStartDrag;
+    //property OnUTF8KeyPress;
+    property ParentFont;
+    property ParentShowHint;
+    property PopupMenu;
+    property ShowHint;
+    //property TabOrder;
+    //property TabStop;
+    property Visible;
+  end;
+
+procedure Register;
+
+implementation
+
+{$IFDEF MDBUTTON_ANIMATEONLYONE}
+var
+  MDAnimating: TCustomMDButtonFocus;
+
+{$ENDIF}
+
+procedure Register;
+begin
+  RegisterComponents('BGRA Controls', [TBCMDButtonFocus]);
+end;
+
+{ TCustomBCMDButtonFocus }
+
+procedure TCustomBCMDButtonFocus.SetFStyleActive(AValue: TBCMDButtonStyle);
+begin
+  if FStyleActive = AValue then
+    Exit;
+  FStyleActive := AValue;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFAlignment(AValue: TAlignment);
+begin
+  if FAlignment = AValue then
+    Exit;
+  FAlignment := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFAnimation(AValue: boolean);
+begin
+  if FAnimation = AValue then
+    Exit;
+  FAnimation := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFChecked(AValue: boolean);
+begin
+  if FChecked = AValue then
+    Exit;
+  FChecked := AValue;
+  if FChecked and (FKind in [mdbkToggleGroup, mdbkRadioButton, mdbkTab]) then
+    UncheckOthers;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFKind(AValue: TBCMDButtonKind);
+begin
+  if FKind = AValue then
+    Exit;
+  FKind := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.OnChangeStyle(Sender: TObject);
+begin
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFStyleDisabled(AValue: TBCMDButtonStyle);
+begin
+  if FStyleDisabled = AValue then
+    Exit;
+  FStyleDisabled := AValue;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFStyleHover(AValue: TBCMDButtonStyle);
+begin
+  if FStyleHover = AValue then
+    Exit;
+  FStyleHover := AValue;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFStyleNormal(AValue: TBCMDButtonStyle);
+begin
+  if FStyleNormal = AValue then
+    Exit;
+  FStyleNormal := AValue;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFTextAutoSize(AValue: boolean);
+begin
+  if FTextAutoSize = AValue then
+    Exit;
+  FTextAutoSize := AValue;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFTextLayout(AValue: TTextLayout);
+begin
+  if FTextLayout = AValue then
+    Exit;
+  FTextLayout := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFTextProportional(AValue: boolean);
+begin
+  if FTextProportional = AValue then
+    Exit;
+  FTextProportional := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.SetFTextProportionalRatio(AValue: single);
+begin
+  if FTextProportionalRatio = AValue then
+    Exit;
+  FTextProportionalRatio := AValue;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.WMSetFocus(var Message: TLMSetFocus);
+begin
+  inherited;
+
+  UpdateFocus(True);
+end;
+
+procedure TCustomBCMDButtonFocus.WMKillFocus(var Message: TLMKillFocus);
+begin
+  inherited;
+
+  if Message.FocusedWnd <> Handle then
+    UpdateFocus(False);
+end;
+
+procedure TCustomBCMDButtonFocus.UpdateFocus(AFocused: boolean);
+var
+  lForm: TCustomForm;
+begin
+  lForm := GetParentForm(Self);
+  if lForm = nil then
+    exit;
+
+  if AFocused then
+    ActiveDefaultControlChanged(lForm.ActiveControl)
+  else
+    ActiveDefaultControlChanged(nil);
+
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.KeyDown(var Key: word; Shift: TShiftState);
+begin
+  inherited KeyDown(Key, Shift);
+
+  if (Key = VK_SPACE) or (Key = VK_RETURN) then
+    MouseDown(mbLeft, [], Width div 2, Height div 2);
+end;
+
+procedure TCustomBCMDButtonFocus.KeyUp(var Key: word; Shift: TShiftState);
+begin
+  if (Key = VK_SPACE) or (Key = VK_RETURN) then
+  begin
+    MouseLeave;
+    Self.Click;
+  end;
+
+  inherited KeyUp(Key, Shift);
+end;
+
+procedure TCustomBCMDButtonFocus.CalculatePreferredSize(
+  var PreferredWidth, PreferredHeight: integer; WithThemeSpace: boolean);
+var
+  bmp: TBGRABitmap;
+  s: TSize;
+begin
+  bmp := TBGRABitmap.Create;
+  bmp.FontName := Font.Name;
+  if FTextProportional then
+    bmp.FontHeight := Round(Height * FTextProportionalRatio)
+  else
+    bmp.FontHeight := 0;
+  bmp.FontAntialias := True;
+  bmp.FontQuality := fqSystemClearType;
+  bmp.FontStyle := Font.Style;
+  s := bmp.TextSize(Caption);
+  if FTextAutoSize then
+  begin
+    PreferredWidth := s.Width + 26 + BorderSpacing.InnerBorder;
+    PreferredHeight := s.Height + 10 + BorderSpacing.InnerBorder;
+  end
+  else
+  begin
+    PreferredWidth := BorderSpacing.InnerBorder;
+    PreferredHeight := BorderSpacing.InnerBorder;
+  end;
+  bmp.Free;
+end;
+
+procedure TCustomBCMDButtonFocus.Paint;
+var
+  bmp: TBGRABitmap;
+  iTemp: integer;
+  alpha: byte;
+  tempState: TBCMDButtonState;
+  tempText: string;
+  tempRounding: integer;
+  tempColor, hoverColor: TBGRAPixel;
+begin
+  bmp := TBGRABitmap.Create(Width, Height);
+  bmp.FontName := Font.Name;
+  if FTextProportional then
+    bmp.FontHeight := Round(Height * FTextProportionalRatio)
+  else
+    bmp.FontHeight := 0;
+  bmp.FontAntialias := True;
+  bmp.FontQuality := fqSystemClearType;
+  bmp.FontStyle := Font.Style;
+  tempState := FState;
+
+  if Kind = mdbkTab then
+    tempRounding := 0
+  else
+    tempRounding := FRounding;
+
+  if FChecked then
+    tempState := mdbsActive
+  else
+    tempState := FState;
+
+  // START / MDBUTTONFOCUS ONLY
+  if Focused and (tempState = mdbsNormal) then
+    tempState := mdbsHover;
+  // END / MDBUTTONFOCUS ONLY
+
+  tempText := Caption;
+
+  case FKind of
+    mdbkCheckBox:
+    begin
+      if Length(Caption) > 0 then
+        tempText := ' ' + Caption;
+      if FChecked then
+        tempText := BCMDBUTTONBALLOTBOXWITHCHECK + tempText
+      else
+        tempText := BCMDBUTTONBALLOTBOX + tempText;
+    end;
+    mdbkRadioButton:
+    begin
+      if Length(Caption) > 0 then
+        tempText := ' ' + Caption;
+      if FChecked then
+        tempText := BCMDBUTTONRADIOBUTTON + tempText
+      else
+        tempText := BCMDBUTTONRADIOBUTTONCIRCLE + tempText;
+    end;
+  end;
+
+  // Enabled
+  if Enabled then
+  begin
+    if not FTimer.Enabled then
+    begin
+      case tempState of
+        mdbsNormal:
+        begin
+          bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+            FStyleNormal.Color,
+            FStyleNormal.Color);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleNormal.TextColor);
+        end;
+        mdbsHover:
+        begin
+          bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+            FStyleHover.Color, FStyleHover.Color);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleHover.TextColor);
+        end;
+        mdbsActive:
+        begin
+          if not FAnimation then
+          begin
+            if FKind in [mdbkNormal] then
+              bmp.RoundRect(0, 0, Width, Height, tempRounding,
+                tempRounding, FStyleActive.Color,
+                FStyleActive.Color)
+            else
+              bmp.RoundRect(0, 0, Width, Height, tempRounding,
+                tempRounding, FStyleHover.Color,
+                FStyleHover.Color);
+          end
+          else
+            bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+              FStyleHover.Color,
+              FStyleHover.Color);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleActive.TextColor);
+        end;
+      end;
+    end
+    else
+    begin
+      iTemp := round(FCircleSize * easeOutQuad(FPercent));
+      alpha := round(easeInOutQuad(FAlphaPercent) * 255);
+      case tempState of
+        mdbsNormal:
+        begin
+          bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+            FStyleNormal.Color,
+            FStyleNormal.Color);
+          if FPercent < 1 then
+            tempColor := FStyleHover.Color
+          else
+          begin
+            tempColor := FStyleNormal.Color;
+            hoverColor := ColorToBGRA(FStyleHover.Color, alpha);
+            PutPixels(@tempColor, @hoverColor, 1, dmDrawWithTransparency, 255);
+          end;
+          bmp.FillEllipseAntialias(FCX, FCY, iTemp,
+            iTemp, tempColor);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleNormal.TextColor);
+        end;
+        mdbsHover, mdbsActive:
+        begin
+          bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+            FStyleHover.Color, FStyleHover.Color);
+          if FPercent < 1 then
+            tempColor := FStyleActive.Color
+          else
+          begin
+            tempColor := FStyleHover.Color;
+            hoverColor := ColorToBGRA(FStyleActive.Color, alpha);
+            PutPixels(@tempColor, @hoverColor, 1, dmDrawWithTransparency, 255);
+          end;
+          bmp.FillEllipseAntialias(FCX, FCY, iTemp,
+            iTemp, tempColor);
+          bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+            Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+            tempText, Alignment,
+            TextLayout, FStyleHover.TextColor);
+        end;
+      end;
+    end;
+  end
+  // Disabled
+  else
+  begin
+    if FChecked then
+    begin
+      bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+        FStyleHover.Color, FStyleHover.Color);
+    end
+    else
+      bmp.RoundRect(0, 0, Width, Height, tempRounding, tempRounding,
+        FStyleDisabled.Color, FStyleDisabled.Color);
+    bmp.TextRect(Rect(BorderSpacing.InnerBorder, BorderSpacing.InnerBorder,
+      Width - BorderSpacing.InnerBorder, Height - BorderSpacing.InnerBorder),
+      tempText, Alignment,
+      TextLayout, FStyleDisabled.TextColor);
+  end;
+
+  // Tab
+  if Kind = mdbkTab then
+  begin
+    if FTimer.Enabled then
+    begin
+      iTemp := round((bmp.Width div 2) * easeInOutQuad(FPercent));
+      bmp.Rectangle((bmp.Width div 2) - iTemp, bmp.Height - 2,
+        (bmp.Width div 2) + iTemp, bmp.Height, $00BB513F, dmSet);
+    end
+    else
+    begin
+      if FChecked then
+        bmp.Rectangle(0, bmp.Height - 2, bmp.Width, bmp.Height, $00BB513F, dmSet);
+    end;
+  end;
+
+  {$IFDEF MDBUTTON_DEBUG}
+  bmp.FontHeight := 10;
+  bmp.TextOut(0, 0, FCount.ToString, BGRA(255, 0, 0, 255));
+  FCount += 1;
+  {$ENDIF}
+  bmp.Draw(Canvas, 0, 0, False);
+  bmp.Free;
+  inherited Paint;
+end;
+
+procedure TCustomBCMDButtonFocus.MouseDown(Button: TMouseButton;
+  Shift: TShiftState; X, Y: integer);
+begin
+  inherited MouseDown(Button, Shift, X, Y);
+  FState := mdbsActive;
+  if FAnimation and BCMDBUTTONANIMATION then
+  begin
+    FCircleSize := max(round(Width / 1.5) + abs((Width div 2) - X),
+      round(Height / 1.5) + abs((Height div 2) - Y));
+    FCX := X;
+    FCY := Y;
+    FTimer.Enabled := False;
+    FTimer.Enabled := True;
+    {$IFDEF MDBUTTON_ANIMATEONLYONE}
+    MDAnimating := Self;
+    {$ENDIF}
+  end;
+  if FKind in [mdbkToggle, mdbkToggleGroup, mdbkCheckBox, mdbkRadioButton, mdbkTab] then
+  begin
+    FChecked := not FChecked;
+    if FKind in [mdbkToggleGroup, mdbkRadioButton, mdbkTab] then
+    begin
+      FChecked := True;
+      UncheckOthers;
+    end;
+  end;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.MouseUp(Button: TMouseButton;
+  Shift: TShiftState; X, Y: integer);
+begin
+  inherited MouseUp(Button, Shift, X, Y);
+  if (x > 0) and (x < Width) and (y > 0) and (y < Height) and (FState = mdbsActive) then
+    FState := mdbsHover
+  else
+    FState := mdbsNormal;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.MouseEnter;
+begin
+  inherited MouseEnter;
+  FState := mdbsHover;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.MouseLeave;
+begin
+  inherited MouseLeave;
+  FState := mdbsNormal;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.RealSetText(const Value: TCaption);
+begin
+  inherited RealSetText(Value);
+  InvalidatePreferredSize;
+  Invalidate;
+end;
+
+procedure TCustomBCMDButtonFocus.OnTimer(Sender: TObject);
+begin
+  {$IFDEF MDBUTTON_ANIMATEONLYONE}
+  if MDAnimating = Self then
+  begin
+  {$ENDIF}
+    FPercent += BCMDBUTTONANIMATIONSPEED;
+    if FPercent < 0 then
+      FPercent := 0
+    else if FPercent > 1 then
+      FPercent := 1;
+
+    if FPercent = 1 then
+    begin
+      FAlphaPercent -= BCMDBUTTONANIMATIONSPEED;
+      if FAlphaPercent < 0 then
+        FAlphaPercent := 0
+      else if FAlphaPercent > 1 then
+        FAlphaPercent := 1;
+    end;
+  {$IFDEF MDBUTTON_ANIMATEONLYONE}
+  end
+  else
+    FTimer.Enabled := False;
+  {$ENDIF}
+
+  Invalidate;
+  if (FPercent >= 1) and (FAlphaPercent <= 0) then
+    FTimer.Enabled := False;
+end;
+
+procedure TCustomBCMDButtonFocus.OnStartTimer(Sender: TObject);
+begin
+  FPercent := 0;
+  FAlphaPercent := 1;
+end;
+
+procedure TCustomBCMDButtonFocus.OnStopTimer(Sender: TObject);
+begin
+
+end;
+
+function TCustomBCMDButtonFocus.easeInOutQuad(t: double): double;
+begin
+  if t < 0.5 then
+    Result := 2 * t * t
+  else
+    Result := -1 + (4 - 2 * t) * t;
+end;
+
+function TCustomBCMDButtonFocus.easeOutQuad(t: double): double;
+begin
+  Result := t * (2 - t);
+end;
+
+procedure TCustomBCMDButtonFocus.UncheckOthers;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  if Parent is TWinControl then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] <> Self) and (control.Controls[i] is
+        TCustomBCMDButtonFocus) then
+        if (TCustomBCMDButtonFocus(control.Controls[i]).Kind in
+          [mdbkToggleGroup, mdbkRadioButton, mdbkTab]) then
+          TCustomBCMDButtonFocus(control.Controls[i]).Checked := False;
+  end;
+end;
+
+class function TCustomBCMDButtonFocus.GetControlClassDefaultSize: TSize;
+begin
+  Result.CX := 75;
+  Result.CY := 25;
+end;
+
+constructor TCustomBCMDButtonFocus.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  // START / MDBUTTONFOCUS ONLY
+  TabStop := True;
+  ControlStyle := ControlStyle + [csAcceptsControls];
+  DoubleBuffered := True;
+  // END / MDBUTTONFOCUS ONLY
+  {$IFDEF DEBUG}
+  FCount := 0;
+  {$ENDIF}
+  // State
+  FState := mdbsNormal;
+  FChecked := False;
+  FKind := mdbkNormal;
+  // Text
+  FTextAutoSize := True;
+  FAlignment := taCenter;
+  FTextLayout := tlCenter;
+  FTextProportional := False;
+  FTextProportionalRatio := 0.5;
+  // Style
+  FRounding := 6;
+  FStyleNormal := TBCMDButtonStyle.Create;
+  FStyleNormal.OnChange := @OnChangeStyle;
+  FStyleHover := TBCMDButtonStyle.Create;
+  FStyleHover.OnChange := @OnChangeStyle;
+  FStyleActive := TBCMDButtonStyle.Create;
+  FStyleActive.OnChange := @OnChangeStyle;
+  FStyleDisabled := TBCMDButtonStyle.Create;
+  FStyleDisabled.OnChange := @OnChangeStyle;
+  // Default Style
+  FStyleHover.Color := RGBToColor(220, 220, 220);
+  FStyleActive.Color := RGBToColor(198, 198, 198);
+  FStyleDisabled.TextColor := RGBToColor(163, 163, 163);
+  // Animation
+  FAnimation := False;
+  FTimer := TTimer.Create(Self);
+  FTimer.Enabled := False;
+  FTimer.Interval := BCMDBUTTONTIMERSPEED;
+  FTimer.OnTimer := @OnTimer;
+  FTimer.OnStartTimer := @OnStartTimer;
+  FTimer.OnStopTimer := @OnStopTimer;
+  // Setup default sizes
+  with GetControlClassDefaultSize do
+    SetInitialBounds(0, 0, CX, CY);
+end;
+
+destructor TCustomBCMDButtonFocus.Destroy;
+begin
+  FTimer.OnTimer := nil;
+  FTimer.OnStartTimer := nil;
+  FTimer.OnStopTimer := nil;
+  FTimer.Enabled := False;
+  FStyleNormal.Free;
+  FStyleHover.Free;
+  FStyleActive.Free;
+  FStyleDisabled.Free;
+  inherited Destroy;
+end;
+
+procedure TCustomBCMDButtonFocus.SelectAll;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  if Parent is TWinControl then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] is TCustomBCMDButtonFocus) then
+        if (TCustomBCMDButtonFocus(control.Controls[i]).Kind in
+          [mdbkToggle, mdbkCheckBox]) then
+          TCustomBCMDButtonFocus(control.Controls[i]).Checked := True;
+  end;
+end;
+
+procedure TCustomBCMDButtonFocus.UnselectAll;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  if Parent is TWinControl then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] is TCustomBCMDButtonFocus) then
+        if (TCustomBCMDButtonFocus(control.Controls[i]).Kind in
+          [mdbkToggle, mdbkCheckBox]) then
+          TCustomBCMDButtonFocus(control.Controls[i]).Checked := False;
+  end;
+end;
+
+procedure TCustomBCMDButtonFocus.InvertSelection;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  if Parent is TWinControl then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] is TCustomBCMDButtonFocus) then
+        if (TCustomBCMDButtonFocus(control.Controls[i]).Kind in
+          [mdbkToggle, mdbkCheckBox]) then
+          TCustomBCMDButtonFocus(control.Controls[i]).Checked :=
+            not TCustomBCMDButtonFocus(control.Controls[i]).Checked;
+  end;
+end;
+
+function TCustomBCMDButtonFocus.GetSelected: TStringList;
+var
+  i: integer;
+  control: TWinControl;
+begin
+  Result := TStringList.Create;
+  if Parent is TWinControl then
+  begin
+    control := TWinControl(Parent);
+    for i := 0 to control.ControlCount - 1 do
+      if (control.Controls[i] is TCustomBCMDButtonFocus) then
+        if TCustomBCMDButtonFocus(control.Controls[i]).Checked then
+          Result.AddObject(TCustomBCMDButtonFocus(control.Controls[i]).Caption,
+            TCustomBCMDButtonFocus(control.Controls[i]));
+  end;
+end;
+
+end.

+ 14 - 2
bgracontrols.lpk

@@ -20,13 +20,15 @@
       <Linking>
         <Debugging>
           <GenerateDebugInfo Value="False"/>
+          <DebugInfoType Value="dsDwarf2Set"/>
+          <UseValgrind Value="True"/>
         </Debugging>
       </Linking>
     </CompilerOptions>
     <Description Value="BGRA Controls is a set of graphical UI elements that you can use with Lazarus LCL applications."/>
     <License Value="Modified LGPL"/>
-    <Version Major="4" Minor="6" Release="2"/>
-    <Files Count="45">
+    <Version Major="5"/>
+    <Files Count="47">
       <Item1>
         <Filename Value="bcbasectrls.pas"/>
         <AddToUsesPkgSection Value="False"/>
@@ -245,6 +247,16 @@
         <AddToUsesPkgSection Value="False"/>
         <UnitName Value="MouseAndKeyInput"/>
       </Item45>
+      <Item46>
+        <Filename Value="bcmdbutton.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="BCMDButton"/>
+      </Item46>
+      <Item47>
+        <Filename Value="bcmdbuttonfocus.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="BCMDButtonFocus"/>
+      </Item47>
     </Files>
     <RequiredPkgs Count="2">
       <Item1>

+ 4 - 1
bgracontrols.pas

@@ -15,7 +15,8 @@ uses
   BGRAImageList, BGRAImageManipulation, BGRAKnob, BGRAResizeSpeedButton, 
   BGRAShape, BGRASpeedButton, BGRASpriteAnimation, BGRAVirtualScreen, 
   ColorSpeedButton, DTAnalogClock, DTAnalogGauge, dtthemedclock, 
-  dtthemedgauge, MaterialColors, LazarusPackageIntf;
+  dtthemedgauge, MaterialColors, bcmdbutton, bcmdbuttonfocus, 
+  LazarusPackageIntf;
 
 implementation
 
@@ -49,6 +50,8 @@ begin
   RegisterUnit('DTAnalogGauge', @DTAnalogGauge.Register);
   RegisterUnit('dtthemedclock', @dtthemedclock.Register);
   RegisterUnit('dtthemedgauge', @dtthemedgauge.Register);
+  RegisterUnit('bcmdbutton', @bcmdbutton.Register);
+  RegisterUnit('bcmdbuttonfocus', @bcmdbuttonfocus.Register);
 end;
 
 initialization

BIN
test/test_bcimagebutton_3dbutton/boton3d.png


+ 83 - 0
test/test_bcimagebutton_3dbutton/test_drawing.lpi

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="10"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="test_drawing"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Resources Count="1">
+        <Resource_0 FileName="boton3d.png" Type="RCDATA" ResourceName="BOTON3D"/>
+      </Resources>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </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="test_drawing.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="frmMain"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="test_drawing"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </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_bcimagebutton_3dbutton/test_drawing.lpr

@@ -0,0 +1,21 @@
+program test_drawing;
+
+{$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(TfrmMain, frmMain);
+  Application.Run;
+end.
+

+ 45 - 0
test/test_bcimagebutton_3dbutton/umain.lfm

@@ -0,0 +1,45 @@
+object frmMain: TfrmMain
+  Left = 354
+  Height = 353
+  Top = 146
+  Width = 491
+  Caption = 'Test Drawing'
+  ClientHeight = 353
+  ClientWidth = 491
+  Color = clSilver
+  DesignTimePPI = 120
+  OnCreate = FormCreate
+  LCLVersion = '1.8.4.0'
+  object BCImageButton1: TBCImageButton
+    Left = 8
+    Height = 137
+    Top = 8
+    Width = 188
+    BitmapOptions.MarginTop = 9
+    BitmapOptions.MarginRight = 13
+    BitmapOptions.MarginBottom = 15
+    BitmapOptions.MarginLeft = 13
+    BitmapOptions.Direction = sdVertical
+    Caption = 'Button'
+    Font.Height = 30
+    ParentFont = False
+    ParentShowHint = False
+  end
+  object BCImageButton2: TBCImageButton
+    Left = 208
+    Height = 137
+    Top = 8
+    Width = 188
+    BitmapOptions.MarginTop = 9
+    BitmapOptions.MarginRight = 13
+    BitmapOptions.MarginBottom = 15
+    BitmapOptions.MarginLeft = 13
+    BitmapOptions.Direction = sdVertical
+    Caption = 'Toggle Button'
+    Font.Height = 30
+    ParentFont = False
+    ParentShowHint = False
+    Toggle = True
+    Pressed = True
+  end
+end

+ 41 - 0
test/test_bcimagebutton_3dbutton/umain.pas

@@ -0,0 +1,41 @@
+unit umain;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
+  BCImageButton;
+
+type
+
+  { TfrmMain }
+
+  TfrmMain = class(TForm)
+    BCImageButton1: TBCImageButton;
+    BCImageButton2: TBCImageButton;
+    procedure FormCreate(Sender: TObject);
+  private
+
+  public
+
+  end;
+
+var
+  frmMain: TfrmMain;
+
+implementation
+
+{$R *.lfm}
+
+{ TfrmMain }
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+  BCImageButton1.LoadFromBitmapResource('boton3d');
+  BCImageButton2.LoadFromBitmapResource('boton3d');
+end;
+
+end.
+

+ 169 - 0
test/test_bgramacos/button/bgramacosbutton.lpi

@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="10"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="bgramacosbutton"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+    </General>
+    <BuildModes Count="3">
+      <Item1 Name="Debug" Default="True"/>
+      <Item2 Name="Release">
+        <CompilerOptions>
+          <Version Value="11"/>
+          <PathDelim Value="\"/>
+          <Target>
+            <Filename Value="bin\$(TargetCPU)-$(TargetOS)\release\bgramacosbutton"/>
+          </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>
+        </CompilerOptions>
+      </Item2>
+      <Item3 Name="Release macOS 64">
+        <MacroValues Count="1">
+          <Macro1 Name="LCLWidgetType" Value="cocoa"/>
+        </MacroValues>
+        <CompilerOptions>
+          <Version Value="11"/>
+          <PathDelim Value="\"/>
+          <Target>
+            <Filename Value="bin\$(TargetCPU)-$(TargetOS)\release\bgramacosbutton"/>
+          </Target>
+          <SearchPaths>
+            <IncludeFiles Value="$(ProjOutDir)"/>
+            <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+          </SearchPaths>
+          <CodeGeneration>
+            <SmartLinkUnit Value="True"/>
+            <TargetCPU Value="x86_64"/>
+            <TargetOS Value="darwin"/>
+            <Optimizations>
+              <OptimizationLevel Value="3"/>
+            </Optimizations>
+          </CodeGeneration>
+          <Linking>
+            <Debugging>
+              <GenerateDebugInfo Value="False"/>
+            </Debugging>
+            <LinkSmart Value="True"/>
+            <Options>
+              <Win32>
+                <GraphicApplication Value="True"/>
+              </Win32>
+            </Options>
+          </Linking>
+        </CompilerOptions>
+      </Item3>
+      <SharedMatrixOptions Count="1">
+        <Item1 ID="031221446204" Modes="Release macOS 64" Type="IDEMacro" MacroName="LCLWidgetType" Value="cocoa"/>
+      </SharedMatrixOptions>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </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="bgramacosbutton.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="frmMain"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="bin\$(TargetCPU)-$(TargetOS)\debug\bgramacosbutton"/>
+    </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>
+      <VerifyObjMethodCallValidity Value="True"/>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <DebugInfoType Value="dsDwarf2Set"/>
+        <UseHeaptrc Value="True"/>
+        <TrashVariables Value="True"/>
+        <UseExternalDbgSyms Value="True"/>
+      </Debugging>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 22 - 0
test/test_bgramacos/button/bgramacosbutton.lpr

@@ -0,0 +1,22 @@
+program bgramacosbutton;
+
+{$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
+  Application.Scaled:=True;
+  RequireDerivedFormResource:=True;
+  Application.Initialize;
+  Application.CreateForm(TfrmMain, frmMain);
+  Application.Run;
+end.
+

+ 81 - 0
test/test_bgramacos/button/bgramacosdraw.pas

@@ -0,0 +1,81 @@
+unit bgramacosdraw;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, BGRABitmap, BGRABitmapTypes, BGRAGradientScanner, Math;
+
+type
+
+  { TBGRAMacOS }
+
+  TBGRAMacOS = class
+    class var BUTTONLINEWIDTH: single;
+    // Generic gradient button that's used by the other methods
+    class procedure GradientButton(
+      const lineTop, lineBottom, fillTop, fillBottom: TBGRAPixel;
+      const ADest: TBGRABitmap; const ARect: TRect);
+
+    // Button
+    class procedure Button(const ADest: TBGRABitmap; const ARect: TRect);
+    class procedure ButtonActive(const ADest: TBGRABitmap; const ARect: TRect);
+    class procedure ButtonPressed(const ADest: TBGRABitmap; const ARect: TRect);
+  end;
+
+implementation
+
+{ TBGRAMacOS }
+
+class procedure TBGRAMacOS.GradientButton(
+  const lineTop, lineBottom, fillTop, fillBottom: TBGRAPixel;
+  const ADest: TBGRABitmap; const ARect: TRect);
+var
+  gradient, gradientfill: TBGRAGradientScanner;
+  halflinewidth: integer;
+begin
+  if (BUTTONLINEWIDTH * 2) + 3 > ARect.Height then
+    Exit;
+  if (BUTTONLINEWIDTH * 2) + 3 > ARect.Width then
+    Exit;
+
+  gradient := TBGRAGradientScanner.Create(lineTop, lineBottom, gtLinear,
+    PointF(0, 0), PointF(0, ARect.Bottom));
+
+  gradientfill := TBGRAGradientScanner.Create(fillTop, fillBottom,
+    gtLinear, PointF(0, BUTTONLINEWIDTH), PointF(0, ARect.Bottom - BUTTONLINEWIDTH));
+
+  halflinewidth := ceil(BUTTONLINEWIDTH * 0.5);
+
+  ADest.RoundRectAntialias(ARect.Left + halflinewidth,
+    ARect.Top + halflinewidth, ARect.Right - halflinewidth - 1,
+    ARect.Bottom - halflinewidth - 1,
+    4, 4, gradient, BUTTONLINEWIDTH, gradientfill);
+
+  FreeAndNil(gradient);
+  FreeAndNil(gradientfill);
+end;
+
+class procedure TBGRAMacOS.Button(const ADest: TBGRABitmap; const ARect: TRect);
+begin
+  GradientButton(BGRA(210, 210, 210), BGRA(180, 180, 180), BGRAWhite,
+    BGRAWhite, ADest, ARect);
+end;
+
+class procedure TBGRAMacOS.ButtonActive(const ADest: TBGRABitmap; const ARect: TRect);
+begin
+  GradientButton(BGRA(83, 160, 246), BGRA(43, 93, 251), BGRA(111, 177, 248),
+    BGRA(45, 127, 252), ADest, ARect);
+end;
+
+class procedure TBGRAMacOS.ButtonPressed(const ADest: TBGRABitmap; const ARect: TRect);
+begin
+  GradientButton(BGRA(55, 124, 251), BGRA(36, 60, 218), BGRA(84, 149, 250),
+    BGRA(39, 102, 225), ADest, ARect);
+end;
+
+initialization
+  TBGRAMacOS.BUTTONLINEWIDTH := 1;
+
+end.

+ 19 - 0
test/test_bgramacos/button/umain.lfm

@@ -0,0 +1,19 @@
+object frmMain: TfrmMain
+  Left = 268
+  Height = 257
+  Top = 126
+  Width = 322
+  Caption = 'BGRA macOS Button'
+  ClientHeight = 257
+  ClientWidth = 322
+  LCLVersion = '1.8.4.0'
+  object BCXButton1: TBCXButton
+    Left = 8
+    Height = 26
+    Top = 8
+    Width = 112
+    OnRenderControl = BCXButton1RenderControl
+    Anchors = [akTop, akLeft, akRight, akBottom]
+    Caption = 'Hello World'
+  end
+end

+ 66 - 0
test/test_bgramacos/button/umain.pas

@@ -0,0 +1,66 @@
+unit umain;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
+  BGRAGraphicControl, BGRABitmap, BCTypes, BCTrackbarUpdown, BCImageButton,
+  BGRABitmapTypes;
+
+type
+
+  { TfrmMain }
+
+  TfrmMain = class(TForm)
+    BCXButton1: TBCXButton;
+    procedure BCXButton1RenderControl(Sender: TObject; Bitmap: TBGRABitmap;
+      State: TBCGraphicButtonState);
+  private
+
+  public
+
+  end;
+
+var
+  frmMain: TfrmMain;
+
+implementation
+
+uses
+  bgramacosdraw;
+
+{$R *.lfm}
+
+{ TfrmMain }
+
+procedure TfrmMain.BCXButton1RenderControl(Sender: TObject;
+  Bitmap: TBGRABitmap; State: TBCGraphicButtonState);
+var
+  r: TRect;
+begin
+  r := Rect(0, 0, Bitmap.Width, Bitmap.Height);
+  Bitmap.FontHeight := 12;
+  Bitmap.FontQuality := fqSystemClearType;
+  case State of
+    gbsNormal:
+    begin
+      TBGRAMacOs.Button(Bitmap, r);
+      Bitmap.TextRect(r, BCXButton1.Caption, taCenter, tlCenter, BGRABlack);
+    end;
+    gbsHover:
+    begin
+      TBGRAMacOs.ButtonActive(Bitmap, r);
+      Bitmap.TextRect(r, BCXButton1.Caption, taCenter, tlCenter, BGRAWhite);
+    end;
+    gbsActive:
+    begin
+      TBGRAMacOs.ButtonPressed(Bitmap, r);
+      Bitmap.TextRect(r, BCXButton1.Caption, taCenter, tlCenter, BGRA(224, 230, 243));
+    end;
+  end;
+end;
+
+end.
+

BIN
test/test_materialdesign/drawings/test.ico


+ 81 - 0
test/test_materialdesign/drawings/test.lpi

@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="test"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Icon Value="0"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+      <Modes Count="0"/>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="bgracontrols"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="LCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="test.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="test"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 22 - 0
test/test_materialdesign/drawings/test.lpr

@@ -0,0 +1,22 @@
+program test;
+
+{$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.Scaled:=True;
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.
+

+ 43 - 0
test/test_materialdesign/drawings/umain.lfm

@@ -0,0 +1,43 @@
+object Form1: TForm1
+  Left = 409
+  Height = 400
+  Top = 143
+  Width = 820
+  Caption = 'Drawings'
+  ChildSizing.LeftRightSpacing = 10
+  ChildSizing.TopBottomSpacing = 10
+  ChildSizing.HorizontalSpacing = 10
+  ChildSizing.VerticalSpacing = 10
+  ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
+  ChildSizing.EnlargeVertical = crsHomogenousChildResize
+  ChildSizing.ShrinkHorizontal = crsHomogenousChildResize
+  ChildSizing.ShrinkVertical = crsHomogenousChildResize
+  ChildSizing.Layout = cclLeftToRightThenTopToBottom
+  ChildSizing.ControlsPerLine = 2
+  ClientHeight = 400
+  ClientWidth = 820
+  DesignTimePPI = 120
+  LCLVersion = '1.9.0.0'
+  object g1: TBGRAGraphicControl
+    Left = 10
+    Height = 380
+    Top = 10
+    Width = 395
+    OnRedraw = g1Redraw
+    BevelOuter = bvNone
+    Color = clWhite
+    ColorOpacity = 128
+    Alignment = taCenter
+  end
+  object g2: TBGRAGraphicControl
+    Left = 415
+    Height = 380
+    Top = 10
+    Width = 395
+    OnRedraw = g2Redraw
+    BevelOuter = bvNone
+    Color = clWhite
+    ColorOpacity = 128
+    Alignment = taCenter
+  end
+end

+ 71 - 0
test/test_materialdesign/drawings/umain.pas

@@ -0,0 +1,71 @@
+unit umain;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, BGRAGraphicControl, BGRABitmap, BCTypes,
+  BGRABitmapTypes, Math;
+
+type
+
+  { TForm1 }
+
+  TForm1 = class(TForm)
+    g1: TBGRAGraphicControl;
+    g2: TBGRAGraphicControl;
+    procedure g1Redraw(Sender: TObject; Bitmap: TBGRABitmap);
+    procedure g2Redraw(Sender: TObject; Bitmap: TBGRABitmap);
+  private
+
+  public
+
+  end;
+
+var
+  Form1: TForm1;
+
+implementation
+
+{$R *.lfm}
+
+{ TForm1 }
+
+procedure TForm1.g1Redraw(Sender: TObject; Bitmap: TBGRABitmap
+  );
+const
+  offset = 8;
+var
+  temp: TBGRABitmap;
+begin
+  Bitmap.FillTransparent;
+  Bitmap.FillEllipseAntialias(g1.Width div 2, (g1.Height) div 2, (g1.Width - 10) div 2, (g1.Height - 10) div 2, BGRA(150, 150, 150));
+  temp := TBGRABitmap.Create;
+  BGRAReplace(temp, Bitmap.FilterBlurRadial(5, 5, rbFast));
+  Bitmap.FillTransparent;
+  Bitmap.PutImage(0, 0, temp, dmDrawWithTransparency);
+  temp.Free;
+  Bitmap.FillEllipseAntialias(g1.Width div 2, (g1.Height - offset) div 2, (g1.Width - offset) div 2, (g1.Height - offset) div 2, BGRAWhite);
+  Bitmap.FontHeight := Min(g1.Height div 2, g1.Width div 2);
+  Bitmap.TextRect(Rect(0, 0, g1.Width, g1.Height - offset), '🐣', TAlignment.taCenter, TTextLayout.tlCenter, BGRABlack);
+end;
+
+procedure TForm1.g2Redraw(Sender: TObject; Bitmap: TBGRABitmap);
+var
+  temp: TBGRABitmap;
+begin
+  Bitmap.FillTransparent;
+  Bitmap.FillRoundRectAntialias(10, 10, g2.Width - 10, g2.Height - 10, 8, 8, BGRA(100,100,100));
+  temp := TBGRABitmap.Create;
+  BGRAReplace(temp, Bitmap.FilterBlurRadial(5, 5, rbFast));
+  Bitmap.FillTransparent;
+  Bitmap.PutImage(0, 0, temp, dmDrawWithTransparency);
+  temp.Free;
+  Bitmap.FillRoundRectAntialias(8, 0, g2.Width - 8, g2.Height - 10, 10, 10, BGRAWhite, [], False);
+  Bitmap.FontHeight := Min(g2.Height div 2, g2.Width div 2);
+  Bitmap.TextRect(Rect(0, 0, g2.Width, g2.Height - 8), '🐣', TAlignment.taCenter, TTextLayout.tlCenter, BGRABlack);
+end;
+
+end.
+

+ 164 - 0
test/test_materialdesign/mdbutton/test.lpi

@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="10"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="MDButton"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+    </General>
+    <BuildModes Count="3">
+      <Item1 Name="Debug" Default="True"/>
+      <Item2 Name="Release">
+        <CompilerOptions>
+          <Version Value="11"/>
+          <PathDelim Value="\"/>
+          <Target>
+            <Filename Value="bin\$(TargetCPU)-$(TargetOS)\test"/>
+          </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>
+        </CompilerOptions>
+      </Item2>
+      <Item3 Name="Release Linux64">
+        <CompilerOptions>
+          <Version Value="11"/>
+          <PathDelim Value="\"/>
+          <Target>
+            <Filename Value="bin\$(TargetCPU)-$(TargetOS)\test"/>
+          </Target>
+          <SearchPaths>
+            <IncludeFiles Value="$(ProjOutDir)"/>
+            <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+          </SearchPaths>
+          <CodeGeneration>
+            <SmartLinkUnit Value="True"/>
+            <TargetCPU Value="x86_64"/>
+            <TargetOS Value="linux"/>
+            <Optimizations>
+              <OptimizationLevel Value="3"/>
+            </Optimizations>
+          </CodeGeneration>
+          <Linking>
+            <Debugging>
+              <GenerateDebugInfo Value="False"/>
+            </Debugging>
+            <LinkSmart Value="True"/>
+            <Options>
+              <Win32>
+                <GraphicApplication Value="True"/>
+              </Win32>
+            </Options>
+          </Linking>
+        </CompilerOptions>
+      </Item3>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </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="test.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="project1"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="frmMain"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="bin\debug\$(TargetCPU)-$(TargetOS)\test"/>
+    </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>
+      <VerifyObjMethodCallValidity Value="True"/>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <DebugInfoType Value="dsDwarf2Set"/>
+        <UseHeaptrc Value="True"/>
+        <TrashVariables Value="True"/>
+        <UseExternalDbgSyms Value="True"/>
+      </Debugging>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 23 - 0
test/test_materialdesign/mdbutton/test.lpr

@@ -0,0 +1,23 @@
+program MDButton;
+
+{$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
+  Application.Scaled:=True;
+  Application.Title:='MDButton';
+  RequireDerivedFormResource:=True;
+  Application.Initialize;
+  Application.CreateForm(TfrmMain, frmMain);
+  Application.Run;
+end.
+

+ 780 - 0
test/test_materialdesign/mdbutton/umain.lfm

@@ -0,0 +1,780 @@
+object frmMain: TfrmMain
+  Left = 599
+  Height = 610
+  Top = 176
+  Width = 522
+  AutoSize = True
+  Caption = 'BCMDButton'
+  ChildSizing.LeftRightSpacing = 10
+  ChildSizing.TopBottomSpacing = 10
+  ChildSizing.VerticalSpacing = 10
+  ChildSizing.EnlargeHorizontal = crsHomogenousChildResize
+  ChildSizing.Layout = cclLeftToRightThenTopToBottom
+  ChildSizing.ControlsPerLine = 1
+  ClientHeight = 610
+  ClientWidth = 522
+  Color = 16448250
+  DesignTimePPI = 120
+  OnCreate = FormCreate
+  Position = poScreenCenter
+  ShowHint = True
+  LCLVersion = '1.8.4.0'
+  object Label1: TLabel
+    Cursor = crHelp
+    Left = 10
+    Height = 20
+    Hint = 'Set "Kind" property to mdbkNormal'
+    Top = 10
+    Width = 502
+    Caption = 'Basic Buttons'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Panel13: TPanel
+    Left = 10
+    Height = 30
+    Top = 40
+    Width = 502
+    AutoSize = True
+    BevelOuter = bvNone
+    ChildSizing.HorizontalSpacing = 20
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 4
+    ClientHeight = 30
+    ClientWidth = 502
+    ParentFont = False
+    TabOrder = 5
+    object BCMDButton1: TBCMDButton
+      Cursor = crHandPoint
+      Left = 0
+      Height = 30
+      Top = 0
+      Width = 60
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Basic'
+      ParentFont = False
+    end
+    object BCMDButton2: TBCMDButton
+      Cursor = crHandPoint
+      Left = 80
+      Height = 30
+      Top = 0
+      Width = 76
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = 12276031
+      StyleHover.Color = 15918563
+      StyleHover.TextColor = 12276031
+      StyleActive.Color = 15456211
+      StyleActive.TextColor = 12276031
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Primary'
+      ParentFont = False
+    end
+    object BCMDButton5: TBCMDButton
+      Cursor = crHandPoint
+      Left = 176
+      Height = 30
+      Top = 0
+      Width = 85
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = 16448250
+      StyleDisabled.TextColor = 10724259
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Disabled'
+      Enabled = False
+      ParentFont = False
+    end
+  end
+  object Label3: TLabel
+    Cursor = crHelp
+    Left = 10
+    Height = 20
+    Hint = 'Set "Kind" property to mdbkToggleGroup'
+    Top = 80
+    Width = 502
+    Caption = 'Toggle Group'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Panel1: TPanel
+    Left = 10
+    Height = 30
+    Top = 110
+    Width = 502
+    AutoSize = True
+    BevelOuter = bvNone
+    ChildSizing.HorizontalSpacing = 20
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 3
+    ClientHeight = 30
+    ClientWidth = 502
+    ParentFont = False
+    TabOrder = 0
+    object BCMDButton9: TBCMDButton
+      Cursor = crHandPoint
+      Left = 0
+      Height = 30
+      Top = 0
+      Width = 36
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkToggleGroup
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'A'
+      ParentFont = False
+    end
+    object BCMDButton10: TBCMDButton
+      Cursor = crHandPoint
+      Left = 56
+      Height = 30
+      Top = 0
+      Width = 35
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkToggleGroup
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'B'
+      ParentFont = False
+    end
+    object BCMDButton11: TBCMDButton
+      Cursor = crHandPoint
+      Left = 111
+      Height = 30
+      Top = 0
+      Width = 35
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Checked = True
+      Kind = mdbkToggleGroup
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'C'
+      Enabled = False
+      ParentFont = False
+    end
+  end
+  object Label5: TLabel
+    Cursor = crHelp
+    Left = 10
+    Height = 20
+    Hint = 'Set "Kind" property to mdbkToggle'
+    Top = 150
+    Width = 502
+    Caption = 'Toggle'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Panel12: TPanel
+    Left = 10
+    Height = 30
+    Top = 180
+    Width = 502
+    AutoSize = True
+    BevelOuter = bvNone
+    ChildSizing.HorizontalSpacing = 20
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 4
+    ClientHeight = 30
+    ClientWidth = 502
+    ParentFont = False
+    TabOrder = 4
+    object BCMDButton15: TBCMDButton
+      Cursor = crHandPoint
+      Left = 0
+      Height = 30
+      Top = 0
+      Width = 36
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkToggle
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'A'
+      ParentFont = False
+    end
+    object BCMDButton16: TBCMDButton
+      Cursor = crHandPoint
+      Left = 56
+      Height = 30
+      Top = 0
+      Width = 35
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkToggle
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'B'
+      ParentFont = False
+    end
+    object BCMDButton17: TBCMDButton
+      Cursor = crHandPoint
+      Left = 111
+      Height = 30
+      Top = 0
+      Width = 35
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Checked = True
+      Kind = mdbkToggle
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'C'
+      Enabled = False
+      ParentFont = False
+    end
+  end
+  object Label7: TLabel
+    Cursor = crHelp
+    Left = 10
+    Height = 20
+    Hint = 'Set "Kind" property to mdbkCheckBox'
+    Top = 220
+    Width = 502
+    Caption = 'Check Box'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Panel11: TPanel
+    Left = 10
+    Height = 30
+    Top = 250
+    Width = 502
+    AutoSize = True
+    BevelOuter = bvNone
+    ChildSizing.HorizontalSpacing = 20
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 4
+    ClientHeight = 30
+    ClientWidth = 502
+    ParentFont = False
+    TabOrder = 2
+    object mdInvert: TBCMDButton
+      Cursor = crHandPoint
+      Left = 0
+      Height = 30
+      Top = 0
+      Width = 128
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Invert Selection'
+      OnClick = mdInvertClick
+      ParentFont = False
+    end
+    object mdUnselect: TBCMDButton
+      Cursor = crHandPoint
+      Left = 148
+      Height = 30
+      Top = 0
+      Width = 104
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Unselect All'
+      OnClick = mdUnselectClick
+      ParentFont = False
+    end
+    object mdSelect: TBCMDButton
+      Cursor = crHandPoint
+      Left = 272
+      Height = 30
+      Top = 0
+      Width = 88
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Select All'
+      OnClick = mdSelectClick
+      ParentFont = False
+    end
+    object mdGet: TBCMDButton
+      Cursor = crHandPoint
+      Left = 380
+      Height = 30
+      Top = 0
+      Width = 110
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Get Selected'
+      OnClick = mdGetClick
+      ParentFont = False
+    end
+  end
+  object Panel9: TPanel
+    Left = 10
+    Height = 30
+    Top = 290
+    Width = 502
+    AutoSize = True
+    BevelOuter = bvNone
+    ChildSizing.HorizontalSpacing = 20
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 3
+    ClientHeight = 30
+    ClientWidth = 502
+    ParentFont = False
+    TabOrder = 1
+    object BCMDButton33: TBCMDButton
+      Cursor = crHandPoint
+      Left = 0
+      Height = 30
+      Top = 0
+      Width = 101
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkCheckBox
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Option 1'
+      ParentFont = False
+    end
+    object BCMDButton34: TBCMDButton
+      Cursor = crHandPoint
+      Left = 121
+      Height = 30
+      Top = 0
+      Width = 101
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkCheckBox
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Option 2'
+      ParentFont = False
+    end
+    object BCMDButton35: TBCMDButton
+      Cursor = crHandPoint
+      Left = 242
+      Height = 30
+      Top = 0
+      Width = 101
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Checked = True
+      Kind = mdbkCheckBox
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Option 3'
+      Enabled = False
+      ParentFont = False
+    end
+  end
+  object Label9: TLabel
+    Cursor = crHelp
+    Left = 10
+    Height = 20
+    Hint = 'Set "Kind" property to mdbkRadioButton'
+    Top = 330
+    Width = 502
+    Caption = 'Radio Button'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Panel2: TPanel
+    Left = 10
+    Height = 70
+    Top = 360
+    Width = 502
+    AutoSize = True
+    BevelOuter = bvNone
+    ChildSizing.VerticalSpacing = 10
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 1
+    ClientHeight = 70
+    ClientWidth = 502
+    ParentFont = False
+    TabOrder = 6
+    object mdGetRadio: TBCMDButton
+      Cursor = crHandPoint
+      Left = 0
+      Height = 30
+      Top = 0
+      Width = 353
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Get Selected'
+      OnClick = mdGetRadioClick
+      ParentFont = False
+    end
+    object Panel7: TPanel
+      Left = 0
+      Height = 30
+      Top = 40
+      Width = 353
+      AutoSize = True
+      BevelOuter = bvNone
+      ChildSizing.HorizontalSpacing = 20
+      ChildSizing.Layout = cclLeftToRightThenTopToBottom
+      ChildSizing.ControlsPerLine = 3
+      ClientHeight = 30
+      ClientWidth = 353
+      ParentFont = False
+      TabOrder = 0
+      object BCMDButton27: TBCMDButton
+        Cursor = crHandPoint
+        Left = 0
+        Height = 30
+        Top = 0
+        Width = 105
+        Animation = True
+        StyleNormal.Color = 16448250
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        Kind = mdbkRadioButton
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Option 1'
+        ParentFont = False
+      end
+      object BCMDButton28: TBCMDButton
+        Cursor = crHandPoint
+        Left = 125
+        Height = 30
+        Top = 0
+        Width = 105
+        Animation = True
+        StyleNormal.Color = 16448250
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        Kind = mdbkRadioButton
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Option 2'
+        ParentFont = False
+      end
+      object BCMDButton29: TBCMDButton
+        Cursor = crHandPoint
+        Left = 250
+        Height = 30
+        Top = 0
+        Width = 103
+        Animation = True
+        StyleNormal.Color = 16448250
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        Checked = True
+        Kind = mdbkRadioButton
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Option 3'
+        Enabled = False
+        ParentFont = False
+      end
+    end
+  end
+  object Label10: TLabel
+    Cursor = crHelp
+    Left = 10
+    Height = 20
+    Hint = 'Set "Kind" property to mdbkTab'
+    Top = 440
+    Width = 502
+    Caption = 'Tab'
+    ParentColor = False
+    ParentFont = False
+  end
+  object Panel8: TPanel
+    Left = 10
+    Height = 30
+    Top = 470
+    Width = 502
+    AutoSize = True
+    BevelOuter = bvNone
+    ChildSizing.HorizontalSpacing = 20
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 3
+    ClientHeight = 30
+    ClientWidth = 502
+    ParentFont = False
+    TabOrder = 3
+    object BCMDButton30: TBCMDButton
+      Cursor = crHandPoint
+      Left = 0
+      Height = 30
+      Top = 0
+      Width = 84
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Checked = True
+      Kind = mdbkTab
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Option 1'
+      ParentFont = False
+    end
+    object BCMDButton31: TBCMDButton
+      Cursor = crHandPoint
+      Left = 104
+      Height = 30
+      Top = 0
+      Width = 84
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkTab
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Option 2'
+      ParentFont = False
+    end
+    object BCMDButton32: TBCMDButton
+      Cursor = crHandPoint
+      Left = 208
+      Height = 30
+      Top = 0
+      Width = 84
+      Animation = True
+      StyleNormal.Color = 16448250
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkTab
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      Caption = 'Option 3'
+      ParentFont = False
+    end
+  end
+  object Label2: TLabel
+    Cursor = crHelp
+    Left = 10
+    Height = 20
+    Hint = 'Set Animation property to True'
+    Top = 510
+    Width = 502
+    Caption = 'Options'
+    ParentColor = False
+    ParentFont = False
+  end
+  object mdAnimations: TBCMDButton
+    Cursor = crHandPoint
+    Left = 10
+    Height = 30
+    Top = 540
+    Width = 502
+    Animation = True
+    StyleNormal.Color = 16448250
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Checked = True
+    Kind = mdbkCheckBox
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'Enable Animations'
+    OnClick = mdAnimationsClick
+    ParentFont = False
+  end
+end

+ 163 - 0
test/test_materialdesign/mdbutton/umain.pas

@@ -0,0 +1,163 @@
+unit umain;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
+  BCMDButton;
+
+type
+
+  { TfrmMain }
+
+  TfrmMain = class(TForm)
+    Label1: TLabel;
+    Label10: TLabel;
+    Label2: TLabel;
+    Label3: TLabel;
+    Label5: TLabel;
+    Label7: TLabel;
+    Label9: TLabel;
+    BCMDButton1: TBCMDButton;
+    BCMDButton10: TBCMDButton;
+    BCMDButton11: TBCMDButton;
+    BCMDButton15: TBCMDButton;
+    BCMDButton16: TBCMDButton;
+    BCMDButton17: TBCMDButton;
+    BCMDButton2: TBCMDButton;
+    BCMDButton27: TBCMDButton;
+    BCMDButton28: TBCMDButton;
+    BCMDButton29: TBCMDButton;
+    BCMDButton30: TBCMDButton;
+    BCMDButton31: TBCMDButton;
+    BCMDButton32: TBCMDButton;
+    BCMDButton5: TBCMDButton;
+    mdGetRadio: TBCMDButton;
+    mdSelect: TBCMDButton;
+    mdUnselect: TBCMDButton;
+    mdInvert: TBCMDButton;
+    BCMDButton33: TBCMDButton;
+    BCMDButton34: TBCMDButton;
+    BCMDButton35: TBCMDButton;
+    mdAnimations: TBCMDButton;
+    mdGet: TBCMDButton;
+    BCMDButton9: TBCMDButton;
+    Panel1: TPanel;
+    Panel11: TPanel;
+    Panel12: TPanel;
+    Panel13: TPanel;
+    Panel2: TPanel;
+    Panel7: TPanel;
+    Panel8: TPanel;
+    Panel9: TPanel;
+    procedure FormCreate(Sender: TObject);
+    procedure MDButton1Click(Sender: TObject);
+    procedure mdSelectClick(Sender: TObject);
+    procedure mdUnselectClick(Sender: TObject);
+    procedure mdInvertClick(Sender: TObject);
+    procedure mdAnimationsClick(Sender: TObject);
+    procedure mdGetRadioClick(Sender: TObject);
+    procedure mdGetClick(Sender: TObject);
+  private
+    procedure EnableAnimations(Control: TControl);
+    procedure DoubleBuffering(Control: TControl);
+  public
+
+  end;
+
+var
+  frmMain: TfrmMain;
+
+implementation
+
+{$R *.lfm}
+
+{ TfrmMain }
+
+procedure TfrmMain.mdSelectClick(Sender: TObject);
+begin
+  BCMDButton33.SelectAll;
+end;
+
+procedure TfrmMain.MDButton1Click(Sender: TObject);
+begin
+  ShowMessage('Hello World');
+end;
+
+procedure TfrmMain.FormCreate(Sender: TObject);
+begin
+  {$ifdef windows}
+  DoubleBuffering(Self);
+  {$endif}
+end;
+
+procedure TfrmMain.mdUnselectClick(Sender: TObject);
+begin
+  BCMDButton33.UnselectAll;
+end;
+
+procedure TfrmMain.mdInvertClick(Sender: TObject);
+begin
+  BCMDButton33.InvertSelection;
+end;
+
+procedure TfrmMain.mdAnimationsClick(Sender: TObject);
+begin
+  EnableAnimations(Self);
+  // Refresh controls
+  Invalidate;
+end;
+
+procedure TfrmMain.mdGetRadioClick(Sender: TObject);
+begin
+  with BCMDButton27.GetSelected do
+  begin
+    ShowMessage(Text);
+    Free;
+  end;
+end;
+
+procedure TfrmMain.mdGetClick(Sender: TObject);
+begin
+  with BCMDButton33.GetSelected do
+  begin
+    ShowMessage(Text);
+    Free;
+  end;
+end;
+
+procedure TfrmMain.EnableAnimations(Control: TControl);
+var
+  i: integer;
+  wincontrol: TWinControl;
+begin
+  if Control is TBCMDButton then
+    TBCMDButton(Control).Animation := mdAnimations.Checked;
+  if Control is TWinControl then
+  begin
+    wincontrol := TWinControl(Control);
+    if wincontrol.ControlCount > 0 then
+      for i := 0 to wincontrol.ControlCount - 1 do
+        EnableAnimations(wincontrol.Controls[i]);
+  end;
+end;
+
+procedure TfrmMain.DoubleBuffering(Control: TControl);
+var
+  i: integer;
+  wincontrol: TWinControl;
+begin
+  if Control is TWinControl then
+  begin
+    wincontrol := TWinControl(Control);
+    wincontrol.DoubleBuffered := True;
+    if wincontrol.ControlCount > 0 then
+      for i := 0 to wincontrol.ControlCount - 1 do
+        DoubleBuffering(wincontrol.Controls[i]);
+  end;
+end;
+
+end.
+

BIN
test/test_materialdesign/mdbutton_tab/test.ico


+ 132 - 0
test/test_materialdesign/mdbutton_tab/test.lpi

@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="10"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="test"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Icon Value="0"/>
+    </General>
+    <BuildModes Count="2">
+      <Item1 Name="Debug" Default="True"/>
+      <Item2 Name="Release">
+        <CompilerOptions>
+          <Version Value="11"/>
+          <PathDelim Value="\"/>
+          <Target>
+            <Filename Value="test"/>
+          </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>
+        </CompilerOptions>
+      </Item2>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </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="test.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="test"/>
+    </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>
+      <VerifyObjMethodCallValidity Value="True"/>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <DebugInfoType Value="dsDwarf2Set"/>
+        <UseHeaptrc Value="True"/>
+        <TrashVariables Value="True"/>
+        <UseExternalDbgSyms Value="True"/>
+      </Debugging>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 22 - 0
test/test_materialdesign/mdbutton_tab/test.lpr

@@ -0,0 +1,22 @@
+program test;
+
+{$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.Scaled:=True;
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.
+

+ 276 - 0
test/test_materialdesign/mdbutton_tab/umain.lfm

@@ -0,0 +1,276 @@
+object Form1: TForm1
+  Left = 438
+  Height = 400
+  Top = 174
+  Width = 640
+  Caption = 'Tabs'
+  ClientHeight = 400
+  ClientWidth = 640
+  Color = clWhite
+  DesignTimePPI = 120
+  OnCreate = FormCreate
+  Position = poScreenCenter
+  LCLVersion = '1.8.4.0'
+  object PageControl1: TPageControl
+    Left = 10
+    Height = 320
+    Top = 70
+    Width = 620
+    ActivePage = TabSheet1
+    Align = alClient
+    BorderSpacing.Around = 10
+    ShowTabs = False
+    TabIndex = 0
+    TabOrder = 0
+    object TabSheet1: TTabSheet
+      Caption = 'TabSheet1'
+      ClientHeight = 312
+      ClientWidth = 612
+      object BCMDButton4: TBCMDButton
+        Left = 8
+        Height = 30
+        Top = 16
+        Width = 120
+        Animation = True
+        StyleNormal.Color = clWhite
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Change to left'
+        OnClick = BCMDButton4Click
+      end
+      object BCMDButton10: TBCMDButton
+        Left = 8
+        Height = 30
+        Top = 56
+        Width = 121
+        Animation = True
+        StyleNormal.Color = clWhite
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Change to top'
+        OnClick = BCMDButton10Click
+      end
+      object BCMDButton11: TBCMDButton
+        Left = 8
+        Height = 30
+        Top = 96
+        Width = 129
+        Animation = True
+        StyleNormal.Color = clWhite
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Change to right'
+        OnClick = BCMDButton11Click
+      end
+      object BCMDButton12: TBCMDButton
+        Left = 8
+        Height = 30
+        Top = 136
+        Width = 148
+        Animation = True
+        StyleNormal.Color = clWhite
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Change to bottom'
+        OnClick = BCMDButton12Click
+      end
+      object BCMDButton13: TBCMDButton
+        Left = 8
+        Height = 30
+        Top = 176
+        Width = 112
+        Animation = True
+        StyleNormal.Color = clWhite
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        Checked = True
+        Kind = mdbkCheckBox
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Animation'
+        OnClick = BCMDButton13Click
+      end
+    end
+    object TabSheet2: TTabSheet
+      Caption = 'TabSheet2'
+      ClientHeight = 312
+      ClientWidth = 612
+      object BCMDButton5: TBCMDButton
+        Left = 8
+        Height = 30
+        Top = 16
+        Width = 139
+        StyleNormal.Color = clWhite
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Hello from Page 2'
+      end
+    end
+    object TabSheet3: TTabSheet
+      Caption = 'TabSheet3'
+      ClientHeight = 312
+      ClientWidth = 612
+      object BCMDButton6: TBCMDButton
+        Left = 8
+        Height = 30
+        Top = 16
+        Width = 139
+        StyleNormal.Color = clWhite
+        StyleNormal.TextColor = clBlack
+        StyleHover.Color = 14474460
+        StyleHover.TextColor = clBlack
+        StyleActive.Color = 13027014
+        StyleActive.TextColor = clBlack
+        StyleDisabled.Color = clWhite
+        StyleDisabled.TextColor = 10724259
+        TextAutoSize = True
+        TextProportional = False
+        TextProportionalRatio = 0.5
+        AutoSize = True
+        Caption = 'Hello from Page 3'
+      end
+    end
+  end
+  object Panel2: TPanel
+    Left = 10
+    Height = 50
+    Top = 10
+    Width = 620
+    Align = alTop
+    AutoSize = True
+    BorderSpacing.Around = 10
+    BevelOuter = bvNone
+    ChildSizing.Layout = cclLeftToRightThenTopToBottom
+    ChildSizing.ControlsPerLine = 3
+    ClientHeight = 50
+    ClientWidth = 620
+    Color = clWhite
+    ParentColor = False
+    TabOrder = 1
+    object BCMDButton7: TBCMDButton
+      Cursor = crHandPoint
+      Left = 0
+      Height = 50
+      Top = 0
+      Width = 91
+      Animation = True
+      StyleNormal.Color = clWhite
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Checked = True
+      Kind = mdbkTab
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      BorderSpacing.InnerBorder = 20
+      Caption = 'Page 1'
+      OnClick = BCMDButton1Click
+    end
+    object BCMDButton8: TBCMDButton
+      Cursor = crHandPoint
+      Left = 91
+      Height = 50
+      Top = 0
+      Width = 91
+      Animation = True
+      StyleNormal.Color = clWhite
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkTab
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      BorderSpacing.InnerBorder = 20
+      Caption = 'Page 2'
+      OnClick = BCMDButton2Click
+    end
+    object BCMDButton9: TBCMDButton
+      Cursor = crHandPoint
+      Left = 182
+      Height = 50
+      Top = 0
+      Width = 91
+      Animation = True
+      StyleNormal.Color = clWhite
+      StyleNormal.TextColor = clBlack
+      StyleHover.Color = 14474460
+      StyleHover.TextColor = clBlack
+      StyleActive.Color = 13027014
+      StyleActive.TextColor = clBlack
+      StyleDisabled.Color = clWhite
+      StyleDisabled.TextColor = 10724259
+      Kind = mdbkTab
+      TextAutoSize = True
+      TextProportional = False
+      TextProportionalRatio = 0.5
+      AutoSize = True
+      BorderSpacing.InnerBorder = 20
+      Caption = 'Page 3'
+      OnClick = BCMDButton3Click
+    end
+  end
+end

+ 105 - 0
test/test_materialdesign/mdbutton_tab/umain.pas

@@ -0,0 +1,105 @@
+unit umain;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, ComCtrls,
+  BCMDButton;
+
+type
+
+  { TForm1 }
+
+  TForm1 = class(TForm)
+    BCMDButton10: TBCMDButton;
+    BCMDButton11: TBCMDButton;
+    BCMDButton12: TBCMDButton;
+    BCMDButton13: TBCMDButton;
+    BCMDButton4: TBCMDButton;
+    BCMDButton5: TBCMDButton;
+    BCMDButton6: TBCMDButton;
+    BCMDButton7: TBCMDButton;
+    BCMDButton8: TBCMDButton;
+    BCMDButton9: TBCMDButton;
+    PageControl1: TPageControl;
+    Panel2: TPanel;
+    TabSheet1: TTabSheet;
+    TabSheet2: TTabSheet;
+    TabSheet3: TTabSheet;
+    procedure FormCreate(Sender: TObject);
+    procedure BCMDButton10Click(Sender: TObject);
+    procedure BCMDButton11Click(Sender: TObject);
+    procedure BCMDButton12Click(Sender: TObject);
+    procedure BCMDButton13Click(Sender: TObject);
+    procedure BCMDButton1Click(Sender: TObject);
+    procedure BCMDButton2Click(Sender: TObject);
+    procedure BCMDButton3Click(Sender: TObject);
+    procedure BCMDButton4Click(Sender: TObject);
+  private
+
+  public
+
+  end;
+
+var
+  Form1: TForm1;
+
+implementation
+
+{$R *.lfm}
+
+{ TForm1 }
+
+procedure TForm1.BCMDButton1Click(Sender: TObject);
+begin
+  PageControl1.ActivePageIndex := 0;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+  PageControl1.ActivePageIndex := 0;
+end;
+
+procedure TForm1.BCMDButton10Click(Sender: TObject);
+begin
+  Panel2.ChildSizing.Layout := cclLeftToRightThenTopToBottom;
+  Panel2.Align := alTop;
+end;
+
+procedure TForm1.BCMDButton11Click(Sender: TObject);
+begin
+  Panel2.ChildSizing.Layout := cclTopToBottomThenLeftToRight;
+  Panel2.Align := alRight;
+end;
+
+procedure TForm1.BCMDButton12Click(Sender: TObject);
+begin
+  Panel2.ChildSizing.Layout := cclLeftToRightThenTopToBottom;
+  Panel2.Align := alBottom;
+end;
+
+procedure TForm1.BCMDButton13Click(Sender: TObject);
+begin
+  BCMDBUTTONANIMATION := BCMDButton13.Checked;
+end;
+
+procedure TForm1.BCMDButton2Click(Sender: TObject);
+begin
+  PageControl1.ActivePageIndex := 1;
+end;
+
+procedure TForm1.BCMDButton3Click(Sender: TObject);
+begin
+  PageControl1.ActivePageIndex := 2;
+end;
+
+procedure TForm1.BCMDButton4Click(Sender: TObject);
+begin
+  Panel2.ChildSizing.Layout := cclTopToBottomThenLeftToRight;
+  Panel2.Align := alLeft;
+end;
+
+end.
+

BIN
test/test_materialdesign/mdbuttonfocus/test.ico


+ 82 - 0
test/test_materialdesign/mdbuttonfocus/test.lpi

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="10"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="test"/>
+      <Scaled Value="True"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <XPManifest>
+        <DpiAware Value="True"/>
+      </XPManifest>
+      <Icon Value="0"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </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="test.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="umain.pas"/>
+        <IsPartOfProject Value="True"/>
+        <ComponentName Value="Form1"/>
+        <HasResources Value="True"/>
+        <ResourceBaseClass Value="Form"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="test"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 22 - 0
test/test_materialdesign/mdbuttonfocus/test.lpr

@@ -0,0 +1,22 @@
+program test;
+
+{$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.Scaled:=True;
+  Application.Initialize;
+  Application.CreateForm(TForm1, Form1);
+  Application.Run;
+end.
+

+ 296 - 0
test/test_materialdesign/mdbuttonfocus/umain.lfm

@@ -0,0 +1,296 @@
+object Form1: TForm1
+  Left = 321
+  Height = 391
+  Top = 123
+  Width = 645
+  Caption = 'Material Design Button with Focus'
+  ClientHeight = 391
+  ClientWidth = 645
+  DesignTimePPI = 120
+  OnCreate = FormCreate
+  LCLVersion = '1.8.4.0'
+  object BCMDButtonFocus1: TBCMDButtonFocus
+    Left = 10
+    Height = 30
+    Top = 10
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus1'
+    ParentFont = False
+  end
+  object BCMDButtonFocus2: TBCMDButtonFocus
+    Left = 10
+    Height = 30
+    Top = 60
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus2'
+    ParentFont = False
+  end
+  object BCMDButtonFocus3: TBCMDButtonFocus
+    Left = 170
+    Height = 30
+    Top = 10
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkCheckBox
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus3'
+    ParentFont = False
+  end
+  object BCMDButtonFocus4: TBCMDButtonFocus
+    Left = 170
+    Height = 30
+    Top = 60
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkCheckBox
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus4'
+    ParentFont = False
+  end
+  object BCMDButtonFocus5: TBCMDButtonFocus
+    Left = 10
+    Height = 30
+    Top = 110
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkRadioButton
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus5'
+    ParentFont = False
+  end
+  object BCMDButtonFocus6: TBCMDButtonFocus
+    Left = 10
+    Height = 30
+    Top = 160
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkRadioButton
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus6'
+    ParentFont = False
+  end
+  object BCMDButtonFocus7: TBCMDButtonFocus
+    Left = 170
+    Height = 30
+    Top = 110
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkTab
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus7'
+    ParentFont = False
+  end
+  object BCMDButtonFocus8: TBCMDButtonFocus
+    Left = 170
+    Height = 30
+    Top = 160
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkTab
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus8'
+    ParentFont = False
+  end
+  object BCMDButtonFocus9: TBCMDButtonFocus
+    Left = 10
+    Height = 30
+    Top = 210
+    Width = 157
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkToggle
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus9'
+    ParentFont = False
+  end
+  object BCMDButtonFocus10: TBCMDButtonFocus
+    Left = 10
+    Height = 30
+    Top = 260
+    Width = 165
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkToggle
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus10'
+    ParentFont = False
+  end
+  object BCMDButtonFocus11: TBCMDButtonFocus
+    Left = 170
+    Height = 30
+    Top = 210
+    Width = 165
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkToggleGroup
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus11'
+    ParentFont = False
+  end
+  object BCMDButtonFocus12: TBCMDButtonFocus
+    Left = 170
+    Height = 30
+    Top = 260
+    Width = 165
+    Animation = True
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Kind = mdbkToggleGroup
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    AutoSize = True
+    Caption = 'BCMDButtonFocus12'
+    ParentFont = False
+  end
+  object BCMDButton1: TBCMDButton
+    Left = 460
+    Height = 31
+    Top = 10
+    Width = 174
+    StyleNormal.Color = clWhite
+    StyleNormal.TextColor = clBlack
+    StyleHover.Color = 14474460
+    StyleHover.TextColor = clBlack
+    StyleActive.Color = 13027014
+    StyleActive.TextColor = clBlack
+    StyleDisabled.Color = clWhite
+    StyleDisabled.TextColor = 10724259
+    Checked = True
+    Kind = mdbkCheckBox
+    TextAutoSize = True
+    TextProportional = False
+    TextProportionalRatio = 0.5
+    Caption = 'Animation'
+    OnClick = BCMDButton1Click
+    ParentFont = False
+  end
+end

+ 57 - 0
test/test_materialdesign/mdbuttonfocus/umain.pas

@@ -0,0 +1,57 @@
+unit umain;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, BCMDButtonFocus,
+  BCMDButton;
+
+type
+
+  { TForm1 }
+
+  TForm1 = class(TForm)
+    BCMDButton1: TBCMDButton;
+    BCMDButtonFocus1: TBCMDButtonFocus;
+    BCMDButtonFocus10: TBCMDButtonFocus;
+    BCMDButtonFocus11: TBCMDButtonFocus;
+    BCMDButtonFocus12: TBCMDButtonFocus;
+    BCMDButtonFocus2: TBCMDButtonFocus;
+    BCMDButtonFocus3: TBCMDButtonFocus;
+    BCMDButtonFocus4: TBCMDButtonFocus;
+    BCMDButtonFocus5: TBCMDButtonFocus;
+    BCMDButtonFocus6: TBCMDButtonFocus;
+    BCMDButtonFocus7: TBCMDButtonFocus;
+    BCMDButtonFocus8: TBCMDButtonFocus;
+    BCMDButtonFocus9: TBCMDButtonFocus;
+    procedure FormCreate(Sender: TObject);
+    procedure BCMDButton1Click(Sender: TObject);
+  private
+
+  public
+
+  end;
+
+var
+  Form1: TForm1;
+
+implementation
+
+{$R *.lfm}
+
+{ TForm1 }
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+  DoubleBuffered := True;
+end;
+
+procedure TForm1.BCMDButton1Click(Sender: TObject);
+begin
+  BCMDBUTTONANIMATION := BCMDButton1.Checked;
+end;
+
+end.
+

+ 2 - 2
update_bgracontrols_force.json

@@ -6,9 +6,9 @@
   "UpdatePackageFiles" : [
     {
       "ForceNotify" : true,
-      "InternalVersion" : 14,
+      "InternalVersion" : 15,
       "Name" : "bgracontrols.lpk",
-      "Version" : "4.6.2.0"
+      "Version" : "5.0.0.0"
     },
     {
       "ForceNotify" : false,