bcpanel.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. // SPDX-License-Identifier: LGPL-3.0-linking-exception
  2. { Equivalent of standard lazarus TPanel but using BGRA Controls framework for render
  3. Functionality:
  4. - Customizable background (gradient etc.)
  5. - Customizable border (frame 3D or normal border, rounding etc)
  6. - FontEx (shadow etc.)
  7. originally written in 2011 by Krzysztof Dibowski dibowski at interia.pl
  8. }
  9. {******************************* CONTRIBUTOR(S) ******************************
  10. - Edivando S. Santos Brasil | [email protected]
  11. (Compatibility with delphi VCL 11/2018)
  12. ***************************** END CONTRIBUTOR(S) *****************************}
  13. unit BCPanel;
  14. {$I bgracontrols.inc}
  15. interface
  16. uses
  17. Classes, SysUtils, {$IFDEF FPC}LResources,{$ENDIF} Types, Forms, Controls, Graphics, Dialogs,
  18. BGRABitmap, BCBaseCtrls, BGRABitmapTypes, BCTypes, LCLVersion;
  19. type
  20. TOnAfterRenderBCPanel = procedure(Sender: TObject; const ABGRA: TBGRABitmap;
  21. ARect: TRect) of object;
  22. TBCPanelBorderStyle = (bpsBorder, bpsFrame3d);
  23. { TCustomBCPanel }
  24. TCustomBCPanel = class(TBCStyleCustomControl)
  25. private
  26. { Private declarations }
  27. {$IFDEF INDEBUG}
  28. FRenderCount: Integer;
  29. {$ENDIF}
  30. FBackground: TBCBackground;
  31. FBevelWidth: Integer;
  32. FBGRA: TBGRABitmapEx;
  33. FBevelInner, FBevelOuter : TBevelCut;
  34. FBorder: TBCBorder;
  35. FBorderBCStyle: TBCPanelBorderStyle;
  36. FFontEx: TBCFont;
  37. FOnAfterRenderBCPanel: TOnAfterRenderBCPanel;
  38. FRounding: TBCRounding;
  39. procedure SetBackground(AValue: TBCBackground);
  40. procedure SetBevelInner(AValue: TBevelCut);
  41. procedure SetBevelOuter(AValue: TBevelCut);
  42. procedure SetBevelWidth(AValue: Integer);
  43. procedure SetBorder(AValue: TBCBorder);
  44. procedure SetBorderBCStyle(AValue: TBCPanelBorderStyle);
  45. procedure SetFontEx(AValue: TBCFont);
  46. procedure SetRounding(AValue: TBCRounding);
  47. procedure Render;
  48. procedure OnChangeProperty({%H-}Sender: TObject; {%H-}AData: BGRAPtrInt);
  49. procedure OnChangeFont({%H-}Sender: TObject; {%H-}AData: BGRAPtrInt);
  50. protected
  51. { Protected declarations }
  52. procedure AdjustClientRect(var aRect: TRect); override;
  53. class function GetControlClassDefaultSize: TSize; override;
  54. function GetDefaultDockCaption: String; override;
  55. procedure SetEnabled(Value: boolean); override;
  56. procedure TextChanged; override;
  57. protected
  58. function GetStyleExtension: String; override;
  59. {$IFDEF INDEBUG}
  60. function GetDebugText: String; override;
  61. {$ENDIF}
  62. procedure DrawControl; override;
  63. procedure RenderControl; override;
  64. protected
  65. {$IF LCL_FULLVERSION >= 2080000}
  66. procedure SetParentBackground(const AParentBackground: Boolean); override;
  67. {$ENDIF}
  68. property Background: TBCBackground read FBackground write SetBackground;
  69. property BevelInner: TBevelCut read FBevelInner write SetBevelInner;
  70. property BevelOuter: TBevelCut read FBevelOuter write SetBevelOuter;
  71. property BevelWidth: Integer read FBevelWidth write SetBevelWidth;
  72. property Border: TBCBorder read FBorder write SetBorder;
  73. property BorderBCStyle: TBCPanelBorderStyle
  74. read FBorderBCStyle write SetBorderBCStyle default bpsFrame3d;
  75. property FontEx: TBCFont read FFontEx write SetFontEx;
  76. property Rounding: TBCRounding read FRounding write SetRounding;
  77. protected
  78. { Events }
  79. property OnAfterRenderBCPanel: TOnAfterRenderBCPanel
  80. Read FOnAfterRenderBCPanel Write FOnAfterRenderBCPanel;
  81. public
  82. { Public declarations }
  83. constructor Create(TheOwner: TComponent); override;
  84. destructor Destroy; override;
  85. procedure UpdateControl; override; // Called by EndUpdate
  86. public
  87. { Streaming }
  88. {$IFDEF FPC}
  89. procedure SaveToFile(AFileName: string);
  90. procedure LoadFromFile(AFileName: string);
  91. {$ENDIF}
  92. procedure OnFindClass({%H-}Reader: TReader; const AClassName: string;
  93. var ComponentClass: TComponentClass);
  94. end;
  95. { TBCPanel }
  96. TBCPanel = class(TCustomBCPanel)
  97. published
  98. property Align;
  99. property Anchors;
  100. property AssignStyle;
  101. property AutoSize;
  102. property BorderSpacing;
  103. property ChildSizing;
  104. {$IFDEF FPC} //#
  105. property OnGetDockCaption;
  106. {$ENDIF}
  107. property Background;
  108. property BevelInner;
  109. property BevelOuter;
  110. property BevelWidth;
  111. property Border;
  112. property BorderBCStyle;
  113. property Caption;
  114. property Color;
  115. property Constraints;
  116. property DockSite;
  117. property DragCursor;
  118. property DragKind;
  119. property DragMode;
  120. property Enabled;
  121. property FontEx;
  122. property ParentBackground;
  123. property PopupMenu;
  124. property Rounding;
  125. property ShowHint;
  126. property TabOrder;
  127. property TabStop;
  128. property UseDockManager default True;
  129. property Visible;
  130. property OnClick;
  131. property OnContextPopup;
  132. property OnDockDrop;
  133. property OnDockOver;
  134. property OnDblClick;
  135. property OnDragDrop;
  136. property OnDragOver;
  137. property OnEndDock;
  138. property OnEndDrag;
  139. property OnEnter;
  140. property OnExit;
  141. property OnGetSiteInfo;
  142. property OnMouseDown;
  143. property OnMouseEnter;
  144. property OnMouseLeave;
  145. property OnMouseMove;
  146. property OnMouseUp;
  147. property OnMouseWheel;
  148. property OnMouseWheelDown;
  149. property OnMouseWheelUp;
  150. property OnResize;
  151. property OnStartDock;
  152. property OnStartDrag;
  153. property OnUnDock;
  154. property OnAfterRenderBCPanel;
  155. end;
  156. {$IFDEF FPC}procedure Register;{$ENDIF}
  157. implementation
  158. uses BCTools;
  159. {$IFDEF FPC}
  160. procedure Register;
  161. begin
  162. RegisterComponents('BGRA Controls', [TBCPanel]);
  163. end;
  164. {$ENDIF}
  165. { TCustomBCPanel }
  166. procedure TCustomBCPanel.DrawControl;
  167. begin
  168. inherited DrawControl;
  169. if FBGRA.NeedRender then
  170. Render;
  171. if Assigned (FRounding) then
  172. begin
  173. if (FRounding.RoundX<>0) and (FRounding.RoundY<>0) then
  174. FBGRA.Draw(Self.Canvas, 0, 0, False)
  175. else
  176. FBGRA.Draw(Self.Canvas, 0, 0);
  177. end
  178. else
  179. FBGRA.Draw(Self.Canvas, 0, 0);
  180. {$IFNDEF FPC}//# //@ IN DELPHI RenderControl NEDD. IF NO RenderControl BE BLACK AFTER INVALIDATE.
  181. FBGRA.NeedRender := True;
  182. {$ENDIF}
  183. end;
  184. procedure TCustomBCPanel.RenderControl;
  185. begin
  186. inherited RenderControl;
  187. if FBGRA<>nil then
  188. FBGRA.NeedRender := True;
  189. end;
  190. {$IF LCL_FULLVERSION >= 2080000}
  191. procedure TCustomBCPanel.SetParentBackground(const AParentBackground: Boolean);
  192. begin
  193. if ParentBackground=AParentBackground then
  194. Exit;
  195. if AParentBackground then
  196. ControlStyle := ControlStyle - [csOpaque]
  197. else
  198. ControlStyle := ControlStyle + [csOpaque];
  199. inherited;
  200. end;
  201. {$ENDIF}
  202. function TCustomBCPanel.GetStyleExtension: String;
  203. begin
  204. Result := 'bcpnl';
  205. end;
  206. {$IFDEF INDEBUG}
  207. function TCustomBCPanel.GetDebugText: String;
  208. begin
  209. Result := 'R: '+IntToStr(FRenderCount);
  210. end;
  211. {$ENDIF}
  212. procedure TCustomBCPanel.Render;
  213. var r: TRect;
  214. begin
  215. if (csCreating in ControlState) or IsUpdating then
  216. Exit;
  217. FBGRA.NeedRender := False;
  218. FBGRA.SetSize(Width, Height);
  219. FBGRA.Fill(BGRAPixelTransparent);
  220. r := FBGRA.ClipRect;
  221. case FBorderBCStyle of
  222. bpsBorder:
  223. begin
  224. RenderBackgroundAndBorder(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding, FBorder);
  225. CalculateBorderRect(FBorder,r);
  226. end;
  227. bpsFrame3d:
  228. begin
  229. // if BevelOuter is set then draw a frame with BevelWidth
  230. if (FBevelOuter <> bvNone) and (FBevelWidth > 0) then
  231. FBGRA.CanvasBGRA.Frame3d(r, FBevelWidth, FBevelOuter,
  232. BGRA(255, 255, 255, 180), BGRA(0, 0, 0, 160)); // Note: Frame3D inflates ARect
  233. // if BevelInner is set then skip the BorderWidth and draw a frame with BevelWidth
  234. if (FBevelInner <> bvNone) and (FBevelWidth > 0) then
  235. begin
  236. InflateRect(r, -FBevelWidth, -FBevelWidth);
  237. FBGRA.CanvasBGRA.Frame3d(r, FBevelWidth, FBevelInner,
  238. BGRA(255, 255, 255, 160), BGRA(0, 0, 0, 160)); // Note: Frame3D inflates ARect
  239. end;
  240. RenderBackground(r, FBackground, TBGRABitmap(FBGRA), nil, True);
  241. end;
  242. else
  243. RenderBackground(FBGRA.ClipRect, FBackground, TBGRABitmap(FBGRA), FRounding, True);
  244. end;
  245. if Caption <> '' then
  246. RenderText(r,FFontEx,Caption,TBGRABitmap(FBGRA),Enabled);
  247. if Assigned(FOnAfterRenderBCPanel) then
  248. FOnAfterRenderBCPanel(Self, FBGRA, r);
  249. {$IFDEF INDEBUG}
  250. FRenderCount := FRenderCount + 1;
  251. {$ENDIF}
  252. end;
  253. procedure TCustomBCPanel.OnChangeProperty(Sender: TObject; AData: BGRAPtrInt);
  254. begin
  255. RenderControl;
  256. Invalidate;
  257. end;
  258. procedure TCustomBCPanel.OnChangeFont(Sender: TObject; AData: BGRAPtrInt);
  259. begin
  260. RenderControl;
  261. Invalidate;
  262. end;
  263. procedure TCustomBCPanel.SetRounding(AValue: TBCRounding);
  264. begin
  265. if FRounding = AValue then Exit;
  266. FRounding.Assign(AValue);
  267. RenderControl;
  268. Invalidate;
  269. end;
  270. procedure TCustomBCPanel.AdjustClientRect(var aRect: TRect);
  271. var BevelSize: Integer;
  272. begin
  273. inherited AdjustClientRect(aRect);
  274. BevelSize := BorderWidth;
  275. if (BevelOuter <> bvNone) then
  276. inc(BevelSize, BevelWidth);
  277. if (BevelInner <> bvNone) then
  278. inc(BevelSize, BevelWidth);
  279. InflateRect(aRect, -BevelSize, -BevelSize);
  280. end;
  281. class function TCustomBCPanel.GetControlClassDefaultSize: TSize;
  282. begin
  283. Result.CX := 170;
  284. Result.CY := 50;
  285. end;
  286. function TCustomBCPanel.GetDefaultDockCaption: String;
  287. begin
  288. Result := Caption;
  289. end;
  290. procedure TCustomBCPanel.SetBackground(AValue: TBCBackground);
  291. begin
  292. if FBackground = AValue then Exit;
  293. FBackground.Assign(AValue);
  294. RenderControl;
  295. Invalidate;
  296. end;
  297. procedure TCustomBCPanel.SetBevelInner(AValue: TBevelCut);
  298. begin
  299. if FBevelInner = AValue then Exit;
  300. FBevelInner := AValue;
  301. RenderControl;
  302. Invalidate;
  303. end;
  304. procedure TCustomBCPanel.SetBevelOuter(AValue: TBevelCut);
  305. begin
  306. if FBevelOuter = AValue then Exit;
  307. FBevelOuter := AValue;
  308. RenderControl;
  309. Invalidate;
  310. end;
  311. procedure TCustomBCPanel.SetBevelWidth(AValue: Integer);
  312. begin
  313. if FBevelWidth = AValue then Exit;
  314. FBevelWidth := AValue;
  315. RenderControl;
  316. Invalidate;
  317. end;
  318. procedure TCustomBCPanel.SetBorder(AValue: TBCBorder);
  319. begin
  320. if FBorder = AValue then Exit;
  321. FBorder.Assign(AValue);
  322. RenderControl;
  323. Invalidate;
  324. end;
  325. procedure TCustomBCPanel.SetBorderBCStyle(AValue: TBCPanelBorderStyle);
  326. begin
  327. if FBorderBCStyle = AValue then Exit;
  328. FBorderBCStyle := AValue;
  329. RenderControl;
  330. Invalidate;
  331. end;
  332. procedure TCustomBCPanel.SetFontEx(AValue: TBCFont);
  333. begin
  334. if FFontEx = AValue then Exit;
  335. FFontEx.Assign(AValue);
  336. RenderControl;
  337. Invalidate;
  338. end;
  339. procedure TCustomBCPanel.SetEnabled(Value: boolean);
  340. begin
  341. inherited SetEnabled(Value);
  342. RenderControl;
  343. Invalidate;
  344. end;
  345. procedure TCustomBCPanel.TextChanged;
  346. begin
  347. {$IFDEF FPC}
  348. inherited TextChanged;
  349. {$ENDIF}
  350. RenderControl;
  351. Invalidate;
  352. end;
  353. constructor TCustomBCPanel.Create(TheOwner: TComponent);
  354. begin
  355. inherited Create(TheOwner);
  356. {$IFDEF INDEBUG}
  357. FRenderCount := 0;
  358. {$ENDIF}
  359. {$IFDEF FPC}
  360. DisableAutoSizing;
  361. Include(FControlState, csCreating);
  362. {$ELSE} //#
  363. {$ENDIF}
  364. BeginUpdate;
  365. try
  366. ControlStyle := ControlStyle + [csAcceptsControls, csCaptureMouse,
  367. csClickEvents, csSetCaption, csDoubleClicks, csReplicatable{$IFDEF FPC},
  368. csNoFocus, csAutoSize0x0{$ENDIF}]
  369. + [csOpaque]; // we need the default background
  370. //Self.DoubleBuffered := True;
  371. with GetControlClassDefaultSize do
  372. SetInitialBounds(0, 0, CX, CY);
  373. FBGRA := TBGRABitmapEx.Create;
  374. FBorderBCStyle := bpsFrame3d;
  375. FBackground := TBCBackground.Create(Self);
  376. FBorder := TBCBorder.Create(Self);
  377. FFontEx := TBCFont.Create(Self);
  378. FBevelOuter := bvRaised;
  379. FBevelInner := bvNone;
  380. FBevelWidth := 1;
  381. ParentColor := True;
  382. UseDockManager := True;
  383. FBackground.OnChange := OnChangeProperty;
  384. FBorder.OnChange := OnChangeProperty;
  385. FFontEx.OnChange := OnChangeFont;
  386. FBackground.Style := bbsColor;
  387. FBackground.Color := {$ifdef UseCLDefault}clDefault{$else}clBtnFace{$endif};
  388. FBorder.Style := bboNone;
  389. FRounding := TBCRounding.Create(Self);
  390. FRounding.OnChange := OnChangeProperty;
  391. finally
  392. {$IFDEF FPC}
  393. EnableAutoSizing;
  394. {$ENDIF}
  395. EndUpdate;
  396. {$IFDEF FPC}
  397. Exclude(FControlState, csCreating);
  398. {$ELSE} //#
  399. {$ENDIF}
  400. end;
  401. end;
  402. destructor TCustomBCPanel.Destroy;
  403. begin
  404. FBackground.Free;
  405. FBorder.Free;
  406. FFontEx.Free;
  407. FBGRA.Free;
  408. FRounding.Free;
  409. inherited Destroy;
  410. end;
  411. procedure TCustomBCPanel.UpdateControl;
  412. begin
  413. Render;
  414. inherited UpdateControl; // invalidate
  415. end;
  416. {$IFDEF FPC}
  417. procedure TCustomBCPanel.SaveToFile(AFileName: string);
  418. var
  419. AStream: TMemoryStream;
  420. begin
  421. AStream := TMemoryStream.Create;
  422. try
  423. WriteComponentAsTextToStream(AStream, Self);
  424. AStream.SaveToFile(AFileName);
  425. finally
  426. AStream.Free;
  427. end;
  428. end;
  429. procedure TCustomBCPanel.LoadFromFile(AFileName: string);
  430. var
  431. AStream: TMemoryStream;
  432. begin
  433. AStream := TMemoryStream.Create;
  434. try
  435. AStream.LoadFromFile(AFileName);
  436. ReadComponentFromTextStream(AStream, TComponent(Self), OnFindClass);
  437. finally
  438. AStream.Free;
  439. end;
  440. end;
  441. {$ENDIF}
  442. procedure TCustomBCPanel.OnFindClass(Reader: TReader; const AClassName: string;
  443. var ComponentClass: TComponentClass);
  444. begin
  445. if CompareText(AClassName, 'TBCPanel') = 0 then
  446. ComponentClass := TBCPanel;
  447. end;
  448. end.