// SPDX-License-Identifier: LGPL-3.0-linking-exception { Equivalent of standard lazarus TLabel but using BGRA Controls framework for text render. Functionality: - Customizable background (gradients etc.) - Customizable border (rounding etc.) - FontEx (shadow, word wrap, etc.) originally written in 2012 by Krzysztof Dibowski dibowski at interia.pl } {******************************* CONTRIBUTOR(S) ****************************** - Edivando S. Santos Brasil | mailedivando@gmail.com (Compatibility with delphi VCL 11/2018) ***************************** END CONTRIBUTOR(S) *****************************} unit BCLabel; {$I bgracontrols.inc} interface uses Classes, SysUtils,{$IFDEF FPC}LResources,{$ENDIF} types, Forms, Controls, Graphics, Dialogs, BCBasectrls, BGRABitmap, BGRABitmapTypes, BCTypes; type { TCustomBCLabel } TCustomBCLabel = class(TBCStyleGraphicControl) private { Private declarations } {$IFDEF INDEBUG} FRenderCount: Integer; {$ENDIF} FBackground: TBCBackground; FBGRA: TBGRABitmapEx; FBorder: TBCBorder; FFontEx: TBCFont; FInnerMargin: single; FRounding: TBCRounding; procedure Render; procedure SetInnerMargin(AValue: single); procedure SetRounding(AValue: TBCRounding); procedure UpdateSize; procedure SetBackground(AValue: TBCBackground); procedure SetBorder(AValue: TBCBorder); procedure SetFontEx(AValue: TBCFont); procedure OnChangeProperty(Sender: TObject; {%H-}Data: BGRAPtrInt); procedure OnChangeFont({%H-}Sender: TObject; {%H-}AData: BGRAPtrInt); protected procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; {%H-}WithThemeSpace: boolean); override; class function GetControlClassDefaultSize: TSize; override; procedure TextChanged; override; protected {$IFDEF INDEBUG} function GetDebugText: String; override; {$ENDIF} procedure DrawControl; override; procedure RenderControl; override; function GetStyleExtension: String; override; protected { Protected declarations } property AutoSize default True; property Background: TBCBackground read FBackground write SetBackground; property Border: TBCBorder read FBorder write SetBorder; property FontEx: TBCFont read FFontEx write SetFontEx; property Rounding: TBCRounding read FRounding write SetRounding; property InnerMargin: single read FInnerMargin write SetInnerMargin; public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure UpdateControl; override; // Called by EndUpdate public { Streaming } {$IFDEF FPC} procedure SaveToFile(AFileName: string); override; procedure LoadFromFile(AFileName: string); override; {$ENDIF} procedure OnFindClass({%H-}Reader: TReader; const AClassName: string; var ComponentClass: TComponentClass); end; { TBCLabel } TBCLabel = class(TCustomBCLabel) published property Action; property Align; property Anchors; property AssignStyle; property AutoSize; property Background; property Border; property BorderSpacing; property Caption; property Cursor; property Enabled; property FontEx; property Height; property HelpContext; property HelpKeyword; property HelpType; property Hint; property InnerMargin; property Left; property PopupMenu; property Rounding; property ShowHint; property Tag; property Top; property Visible; property Width; property OnClick; property OnDblClick; property OnMouseDown; property OnMouseEnter; property OnMouseLeave; property OnMouseMove; property OnMouseUp; property OnMouseWheel; property OnMouseWheelDown; property OnMouseWheelUp; end; {$IFDEF FPC}procedure Register;{$ENDIF} implementation uses BCTools; {$IFDEF FPC}procedure Register; begin RegisterComponents('BGRA Controls',[TBCLabel]); end; {$ENDIF} { TCustomBCLabel } procedure TCustomBCLabel.Render; var r: TRect; begin if (csCreating in ControlState) or IsUpdating then Exit; FBGRA.NeedRender := False; FBGRA.SetSize(Width, Height); FBGRA.Fill(BGRAPixelTransparent); // Clear; r := FBGRA.ClipRect; CalculateBorderRect(FBorder,r); RenderBackgroundAndBorder(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding, FBorder, FInnerMargin); RenderText(FBGRA.ClipRect, FFontEx, Caption, TBGRABitmap(FBGRA), Enabled); {$IFDEF INDEBUG} FRenderCount := FRenderCount +1; {$ENDIF} {$IFNDEF FPC}//# //@ IN DELPHI NEEDRENDER NEED TO BE TRUE. IF FALSE COMPONENT IN BGRANORMAL BE BLACK AFTER INVALIDATE. FBGRA.NeedRender := True; {$ENDIF} end; procedure TCustomBCLabel.SetInnerMargin(AValue: single); begin if FInnerMargin=AValue then Exit; FInnerMargin:=AValue; RenderControl; Invalidate; end; procedure TCustomBCLabel.SetRounding(AValue: TBCRounding); begin if FRounding = AValue then Exit; FRounding.Assign(AValue); RenderControl; Invalidate; end; procedure TCustomBCLabel.UpdateSize; begin InvalidatePreferredSize; AdjustSize; end; procedure TCustomBCLabel.SetBackground(AValue: TBCBackground); begin FBackground.Assign(AValue); RenderControl; Invalidate; end; procedure TCustomBCLabel.SetBorder(AValue: TBCBorder); begin FBorder.Assign(AValue); RenderControl; Invalidate; end; procedure TCustomBCLabel.SetFontEx(AValue: TBCFont); begin FFontEx.Assign(AValue); RenderControl; Invalidate; end; procedure TCustomBCLabel.OnChangeProperty(Sender: TObject; Data: BGRAPtrInt); begin RenderControl; if (Sender = FBorder) and AutoSize then UpdateSize; Invalidate; end; procedure TCustomBCLabel.OnChangeFont(Sender: TObject; AData: BGRAPtrInt); begin RenderControl; UpdateSize; Invalidate; end; procedure TCustomBCLabel.CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; WithThemeSpace: boolean); begin if (Parent = nil) or (not Parent.HandleAllocated) then Exit; CalculateTextSize(Caption, FFontEx, PreferredWidth, PreferredHeight); if AutoSize and (FBorder.Style<>bboNone) then begin Inc(PreferredHeight, 2 * FBorder.Width); Inc(PreferredWidth, 2 * FBorder.Width); end; end; class function TCustomBCLabel.GetControlClassDefaultSize: TSize; begin Result.cx := 100; Result.cy := 25; end; procedure TCustomBCLabel.TextChanged; begin inherited TextChanged; RenderControl; UpdateSize; Invalidate; end; {$IFDEF INDEBUG} function TCustomBCLabel.GetDebugText: String; begin Result := 'R: '+IntToStr(FRenderCount); end; {$ENDIF} procedure TCustomBCLabel.DrawControl; begin inherited DrawControl; if FBGRA.NeedRender then Render; FBGRA.Draw(Self.Canvas,0,0,False); {$IFNDEF FPC}//# //@ IN DELPHI RenderControl NEDD. IF NO RenderControl BE BLACK AFTER INVALIDATE. FBGRA.NeedRender := True; {$ENDIF} end; procedure TCustomBCLabel.RenderControl; begin inherited RenderControl; if FBGRA<>nil then FBGRA.NeedRender := True; end; function TCustomBCLabel.GetStyleExtension: String; begin Result := 'bclbl'; end; procedure TCustomBCLabel.UpdateControl; begin RenderControl; inherited UpdateControl; // invalidate end; {$IFDEF FPC} procedure TCustomBCLabel.SaveToFile(AFileName: string); var AStream: TMemoryStream; begin AStream := TMemoryStream.Create; try WriteComponentAsTextToStream(AStream, Self); AStream.SaveToFile(AFileName); finally AStream.Free; end; end; procedure TCustomBCLabel.LoadFromFile(AFileName: string); var AStream: TMemoryStream; begin AStream := TMemoryStream.Create; try AStream.LoadFromFile(AFileName); ReadComponentFromTextStream(AStream, TComponent(Self), OnFindClass); finally AStream.Free; end; end; {$ENDIF} procedure TCustomBCLabel.OnFindClass(Reader: TReader; const AClassName: string; var ComponentClass: TComponentClass); begin if CompareText(AClassName, 'TBCLabel') = 0 then ComponentClass := TBCLabel; end; constructor TCustomBCLabel.Create(AOwner: TComponent); begin inherited Create(AOwner); {$IFDEF INDEBUG} FRenderCount := 0; {$ENDIF} {$IFDEF FPC} DisableAutoSizing; Include(FControlState, csCreating); {$ELSE} //# {$ENDIF} BeginUpdate; try with GetControlClassDefaultSize do SetInitialBounds(0, 0, CX, CY); FBGRA := TBGRABitmapEx.Create(Width, Height); FBackground := TBCBackground.Create(Self); FBorder := TBCBorder.Create(Self); FFontEx := TBCFont.Create(Self); ParentColor := True; FBackground.OnChange := OnChangeProperty; FBorder.OnChange := OnChangeProperty; FFontEx.OnChange := OnChangeFont; FBackground.Style := bbsClear; FBorder.Style := bboNone; FRounding := TBCRounding.Create(Self); FRounding.OnChange := OnChangeProperty; AutoSize := True; finally {$IFDEF FPC} EnableAutoSizing; {$ENDIF} EndUpdate; {$IFDEF FPC} Exclude(FControlState, csCreating); {$ELSE} //# {$ENDIF} end; end; destructor TCustomBCLabel.Destroy; begin FBGRA.Free; FBackground.Free; FBorder.Free; FFontEx.Free; FRounding.Free; inherited Destroy; end; end.