bclabel.pas 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. // SPDX-License-Identifier: LGPL-3.0-linking-exception
  2. { Equivalent of standard lazarus TLabel but using BGRA Controls framework for text
  3. render.
  4. Functionality:
  5. - Customizable background (gradients etc.)
  6. - Customizable border (rounding etc.)
  7. - FontEx (shadow, word wrap, etc.)
  8. originally written in 2012 by Krzysztof Dibowski dibowski at interia.pl
  9. }
  10. {******************************* CONTRIBUTOR(S) ******************************
  11. - Edivando S. Santos Brasil | [email protected]
  12. (Compatibility with delphi VCL 11/2018)
  13. ***************************** END CONTRIBUTOR(S) *****************************}
  14. unit BCLabel;
  15. {$I bgracontrols.inc}
  16. interface
  17. uses
  18. Classes, SysUtils,{$IFDEF FPC}LResources,{$ENDIF}
  19. types, Forms, Controls, Graphics, Dialogs,
  20. BCBasectrls, BGRABitmap, BGRABitmapTypes, BCTypes;
  21. type
  22. { TCustomBCLabel }
  23. TCustomBCLabel = class(TBCStyleGraphicControl)
  24. private
  25. { Private declarations }
  26. {$IFDEF INDEBUG}
  27. FRenderCount: Integer;
  28. {$ENDIF}
  29. FBackground: TBCBackground;
  30. FBGRA: TBGRABitmapEx;
  31. FBorder: TBCBorder;
  32. FFontEx: TBCFont;
  33. FInnerMargin: single;
  34. FRounding: TBCRounding;
  35. procedure Render;
  36. procedure SetInnerMargin(AValue: single);
  37. procedure SetRounding(AValue: TBCRounding);
  38. procedure UpdateSize;
  39. procedure SetBackground(AValue: TBCBackground);
  40. procedure SetBorder(AValue: TBCBorder);
  41. procedure SetFontEx(AValue: TBCFont);
  42. procedure OnChangeProperty(Sender: TObject; {%H-}Data: BGRAPtrInt);
  43. procedure OnChangeFont({%H-}Sender: TObject; {%H-}AData: BGRAPtrInt);
  44. protected
  45. procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
  46. {%H-}WithThemeSpace: boolean); override;
  47. class function GetControlClassDefaultSize: TSize; override;
  48. procedure TextChanged; override;
  49. protected
  50. {$IFDEF INDEBUG}
  51. function GetDebugText: String; override;
  52. {$ENDIF}
  53. procedure DrawControl; override;
  54. procedure RenderControl; override;
  55. function GetStyleExtension: String; override;
  56. protected
  57. { Protected declarations }
  58. property AutoSize default True;
  59. property Background: TBCBackground read FBackground write SetBackground;
  60. property Border: TBCBorder read FBorder write SetBorder;
  61. property FontEx: TBCFont read FFontEx write SetFontEx;
  62. property Rounding: TBCRounding read FRounding write SetRounding;
  63. property InnerMargin: single read FInnerMargin write SetInnerMargin;
  64. public
  65. { Public declarations }
  66. constructor Create(AOwner: TComponent); override;
  67. destructor Destroy; override;
  68. procedure UpdateControl; override; // Called by EndUpdate
  69. public
  70. { Streaming }
  71. {$IFDEF FPC}
  72. procedure SaveToFile(AFileName: string); override;
  73. procedure LoadFromFile(AFileName: string); override;
  74. {$ENDIF}
  75. procedure OnFindClass({%H-}Reader: TReader; const AClassName: string;
  76. var ComponentClass: TComponentClass);
  77. end;
  78. { TBCLabel }
  79. TBCLabel = class(TCustomBCLabel)
  80. published
  81. property Action;
  82. property Align;
  83. property Anchors;
  84. property AssignStyle;
  85. property AutoSize;
  86. property Background;
  87. property Border;
  88. property BorderSpacing;
  89. property Caption;
  90. property Cursor;
  91. property Enabled;
  92. property FontEx;
  93. property Height;
  94. property HelpContext;
  95. property HelpKeyword;
  96. property HelpType;
  97. property Hint;
  98. property InnerMargin;
  99. property Left;
  100. property PopupMenu;
  101. property Rounding;
  102. property ShowHint;
  103. property Tag;
  104. property Top;
  105. property Visible;
  106. property Width;
  107. property OnClick;
  108. property OnDblClick;
  109. property OnMouseDown;
  110. property OnMouseEnter;
  111. property OnMouseLeave;
  112. property OnMouseMove;
  113. property OnMouseUp;
  114. property OnMouseWheel;
  115. property OnMouseWheelDown;
  116. property OnMouseWheelUp;
  117. end;
  118. {$IFDEF FPC}procedure Register;{$ENDIF}
  119. implementation
  120. uses BCTools;
  121. {$IFDEF FPC}procedure Register;
  122. begin
  123. RegisterComponents('BGRA Controls',[TBCLabel]);
  124. end;
  125. {$ENDIF}
  126. { TCustomBCLabel }
  127. procedure TCustomBCLabel.Render;
  128. var r: TRect;
  129. begin
  130. if (csCreating in ControlState) or IsUpdating then
  131. Exit;
  132. FBGRA.NeedRender := False;
  133. FBGRA.SetSize(Width, Height);
  134. FBGRA.Fill(BGRAPixelTransparent); // Clear;
  135. r := FBGRA.ClipRect;
  136. CalculateBorderRect(FBorder,r);
  137. RenderBackgroundAndBorder(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding, FBorder, FInnerMargin);
  138. RenderText(FBGRA.ClipRect, FFontEx, Caption, TBGRABitmap(FBGRA), Enabled);
  139. {$IFDEF INDEBUG}
  140. FRenderCount := FRenderCount +1;
  141. {$ENDIF}
  142. {$IFNDEF FPC}//# //@ IN DELPHI NEEDRENDER NEED TO BE TRUE. IF FALSE COMPONENT IN BGRANORMAL BE BLACK AFTER INVALIDATE.
  143. FBGRA.NeedRender := True;
  144. {$ENDIF}
  145. end;
  146. procedure TCustomBCLabel.SetInnerMargin(AValue: single);
  147. begin
  148. if FInnerMargin=AValue then Exit;
  149. FInnerMargin:=AValue;
  150. RenderControl;
  151. Invalidate;
  152. end;
  153. procedure TCustomBCLabel.SetRounding(AValue: TBCRounding);
  154. begin
  155. if FRounding = AValue then Exit;
  156. FRounding.Assign(AValue);
  157. RenderControl;
  158. Invalidate;
  159. end;
  160. procedure TCustomBCLabel.UpdateSize;
  161. begin
  162. InvalidatePreferredSize;
  163. AdjustSize;
  164. end;
  165. procedure TCustomBCLabel.SetBackground(AValue: TBCBackground);
  166. begin
  167. FBackground.Assign(AValue);
  168. RenderControl;
  169. Invalidate;
  170. end;
  171. procedure TCustomBCLabel.SetBorder(AValue: TBCBorder);
  172. begin
  173. FBorder.Assign(AValue);
  174. RenderControl;
  175. Invalidate;
  176. end;
  177. procedure TCustomBCLabel.SetFontEx(AValue: TBCFont);
  178. begin
  179. FFontEx.Assign(AValue);
  180. RenderControl;
  181. Invalidate;
  182. end;
  183. procedure TCustomBCLabel.OnChangeProperty(Sender: TObject; Data: BGRAPtrInt);
  184. begin
  185. RenderControl;
  186. if (Sender = FBorder) and AutoSize then
  187. UpdateSize;
  188. Invalidate;
  189. end;
  190. procedure TCustomBCLabel.OnChangeFont(Sender: TObject; AData: BGRAPtrInt);
  191. begin
  192. RenderControl;
  193. UpdateSize;
  194. Invalidate;
  195. end;
  196. procedure TCustomBCLabel.CalculatePreferredSize(var PreferredWidth,
  197. PreferredHeight: integer; WithThemeSpace: boolean);
  198. begin
  199. if (Parent = nil) or (not Parent.HandleAllocated) then
  200. Exit;
  201. CalculateTextSize(Caption, FFontEx, PreferredWidth, PreferredHeight);
  202. if AutoSize and (FBorder.Style<>bboNone) then
  203. begin
  204. Inc(PreferredHeight, 2 * FBorder.Width);
  205. Inc(PreferredWidth, 2 * FBorder.Width);
  206. end;
  207. end;
  208. class function TCustomBCLabel.GetControlClassDefaultSize: TSize;
  209. begin
  210. Result.cx := 100;
  211. Result.cy := 25;
  212. end;
  213. procedure TCustomBCLabel.TextChanged;
  214. begin
  215. inherited TextChanged;
  216. RenderControl;
  217. UpdateSize;
  218. Invalidate;
  219. end;
  220. {$IFDEF INDEBUG}
  221. function TCustomBCLabel.GetDebugText: String;
  222. begin
  223. Result := 'R: '+IntToStr(FRenderCount);
  224. end;
  225. {$ENDIF}
  226. procedure TCustomBCLabel.DrawControl;
  227. begin
  228. inherited DrawControl;
  229. if FBGRA.NeedRender then
  230. Render;
  231. FBGRA.Draw(Self.Canvas,0,0,False);
  232. {$IFNDEF FPC}//# //@ IN DELPHI RenderControl NEDD. IF NO RenderControl BE BLACK AFTER INVALIDATE.
  233. FBGRA.NeedRender := True;
  234. {$ENDIF}
  235. end;
  236. procedure TCustomBCLabel.RenderControl;
  237. begin
  238. inherited RenderControl;
  239. if FBGRA<>nil then
  240. FBGRA.NeedRender := True;
  241. end;
  242. function TCustomBCLabel.GetStyleExtension: String;
  243. begin
  244. Result := 'bclbl';
  245. end;
  246. procedure TCustomBCLabel.UpdateControl;
  247. begin
  248. RenderControl;
  249. inherited UpdateControl; // invalidate
  250. end;
  251. {$IFDEF FPC}
  252. procedure TCustomBCLabel.SaveToFile(AFileName: string);
  253. var
  254. AStream: TMemoryStream;
  255. begin
  256. AStream := TMemoryStream.Create;
  257. try
  258. WriteComponentAsTextToStream(AStream, Self);
  259. AStream.SaveToFile(AFileName);
  260. finally
  261. AStream.Free;
  262. end;
  263. end;
  264. procedure TCustomBCLabel.LoadFromFile(AFileName: string);
  265. var
  266. AStream: TMemoryStream;
  267. begin
  268. AStream := TMemoryStream.Create;
  269. try
  270. AStream.LoadFromFile(AFileName);
  271. ReadComponentFromTextStream(AStream, TComponent(Self), OnFindClass);
  272. finally
  273. AStream.Free;
  274. end;
  275. end;
  276. {$ENDIF}
  277. procedure TCustomBCLabel.OnFindClass(Reader: TReader; const AClassName: string;
  278. var ComponentClass: TComponentClass);
  279. begin
  280. if CompareText(AClassName, 'TBCLabel') = 0 then
  281. ComponentClass := TBCLabel;
  282. end;
  283. constructor TCustomBCLabel.Create(AOwner: TComponent);
  284. begin
  285. inherited Create(AOwner);
  286. {$IFDEF INDEBUG}
  287. FRenderCount := 0;
  288. {$ENDIF}
  289. {$IFDEF FPC}
  290. DisableAutoSizing;
  291. Include(FControlState, csCreating);
  292. {$ELSE} //#
  293. {$ENDIF}
  294. BeginUpdate;
  295. try
  296. with GetControlClassDefaultSize do
  297. SetInitialBounds(0, 0, CX, CY);
  298. FBGRA := TBGRABitmapEx.Create(Width, Height);
  299. FBackground := TBCBackground.Create(Self);
  300. FBorder := TBCBorder.Create(Self);
  301. FFontEx := TBCFont.Create(Self);
  302. ParentColor := True;
  303. FBackground.OnChange := OnChangeProperty;
  304. FBorder.OnChange := OnChangeProperty;
  305. FFontEx.OnChange := OnChangeFont;
  306. FBackground.Style := bbsClear;
  307. FBorder.Style := bboNone;
  308. FRounding := TBCRounding.Create(Self);
  309. FRounding.OnChange := OnChangeProperty;
  310. AutoSize := True;
  311. finally
  312. {$IFDEF FPC}
  313. EnableAutoSizing;
  314. {$ENDIF}
  315. EndUpdate;
  316. {$IFDEF FPC}
  317. Exclude(FControlState, csCreating);
  318. {$ELSE} //#
  319. {$ENDIF}
  320. end;
  321. end;
  322. destructor TCustomBCLabel.Destroy;
  323. begin
  324. FBGRA.Free;
  325. FBackground.Free;
  326. FBorder.Free;
  327. FFontEx.Free;
  328. FRounding.Free;
  329. inherited Destroy;
  330. end;
  331. end.