|
@@ -2,11 +2,15 @@ unit ColorSpeedButton;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
|
{$mode objfpc}{$H+}
|
|
|
|
|
|
|
|
|
|
+{$ifdef windows}
|
|
|
|
|
+{$define overridepaint}
|
|
|
|
|
+{$endif}
|
|
|
|
|
+
|
|
|
interface
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
uses
|
|
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
|
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
|
|
|
- Buttons, BGRASpeedButton;
|
|
|
|
|
|
|
+ Buttons, BGRASpeedButton, Types, LCLType, Themes, Math, LCLProc;
|
|
|
|
|
|
|
|
type
|
|
type
|
|
|
|
|
|
|
@@ -44,6 +48,11 @@ type
|
|
|
procedure SetFStateHover(AValue: TColorState);
|
|
procedure SetFStateHover(AValue: TColorState);
|
|
|
procedure SetFStateNormal(AValue: TColorState);
|
|
procedure SetFStateNormal(AValue: TColorState);
|
|
|
protected
|
|
protected
|
|
|
|
|
+ {$ifdef overridepaint}
|
|
|
|
|
+ procedure MeasureDraw(Draw: boolean; PaintRect: TRect;
|
|
|
|
|
+ out PreferredWidth, PreferredHeight: integer);
|
|
|
|
|
+ procedure Paint; override;
|
|
|
|
|
+ {$endif}
|
|
|
procedure PaintBackground(var PaintRect: TRect); override;
|
|
procedure PaintBackground(var PaintRect: TRect); override;
|
|
|
public
|
|
public
|
|
|
constructor Create(TheOwner: TComponent); override;
|
|
constructor Create(TheOwner: TComponent); override;
|
|
@@ -107,6 +116,227 @@ begin
|
|
|
Invalidate;
|
|
Invalidate;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
+{$ifdef overridepaint}
|
|
|
|
|
+procedure TColorSpeedButton.MeasureDraw(Draw: boolean; PaintRect: TRect; out
|
|
|
|
|
+ PreferredWidth, PreferredHeight: integer);
|
|
|
|
|
+var
|
|
|
|
|
+ GlyphWidth, GlyphHeight: Integer;
|
|
|
|
|
+ Offset, OffsetCap: TPoint;
|
|
|
|
|
+ ClientSize, TotalSize, TextSize, GlyphSize: TSize;
|
|
|
|
|
+ M, S : integer;
|
|
|
|
|
+ SIndex : Longint;
|
|
|
|
|
+ TMP : String;
|
|
|
|
|
+ TextFlags: Integer;
|
|
|
|
|
+ DrawDetails: TThemedElementDetails;
|
|
|
|
|
+ FixedWidth: Boolean;
|
|
|
|
|
+ FixedHeight: Boolean;
|
|
|
|
|
+ TextRect: TRect;
|
|
|
|
|
+ HasGlyph: Boolean;
|
|
|
|
|
+ HasText: Boolean;
|
|
|
|
|
+ CurLayout: TButtonLayout;
|
|
|
|
|
+begin
|
|
|
|
|
+ if Glyph = nil then exit;
|
|
|
|
|
+
|
|
|
|
|
+ DrawDetails := GetDrawDetails;
|
|
|
|
|
+
|
|
|
|
|
+ PreferredWidth:=0;
|
|
|
|
|
+ PreferredHeight:=0;
|
|
|
|
|
+
|
|
|
|
|
+ if Draw then begin
|
|
|
|
|
+ //FLastDrawDetails:=DrawDetails;
|
|
|
|
|
+ PaintBackground(PaintRect);
|
|
|
|
|
+ FixedWidth:=true;
|
|
|
|
|
+ FixedHeight:=true;
|
|
|
|
|
+ end else begin
|
|
|
|
|
+ FixedWidth:=WidthIsAnchored;
|
|
|
|
|
+ FixedHeight:=HeightIsAnchored;
|
|
|
|
|
+ end;
|
|
|
|
|
+ ClientSize.cx:= PaintRect.Right - PaintRect.Left;
|
|
|
|
|
+ ClientSize.cy:= PaintRect.Bottom - PaintRect.Top;
|
|
|
|
|
+ //debugln(['TCustomSpeedButton.MeasureDraw Step1 ',DbgSName(Self),' PaintRect=',dbgs(PaintRect)]);
|
|
|
|
|
+ // compute size of glyph
|
|
|
|
|
+ GlyphSize := GetGlyphSize(Draw,PaintRect);
|
|
|
|
|
+ GlyphWidth := GlyphSize.CX;
|
|
|
|
|
+ if TButtonGlyph(Glyph).NumGlyphs > 1 then
|
|
|
|
|
+ GlyphWidth:=GlyphWidth div NumGlyphs;
|
|
|
|
|
+ GlyphHeight := GlyphSize.CY;
|
|
|
|
|
+ HasGlyph:=(GlyphWidth<>0) and (GlyphHeight<>0);
|
|
|
|
|
+ //debugln(['TCustomSpeedButton.MeasureDraw Step2 ',DbgSName(Self),' PaintRect=',dbgs(PaintRect),' GlyphSize=',GlyphWidth,'x',GlyphHeight]);
|
|
|
|
|
+
|
|
|
|
|
+ // compute size of text
|
|
|
|
|
+ CurLayout:=BidiAdjustButtonLayout(UseRightToLeftReading, Layout);
|
|
|
|
|
+ if ShowCaption and (Caption<>'') then begin
|
|
|
|
|
+ TextRect:=PaintRect;
|
|
|
|
|
+ // for wordbreak compute the maximum size for the text
|
|
|
|
|
+ if Margin>0 then
|
|
|
|
|
+ InflateRect(TextRect,-Margin,-Margin);
|
|
|
|
|
+ if HasGlyph then
|
|
|
|
|
+ begin
|
|
|
|
|
+ if (Spacing>=0) then
|
|
|
|
|
+ if CurLayout in [blGlyphLeft,blGlyphRight] then
|
|
|
|
|
+ dec(TextRect.Right,Spacing)
|
|
|
|
|
+ else
|
|
|
|
|
+ dec(TextRect.Bottom,Spacing);
|
|
|
|
|
+ if CurLayout in [blGlyphLeft,blGlyphRight] then
|
|
|
|
|
+ dec(TextRect.Right,GlyphWidth)
|
|
|
|
|
+ else
|
|
|
|
|
+ dec(TextRect.Bottom,GlyphHeight);
|
|
|
|
|
+ end;
|
|
|
|
|
+ if not FixedWidth then
|
|
|
|
|
+ begin
|
|
|
|
|
+ TextRect.Left:=0;
|
|
|
|
|
+ TextRect.Right:=High(TextRect.Right) div 2;
|
|
|
|
|
+ end;
|
|
|
|
|
+ if not FixedHeight then
|
|
|
|
|
+ begin
|
|
|
|
|
+ TextRect.Top:=0;
|
|
|
|
|
+ TextRect.Bottom:=High(TextRect.Bottom) div 2;
|
|
|
|
|
+ end;
|
|
|
|
|
+ TextSize := GetTextSize(Draw,TextRect);
|
|
|
|
|
+ end else begin
|
|
|
|
|
+ TextSize.cx:=0;
|
|
|
|
|
+ TextSize.cy:=0;
|
|
|
|
|
+ end;
|
|
|
|
|
+ HasText:=(TextSize.cx <> 0) or (TextSize.cy <> 0);
|
|
|
|
|
+
|
|
|
|
|
+ if Caption <> '' then
|
|
|
|
|
+ begin
|
|
|
|
|
+ TMP := Caption;
|
|
|
|
|
+ SIndex := DeleteAmpersands(TMP);
|
|
|
|
|
+ If SIndex > 0 then
|
|
|
|
|
+ If SIndex <= Length(TMP) then begin
|
|
|
|
|
+ //FShortcut := Ord(TMP[SIndex]);
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ if HasGlyph and HasText then
|
|
|
|
|
+ S:= Spacing
|
|
|
|
|
+ else
|
|
|
|
|
+ S:= 0;
|
|
|
|
|
+ M:=Margin;
|
|
|
|
|
+ if not Draw then
|
|
|
|
|
+ begin
|
|
|
|
|
+ if M<0 then M:=2;
|
|
|
|
|
+ if S<0 then S:=M;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate caption and glyph layout
|
|
|
|
|
+ if M = -1 then begin
|
|
|
|
|
+ // auto compute margin to center content
|
|
|
|
|
+ if S = -1 then begin
|
|
|
|
|
+ // use the same value for Spacing and Margin
|
|
|
|
|
+ TotalSize.cx:= TextSize.cx + GlyphWidth;
|
|
|
|
|
+ TotalSize.cy:= TextSize.cy + GlyphHeight;
|
|
|
|
|
+ if Layout in [blGlyphLeft, blGlyphRight] then
|
|
|
|
|
+ M:= (ClientSize.cx - TotalSize.cx) div 3
|
|
|
|
|
+ else
|
|
|
|
|
+ M:= (ClientSize.cy - TotalSize.cy) div 3;
|
|
|
|
|
+ S:= M;
|
|
|
|
|
+ end else begin
|
|
|
|
|
+ // fixed Spacing and center content
|
|
|
|
|
+ TotalSize.cx:= GlyphWidth + S + TextSize.cx;
|
|
|
|
|
+ TotalSize.cy:= GlyphHeight + S + TextSize.cy;
|
|
|
|
|
+ if Layout in [blGlyphLeft, blGlyphRight] then
|
|
|
|
|
+ M:= (ClientSize.cx - TotalSize.cx) div 2
|
|
|
|
|
+ else
|
|
|
|
|
+ M:= (ClientSize.cy - TotalSize.cy) div 2;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end else begin
|
|
|
|
|
+ // fixed Margin
|
|
|
|
|
+ if S = -1 then begin
|
|
|
|
|
+ // use the rest for Spacing between Glyph and Caption
|
|
|
|
|
+ TotalSize.cx:= ClientSize.cx - (Margin + GlyphWidth);
|
|
|
|
|
+ TotalSize.cy:= ClientSize.cy - (Margin + GlyphHeight);
|
|
|
|
|
+ if Layout in [blGlyphLeft, blGlyphRight] then
|
|
|
|
|
+ S:= (TotalSize.cx - TextSize.cx) div 2
|
|
|
|
|
+ else
|
|
|
|
|
+ S:= (TotalSize.cy - TextSize.cy) div 2;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ //debugln(['TCustomSpeedButton.MeasureDraw Step3 ',DbgSName(Self),' PaintRect=',dbgs(PaintRect),' GlyphSize=',GlyphWidth,'x',GlyphHeight,' TextSize=',TextSize.cx,'x',TextSize.cy,' S=',S,' M=',M]);
|
|
|
|
|
+
|
|
|
|
|
+ if Draw then
|
|
|
|
|
+ begin
|
|
|
|
|
+ case CurLayout of
|
|
|
|
|
+ blGlyphLeft : begin
|
|
|
|
|
+ Offset.X:= M;
|
|
|
|
|
+ Offset.Y:= (ClientSize.cy - GlyphHeight) div 2;
|
|
|
|
|
+ OffsetCap.X:= Offset.X + GlyphWidth + S;
|
|
|
|
|
+ OffsetCap.Y:= (ClientSize.cy - TextSize.cy) div 2;
|
|
|
|
|
+ end;
|
|
|
|
|
+ blGlyphRight : begin
|
|
|
|
|
+ Offset.X:= ClientSize.cx - M - GlyphWidth;
|
|
|
|
|
+ Offset.Y:= (ClientSize.cy - GlyphHeight) div 2;
|
|
|
|
|
+ OffsetCap.X:= Offset.X - S - TextSize.cx;
|
|
|
|
|
+ OffsetCap.Y:= (ClientSize.cy - TextSize.cy) div 2;
|
|
|
|
|
+ end;
|
|
|
|
|
+ blGlyphTop : begin
|
|
|
|
|
+ Offset.X:= (ClientSize.cx - GlyphWidth) div 2;
|
|
|
|
|
+ Offset.Y:= M;
|
|
|
|
|
+ OffsetCap.X:= (ClientSize.cx - TextSize.cx) div 2;
|
|
|
|
|
+ OffsetCap.Y:= Offset.Y + GlyphHeight + S;
|
|
|
|
|
+ end;
|
|
|
|
|
+ blGlyphBottom : begin
|
|
|
|
|
+ Offset.X:= (ClientSize.cx - GlyphWidth) div 2;
|
|
|
|
|
+ Offset.Y:= ClientSize.cy - M - GlyphHeight;
|
|
|
|
|
+ OffsetCap.X:= (ClientSize.cx - TextSize.cx) div 2;
|
|
|
|
|
+ OffsetCap.Y:= Offset.Y - S - TextSize.cy;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ DrawGlyph(Canvas, PaintRect, Offset, FState, Transparent, 0);
|
|
|
|
|
+
|
|
|
|
|
+ if ShowCaption and (Caption <> '') then
|
|
|
|
|
+ begin
|
|
|
|
|
+ with PaintRect, OffsetCap do
|
|
|
|
|
+ begin
|
|
|
|
|
+ Left := Left + X;
|
|
|
|
|
+ Top := Top + Y;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ TextFlags := DT_LEFT or DT_TOP;
|
|
|
|
|
+ if UseRightToLeftReading then
|
|
|
|
|
+ TextFlags := TextFlags or DT_RTLREADING;
|
|
|
|
|
+
|
|
|
|
|
+ if Draw then
|
|
|
|
|
+ Canvas.TextRect(PaintRect, PaintRect.Left, PaintRect.Top, Caption);
|
|
|
|
|
+ {ThemeServices.DrawText(Canvas, DrawDetails, Caption, PaintRect,
|
|
|
|
|
+ TextFlags, 0);}
|
|
|
|
|
+ end;
|
|
|
|
|
+ end else begin
|
|
|
|
|
+ // measuring, not drawing
|
|
|
|
|
+ case CurLayout of
|
|
|
|
|
+ blGlyphLeft, blGlyphRight :
|
|
|
|
|
+ begin
|
|
|
|
|
+ PreferredWidth:=2*M+S+GlyphWidth+TextSize.cx;
|
|
|
|
|
+ PreferredHeight:=2*M+Max(GlyphHeight,TextSize.cy);
|
|
|
|
|
+ end;
|
|
|
|
|
+ blGlyphTop, blGlyphBottom :
|
|
|
|
|
+ begin
|
|
|
|
|
+ PreferredWidth:=2*M+Max(GlyphWidth,TextSize.cx);
|
|
|
|
|
+ PreferredHeight:=2*M+S+GlyphHeight+TextSize.cy;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TColorSpeedButton.Paint;
|
|
|
|
|
+var
|
|
|
|
|
+ PaintRect: TRect;
|
|
|
|
|
+ PreferredWidth: integer;
|
|
|
|
|
+ PreferredHeight: integer;
|
|
|
|
|
+begin
|
|
|
|
|
+ UpdateState(false);
|
|
|
|
|
+ if Glyph = nil then exit;
|
|
|
|
|
+
|
|
|
|
|
+ PaintRect:=ClientRect;
|
|
|
|
|
+ MeasureDraw(true,PaintRect,PreferredWidth,PreferredHeight);
|
|
|
|
|
+
|
|
|
|
|
+ //inherited Paint;
|
|
|
|
|
+end;
|
|
|
|
|
+{$endif}
|
|
|
|
|
+
|
|
|
procedure TColorSpeedButton.PaintBackground(var PaintRect: TRect);
|
|
procedure TColorSpeedButton.PaintBackground(var PaintRect: TRect);
|
|
|
begin
|
|
begin
|
|
|
case FState of
|
|
case FState of
|
|
@@ -156,6 +386,7 @@ begin
|
|
|
FStateActive.BorderColor := RGBToColor(0, 84, 153);
|
|
FStateActive.BorderColor := RGBToColor(0, 84, 153);
|
|
|
FStateDisabled.Color := RGBToColor(204, 204, 204);
|
|
FStateDisabled.Color := RGBToColor(204, 204, 204);
|
|
|
FStateDisabled.Color := RGBToColor(191, 191, 191);
|
|
FStateDisabled.Color := RGBToColor(191, 191, 191);
|
|
|
|
|
+ Font.Color := clBlack;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
destructor TColorSpeedButton.Destroy;
|
|
destructor TColorSpeedButton.Destroy;
|
|
@@ -174,7 +405,7 @@ begin
|
|
|
if PopupMode then
|
|
if PopupMode then
|
|
|
begin
|
|
begin
|
|
|
p := Parent.ClientToScreen(Point(Left, Top));
|
|
p := Parent.ClientToScreen(Point(Left, Top));
|
|
|
- PopupMenu.PopUp(p.x, p.y+Height);
|
|
|
|
|
|
|
+ PopupMenu.PopUp(p.x, p.y + Height);
|
|
|
end;
|
|
end;
|
|
|
inherited Click;
|
|
inherited Click;
|
|
|
end;
|
|
end;
|