bcleaboard.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. {
  2. *****************************************************************************
  3. See the file COPYING.modifiedLGPL.txt, included in this distribution,
  4. for details about the license.
  5. *****************************************************************************
  6. Author: Boban Spasic
  7. }
  8. unit BCLeaBoard;
  9. {$mode objfpc}{$H+}
  10. interface
  11. uses
  12. Classes, SysUtils, LResources, Controls, Graphics,
  13. BGRABitmapTypes, BGRABitmap, BGRAGradients, BCLeaTheme, BCLeaTypes;
  14. type
  15. TBCLeaBoard = class(TCustomControl)
  16. private
  17. FBitmap: TBGRABitmap;
  18. FTheme: TBCLeaTheme;
  19. FFrameColor: TColor;
  20. FBoardColor: TColor;
  21. FBkgColor: TColor;
  22. FFrameStyle: TZStyle;
  23. FBoardStyle: TZStyle;
  24. FAltitude: integer;
  25. FRounding: integer;
  26. FFrameHeight: integer;
  27. FFrameDistance: integer;
  28. //global intensity of the light
  29. FLightSourceIntensity: single;
  30. //minimum distance always added (positive value)
  31. FLightSourceDistanceTerm: single;
  32. //how much actual distance is taken into account (usually 0 or 1)
  33. FLightSourceDistanceFactor: single;
  34. //how much the location of the lightened pixel is taken into account (usually 0 or 1)
  35. FLightDestFactor: single;
  36. //color of the light reflection
  37. FLightColor: TColor;
  38. //how much light is reflected (0..1)
  39. FSpecularFactor: single;
  40. //how concentrated reflected light is (positive value)
  41. FSpecularIndex: single;
  42. //ambiant lighting whereever the point is (0..1)
  43. FAmbientFactor: single;
  44. //diffusion, i.e. how much pixels are lightened by light source (0..1)
  45. FDiffusionFactor: single;
  46. //how much hidden surface are darkened (0..1)
  47. FNegativeDiffusionFactor: single;
  48. //when diffusion saturates, use light color to show it
  49. FDiffuseSaturation: boolean;
  50. FLightPositionX: integer;
  51. FLightPositionY: integer;
  52. FLightPositionZ: integer;
  53. procedure SetAltitude(AValue: integer);
  54. procedure SetFrameColor(AValue: TColor);
  55. procedure SetBoardColor(AValue: TColor);
  56. procedure SetBkgColor(AValue: TColor);
  57. procedure SetFrameStyle(AValue: TZStyle);
  58. procedure SetBoardStyle(AValue: TZStyle);
  59. procedure SetTheme(AValue: TBCLeaTheme);
  60. procedure SetRounding(AValue: integer);
  61. procedure SetFrameHeight(AValue: integer);
  62. procedure SetFrameDistance(AValue: integer);
  63. protected
  64. procedure SetEnabled(Value: boolean); override;
  65. procedure SetVisible(Value: boolean); override;
  66. procedure Paint; override;
  67. procedure Redraw;
  68. public
  69. constructor Create(AOwner: TComponent); override;
  70. destructor Destroy; override;
  71. procedure UpdateTheme;
  72. procedure ApplyTheme;
  73. procedure SaveThemeToFile(AFileName: string);
  74. procedure LoadThemeFromFile(AFileName: string);
  75. procedure ApplyDefaultTheme;
  76. published
  77. property Align;
  78. property Cursor;
  79. property Enabled;
  80. property Font;
  81. property PopupMenu;
  82. property ShowHint;
  83. property TabOrder;
  84. property TabStop default True;
  85. property Anchors;
  86. property Constraints;
  87. property Visible;
  88. property OnClick;
  89. property OnDblClick;
  90. property OnEnter;
  91. property OnExit;
  92. property OnContextPopup;
  93. property FrameColor: TColor read FFrameColor write SetFrameColor default clBtnFace;
  94. property BoardColor: TColor read FBoardColor write SetBoardColor default clBtnFace;
  95. property BackgroundColor: TColor read FBkgColor write SetBkgColor default clBtnFace;
  96. property FrameStyle: TZStyle read FFrameStyle write SetFrameStyle default zsRaised;
  97. property BoardStyle: TZStyle read FBoardStyle write SetBoardStyle default zsFlat;
  98. property Theme: TBCLeaTheme read FTheme write SetTheme;
  99. property Altitude: integer read FAltitude write SetAltitude default 2;
  100. property Rounding: integer read FRounding write SetRounding default 10;
  101. property FrameHeight: integer read FFrameHeight write SetFrameHeight default 10;
  102. property FrameDistance: integer read FFrameDistance write SetFrameDistance default 3;
  103. end;
  104. procedure Register;
  105. implementation
  106. procedure Register;
  107. begin
  108. RegisterComponents('BGRA Controls', [TBCLeaBoard]);
  109. end;
  110. constructor TBCLeaBoard.Create(AOwner: TComponent);
  111. begin
  112. inherited Create(AOwner);
  113. with GetControlClassDefaultSize do
  114. SetInitialBounds(0, 0, 200, 150);
  115. ControlStyle := [csAcceptsControls, csReplicatable, csClickEvents];
  116. ApplyDefaultTheme;
  117. FBitmap := TBGRABitmap.Create(Width, Height, FBkgColor);
  118. end;
  119. destructor TBCLeaBoard.Destroy;
  120. begin
  121. FreeAndNil(FBitmap);
  122. inherited Destroy;
  123. end;
  124. procedure TBCLeaBoard.SetEnabled(Value: boolean);
  125. begin
  126. inherited SetEnabled(Value);
  127. Invalidate;
  128. end;
  129. procedure TBCLeaBoard.SetVisible(Value: boolean);
  130. begin
  131. inherited SetVisible(Value);
  132. Invalidate;
  133. end;
  134. procedure TBCLeaBoard.Paint;
  135. begin
  136. inherited Paint;
  137. Redraw;
  138. end;
  139. procedure TBCLeaBoard.SetFrameStyle(AValue: TZStyle);
  140. begin
  141. if FFrameStyle = AValue then
  142. Exit;
  143. FFrameStyle := AValue;
  144. Invalidate;
  145. end;
  146. procedure TBCLeaBoard.SetBoardStyle(AValue: TZStyle);
  147. begin
  148. if FBoardStyle = AValue then
  149. Exit;
  150. FBoardStyle := AValue;
  151. Invalidate;
  152. end;
  153. procedure TBCLeaBoard.SetFrameColor(AValue: TColor);
  154. begin
  155. if FFrameColor = AValue then
  156. Exit;
  157. FFrameColor := AValue;
  158. Invalidate;
  159. end;
  160. procedure TBCLeaBoard.SetBoardColor(AValue: TColor);
  161. begin
  162. if FBoardColor = AValue then
  163. Exit;
  164. FBoardColor := AValue;
  165. Invalidate;
  166. end;
  167. procedure TBCLeaBoard.SetBkgColor(AValue: TColor);
  168. begin
  169. if FBkgColor = AValue then
  170. Exit;
  171. FBkgColor := AValue;
  172. Invalidate;
  173. end;
  174. procedure TBCLeaBoard.SetAltitude(AValue: integer);
  175. begin
  176. if FAltitude = AValue then
  177. Exit;
  178. FAltitude := AValue;
  179. Invalidate;
  180. end;
  181. procedure TBCLeaBoard.SetRounding(AValue: integer);
  182. begin
  183. if FRounding = AValue then
  184. Exit;
  185. FRounding := AValue;
  186. Invalidate;
  187. end;
  188. procedure TBCLeaBoard.SetTheme(AValue: TBCLeaTheme);
  189. begin
  190. if FTheme = AValue then
  191. Exit;
  192. FTheme := AValue;
  193. Invalidate;
  194. end;
  195. procedure TBCLeaBoard.SetFrameDistance(AValue: integer);
  196. begin
  197. if FFrameDistance = AValue then
  198. Exit;
  199. FFrameDistance := AValue;
  200. Invalidate;
  201. end;
  202. procedure TBCLeaBoard.SetFrameHeight(AValue: integer);
  203. begin
  204. if FFrameHeight = AValue then
  205. Exit;
  206. FFrameHeight := AValue;
  207. Invalidate;
  208. end;
  209. procedure TBCLeaBoard.ApplyDefaultTheme;
  210. begin
  211. FFrameColor := clBtnFace;
  212. FBoardColor := clBtnFace;
  213. FBkgColor := clBtnFace;
  214. FFrameStyle := zsRaised;
  215. FBoardStyle := zsFlat;
  216. FFrameHeight := 10;
  217. FFrameDistance := 3;
  218. FAltitude := 2;
  219. FRounding := 10;
  220. FAmbientFactor := 0.3;
  221. FSpecularIndex := 10;
  222. FSpecularFactor := 0.6;
  223. FLightDestFactor := 1;
  224. FLightPositionX := -100;
  225. FLightPositionY := -100;
  226. FLightPositionZ := 100;
  227. FLightSourceIntensity := 500;
  228. FLightSourceDistanceTerm := 150;
  229. FLightSourceDistanceFactor := 1;
  230. FNegativeDiffusionFactor := 0.1;
  231. FLightColor := clWhite;
  232. FDiffuseSaturation := False;
  233. FDiffusionFactor := 0.9;
  234. end;
  235. procedure TBCLeaBoard.UpdateTheme;
  236. begin
  237. if Assigned(FTheme) then
  238. begin
  239. FTheme.BRD_FrameColor := FFrameColor;
  240. FTheme.BRD_BoardColor := FBoardColor;
  241. FTheme.BRD_BkgColor := FBkgColor;
  242. FTheme.BRD_FrameStyle := FFrameStyle;
  243. FTheme.BRD_BoardStyle := FBoardStyle;
  244. FTheme.BRD_FrameHeight := FFrameHeight;
  245. FTheme.BRD_FrameDistance := FFrameDistance;
  246. FTheme.BRD_Altitude := FAltitude;
  247. FTheme.BRD_Rounding := FRounding;
  248. end;
  249. end;
  250. procedure TBCLeaBoard.ApplyTheme;
  251. begin
  252. if Assigned(FTheme) then
  253. begin
  254. FFrameColor := FTheme.BRD_FrameColor;
  255. FBoardColor := FTheme.BRD_BoardColor;
  256. FBkgColor := FTheme.BRD_BkgColor;
  257. FFrameStyle := FTheme.BRD_FrameStyle;
  258. FBoardStyle := FTheme.BRD_BoardStyle;
  259. FFrameHeight := FTheme.BRD_FrameHeight;
  260. FFrameDistance := FTheme.BRD_FrameDistance;
  261. FAltitude := FTheme.BRD_Altitude;
  262. FRounding := FTheme.BRD_Rounding;
  263. FLightSourceIntensity := FTheme.COM_LightSourceIntensity;
  264. FLightSourceDistanceTerm := FTheme.COM_LightSourceDistanceTerm;
  265. FLightSourceDistanceFactor := FTheme.COM_LightSourceDistanceFactor;
  266. FLightDestFactor := FTheme.COM_LightDestFactor;
  267. FLightColor := FTheme.COM_LightColor;
  268. FSpecularFactor := FTheme.COM_SpecularFactor;
  269. FSpecularIndex := FTheme.COM_SpecularIndex;
  270. FAmbientFactor := FTheme.COM_AmbientFactor;
  271. FDiffusionFactor := FTheme.COM_DiffusionFactor;
  272. FNegativeDiffusionFactor := FTheme.COM_NegativeDiffusionFactor;
  273. FDiffuseSaturation := FTheme.COM_DiffuseSaturation;
  274. FLightPositionX := FTheme.COM_LightPositionX;
  275. FLightPositionY := FTheme.COM_LightPositionY;
  276. FLightPositionZ := FTheme.COM_LightPositionZ;
  277. Invalidate;
  278. end
  279. else
  280. begin
  281. ApplyDefaultTheme;
  282. end;
  283. end;
  284. procedure TBCLeaBoard.SaveThemeToFile(AFileName: string);
  285. begin
  286. if Assigned(FTheme) then
  287. FTheme.SaveThemeToFile(AFileName);
  288. end;
  289. procedure TBCLeaBoard.LoadThemeFromFile(AFileName: string);
  290. begin
  291. if Assigned(FTheme) then
  292. FTheme.LoadThemeFromFile(AFileName);
  293. end;
  294. procedure TBCLeaBoard.Redraw;
  295. var
  296. EffectiveSize: integer;
  297. Blur: TBGRABitmap;
  298. Mask, TmpBitmap: TBGRABitmap;
  299. Phong: TPhongShading;
  300. ScaledPhongSize{, ScaledSize}: integer;
  301. procedure DoDrawFrame(AFrameColor, ABoardColor: TColor);
  302. var
  303. d: integer;
  304. begin
  305. d := FFrameDistance;
  306. FBitmap.FillRoundRectAntialias(d, d, Width - d, Height - d, FRounding, FRounding, AFrameColor);
  307. d := FFrameDistance + FFrameHeight + FAltitude;
  308. FBitmap.FillRoundRectAntialias(d, d, Width - d, Height - d, FRounding, FRounding, ABoardColor);
  309. if (FFrameStyle = zsRaised) or (FFrameStyle = zsLowered) then
  310. begin
  311. Mask := FBitmap.FilterGrayscale as TBGRABitmap;
  312. if (FFrameStyle = zsRaised) then
  313. Mask.Negative;
  314. Blur := Mask.FilterBlurRadial(ScaledPhongSize, ScaledPhongSize, rbFast) as TBGRABitmap;
  315. Blur.FillMask(0, 0, Mask, BGRAPixelTransparent, dmSet);
  316. Mask.Free;
  317. Phong := TPhongShading.Create;
  318. if assigned(FTheme) then
  319. begin
  320. Phong.AmbientFactor := FAmbientFactor;
  321. Phong.SpecularIndex := FSpecularIndex;
  322. Phong.LightDestFactor := FLightDestFactor;
  323. Phong.LightPosition := Point(FLightPositionX, FLightPositionY);
  324. Phong.LightPositionZ := FLightPositionZ;
  325. Phong.LightSourceIntensity := FLightSourceIntensity;
  326. Phong.LightSourceDistanceTerm := FLightSourceDistanceTerm;
  327. Phong.LightSourceDistanceFactor := FLightSourceDistanceFactor;
  328. Phong.NegativeDiffusionFactor := FNegativeDiffusionFactor;
  329. Phong.SpecularFactor := FSpecularFactor;
  330. Phong.DiffusionFactor := FDiffusionFactor;
  331. Phong.DiffuseSaturation := FDiffuseSaturation;
  332. Phong.LightColor := FLightColor;
  333. end;
  334. Mask := TBGRABitmap.Create(Width, Height, ColorToBGRA(ColorToRGB(BGRABlack)));
  335. d := FFrameDistance;
  336. Mask.FillRoundRectAntialias(d, d, Width - d, Height - d, FRounding, FRounding, BGRAWhite);
  337. d := FFrameDistance + FFrameHeight + FAltitude;
  338. FBitmap.FillRoundRectAntialias(d, d, Width - d, Height - d, FRounding, FRounding, BGRABlack);
  339. TmpBitmap := TBGRABitmap.Create(Width, Height, ColorToBGRA(ColorToRGB(BGRABlack)));
  340. Phong.Draw(TmpBitmap, Blur, FAltitude, 0, 0, FBitmap);
  341. Phong.Free;
  342. Blur.Free;
  343. TmpBitmap.ApplyMask(Mask);
  344. FBitmap.PutImage(0,0,TmpBitmap, dmDrawWithTransparency);
  345. TmpBitmap.Free;
  346. Mask.Free;
  347. end;
  348. end;
  349. procedure DoDrawBoard(AValue: TColor);
  350. var
  351. d: integer;
  352. begin
  353. d := FFrameDistance + FFrameHeight + FAltitude;
  354. FBitmap.FillRoundRectAntialias(d, d, Width - d, Height - d, FRounding, FRounding, AValue);
  355. end;
  356. begin
  357. FBitmap.SetSize(Width, Height);
  358. FBitmap.Fill(FBkgColor);
  359. if Width < Height then
  360. EffectiveSize := Width
  361. else
  362. EffectiveSize := Height;
  363. if EffectiveSize < 2 then exit;
  364. //ScaledSize := Scale96ToForm(FSize);
  365. ScaledPhongSize := Scale96ToForm(5);
  366. if Enabled then
  367. begin
  368. DoDrawFrame(FFrameColor, FBoardColor);
  369. if FBoardStyle = zsFlat then
  370. DoDrawBoard(FBoardColor);
  371. end
  372. else
  373. begin
  374. DoDrawFrame(clDkGray, clGray);
  375. if FBoardStyle = zsFlat then
  376. DoDrawBoard(clGray);
  377. end;
  378. FBitmap.Draw(Canvas, 0, 0, True);
  379. end;
  380. end.