mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
309 lines
8.1 KiB
ObjectPascal
309 lines
8.1 KiB
ObjectPascal
{
|
|
Double Commander
|
|
-------------------------------------------------------------------------
|
|
Control like TButton which does not steal focus on click
|
|
|
|
Copyright (C) 2021-2023 Alexander Koblov (alexx2000@mail.ru)
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
}
|
|
|
|
unit KASButton;
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
|
|
Buttons, Themes, Types;
|
|
|
|
type
|
|
|
|
{ TKASButton }
|
|
|
|
TKASButton = class(TPanel)
|
|
private
|
|
FState: TButtonState;
|
|
FShowCaption: Boolean;
|
|
FButtonGlyph: TButtonGlyph;
|
|
function GetGlyph: TBitmap;
|
|
function IsGlyphStored: Boolean;
|
|
procedure SetGlyph(AValue: TBitmap);
|
|
procedure SetShowCaption(AValue: Boolean);
|
|
function GetDrawDetails: TThemedElementDetails;
|
|
protected
|
|
procedure Paint; override;
|
|
procedure DoExit; override;
|
|
procedure DoEnter; override;
|
|
procedure MouseEnter; override;
|
|
procedure MouseLeave; override;
|
|
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
protected
|
|
procedure GlyphChanged(Sender: TObject);
|
|
class function GetControlClassDefaultSize: TSize; override;
|
|
procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override;
|
|
procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; WithThemeSpace: Boolean); override;
|
|
public
|
|
constructor Create(TheOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
published
|
|
property Action;
|
|
property Glyph: TBitmap read GetGlyph write SetGlyph stored IsGlyphStored;
|
|
property ShowCaption: Boolean read FShowCaption write SetShowCaption default True;
|
|
end;
|
|
|
|
procedure Register;
|
|
|
|
implementation
|
|
|
|
uses
|
|
LCLType, LCLProc, LCLIntf, ActnList;
|
|
|
|
procedure Register;
|
|
begin
|
|
RegisterComponents('KASComponents',[TKASButton]);
|
|
end;
|
|
|
|
{ TKASButton }
|
|
|
|
procedure TKASButton.DoEnter;
|
|
begin
|
|
inherited DoEnter;
|
|
FState:= bsExclusive;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TKASButton.DoExit;
|
|
begin
|
|
inherited DoExit;
|
|
FState:= bsUp;
|
|
Invalidate;
|
|
end;
|
|
|
|
function TKASButton.GetDrawDetails: TThemedElementDetails;
|
|
var
|
|
Detail: TThemedButton;
|
|
begin
|
|
if not IsEnabled then
|
|
Detail := tbPushButtonDisabled
|
|
else if FState = bsDown then
|
|
Detail := tbPushButtonPressed
|
|
else if FState = bsHot then
|
|
Detail := tbPushButtonHot
|
|
else if FState = bsExclusive then
|
|
Detail := tbPushButtonDefaulted
|
|
else begin
|
|
Detail := tbPushButtonNormal;
|
|
end;
|
|
Result := ThemeServices.GetElementDetails(Detail)
|
|
end;
|
|
|
|
procedure TKASButton.SetShowCaption(AValue: Boolean);
|
|
begin
|
|
if FShowCaption = AValue then Exit;
|
|
FShowCaption:= AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
function TKASButton.GetGlyph: TBitmap;
|
|
begin
|
|
Result:= FButtonGlyph.Glyph;
|
|
end;
|
|
|
|
function TKASButton.IsGlyphStored: Boolean;
|
|
var
|
|
Act: TCustomAction;
|
|
begin
|
|
if Action <> nil then
|
|
begin
|
|
Result:= True;
|
|
Act:= TCustomAction(Action);
|
|
if (Act.ActionList <> nil) and (Act.ActionList.Images <> nil) and
|
|
(Act.ImageIndex >= 0) and (Act.ImageIndex < Act.ActionList.Images.Count) then
|
|
Result := False;
|
|
end
|
|
else Result:= (FButtonGlyph.Glyph <> nil) and (not FButtonGlyph.Glyph.Empty) and
|
|
(FButtonGlyph.Glyph.Width > 0) and (FButtonGlyph.Glyph.Height > 0);
|
|
end;
|
|
|
|
procedure TKASButton.SetGlyph(AValue: TBitmap);
|
|
begin
|
|
FButtonGlyph.Glyph := AValue;
|
|
InvalidatePreferredSize;
|
|
AdjustSize;
|
|
end;
|
|
|
|
procedure TKASButton.Paint;
|
|
var
|
|
APoint: TPoint;
|
|
SysFont: TFont;
|
|
PaintRect: TRect;
|
|
TextFlags: Integer;
|
|
Details: TThemedElementDetails;
|
|
begin
|
|
PaintRect:= ClientRect;
|
|
Details:= GetDrawDetails;
|
|
ThemeServices.DrawElement(Canvas.Handle, Details, PaintRect);
|
|
PaintRect := ThemeServices.ContentRect(Canvas.Handle, Details, PaintRect);
|
|
|
|
if FShowCaption and (Caption <> EmptyStr) then
|
|
begin
|
|
TextFlags := DT_CENTER or DT_VCENTER;
|
|
if UseRightToLeftReading then begin
|
|
TextFlags := TextFlags or DT_RTLREADING;
|
|
end;
|
|
|
|
SysFont := Screen.SystemFont;
|
|
|
|
if (SysFont.Color = Font.Color) and
|
|
((SysFont.Name = Font.Name) or IsFontNameDefault(Font.Name)) and
|
|
(SysFont.Pitch = Font.Pitch) and (SysFont.Style = Font.Style) then
|
|
begin
|
|
ThemeServices.DrawText(Canvas, Details, Caption, PaintRect, TextFlags, 0);
|
|
end
|
|
else begin
|
|
Canvas.Brush.Style := bsClear;
|
|
DrawText(Canvas.Handle, PChar(Caption), Length(Caption), PaintRect, TextFlags);
|
|
end;
|
|
end
|
|
else if not FButtonGlyph.Glyph.Empty then
|
|
begin
|
|
APoint.X:= (PaintRect.Width - FButtonGlyph.Width) div 2;
|
|
APoint.Y:= (PaintRect.Height - FButtonGlyph.Height) div 2;
|
|
FButtonGlyph.Draw(Canvas, PaintRect, APoint, FState, True, 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TKASButton.MouseEnter;
|
|
begin
|
|
inherited MouseEnter;
|
|
FState:= bsHot;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TKASButton.MouseLeave;
|
|
begin
|
|
inherited MouseLeave;
|
|
FState:= bsUp;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TKASButton.KeyUp(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
inherited KeyUp(Key, Shift);
|
|
if (Key in [VK_SPACE, VK_RETURN]) and (Shift = []) then
|
|
begin
|
|
FState:= bsUp;
|
|
Invalidate;
|
|
Click;
|
|
end;
|
|
end;
|
|
|
|
procedure TKASButton.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
if (Key in [VK_SPACE, VK_RETURN]) and (Shift = []) then
|
|
begin
|
|
FState:= bsDown;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TKASButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
|
|
Y: Integer);
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
FState:= bsUp;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TKASButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
FState:= bsDown;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TKASButton.GlyphChanged(Sender: TObject);
|
|
begin
|
|
InvalidatePreferredSize;
|
|
AdjustSize;
|
|
end;
|
|
|
|
class function TKASButton.GetControlClassDefaultSize: TSize;
|
|
begin
|
|
Result.CX := 23;
|
|
Result.CY := 22;
|
|
end;
|
|
|
|
procedure TKASButton.ActionChange(Sender: TObject; CheckDefaults: Boolean);
|
|
begin
|
|
inherited ActionChange(Sender, CheckDefaults);
|
|
|
|
if Sender is TCustomAction then
|
|
begin
|
|
with TCustomAction(Sender) do
|
|
begin
|
|
if (Glyph.Empty) and (ActionList <> nil) and (ActionList.Images <> nil) and
|
|
(ImageIndex >= 0) and (ImageIndex < ActionList.Images.Count) then
|
|
ActionList.Images.GetBitmap(ImageIndex, Glyph);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TKASButton.CalculatePreferredSize(var PreferredWidth,
|
|
PreferredHeight: Integer; WithThemeSpace: Boolean);
|
|
var
|
|
PaintRect: TRect;
|
|
ClientRect: TRect;
|
|
Details: TThemedElementDetails;
|
|
begin
|
|
inherited CalculatePreferredSize(PreferredWidth, PreferredHeight, WithThemeSpace);
|
|
|
|
if (not FButtonGlyph.Glyph.Empty) then
|
|
begin
|
|
Details:= GetDrawDetails;
|
|
PaintRect:= TRect.Create(0, 0, 32, 32);
|
|
ClientRect:= ThemeServices.ContentRect(Canvas.Handle, Details, PaintRect);
|
|
|
|
PreferredWidth:= Abs(PaintRect.Width - ClientRect.Width) + FButtonGlyph.Width;
|
|
PreferredHeight:= Abs(PaintRect.Height - ClientRect.Height) + FButtonGlyph.Height;
|
|
end;
|
|
end;
|
|
|
|
constructor TKASButton.Create(TheOwner: TComponent);
|
|
begin
|
|
inherited Create(TheOwner);
|
|
|
|
FButtonGlyph := TButtonGlyph.Create;
|
|
FButtonGlyph.NumGlyphs := 1;
|
|
FButtonGlyph.OnChange := GlyphChanged;
|
|
FButtonGlyph.IsDesigning := csDesigning in ComponentState;
|
|
|
|
FShowCaption:= True;
|
|
TabStop:= True;
|
|
end;
|
|
|
|
destructor TKASButton.Destroy;
|
|
begin
|
|
FreeAndNil(FButtonGlyph);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
end.
|