kascomctrls.pas 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. unit KASComCtrls;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Controls, ComCtrls, Graphics, Dialogs;
  6. type
  7. { TToolButtonClr }
  8. TToolButtonClr = class(TToolButton)
  9. private
  10. FButtonColor: TColor;
  11. FColorDialog: TColorDialog;
  12. procedure SetButtonColor(AValue: TColor);
  13. protected
  14. procedure Paint; override;
  15. procedure ShowColorDialog;
  16. public
  17. constructor Create(TheOwner: TComponent); override;
  18. procedure Click; override;
  19. property ButtonColor: TColor read FButtonColor write SetButtonColor;
  20. end;
  21. { TToolBarAdv }
  22. TToolBarAdv = class(TToolBar)
  23. private
  24. FToolBarFlags: TToolBarFlags;
  25. protected
  26. procedure CalculatePreferredSize(var PreferredWidth,
  27. PreferredHeight: Integer;
  28. {%H-}WithThemeSpace: Boolean); override;
  29. procedure AlignControls({%H-}AControl: TControl;
  30. var RemainingClientRect: TRect); override;
  31. function WrapButtons(UseSize: Integer; out NewWidth,
  32. NewHeight: Integer; Simulate: Boolean): Boolean;
  33. end;
  34. procedure Register;
  35. implementation
  36. uses
  37. Math;
  38. { TToolButtonClr }
  39. procedure TToolButtonClr.SetButtonColor(AValue: TColor);
  40. begin
  41. if FButtonColor <> AValue then
  42. begin
  43. FButtonColor:= AValue;
  44. Invalidate;
  45. end;
  46. end;
  47. procedure TToolButtonClr.Paint;
  48. var
  49. ARect, IconRect: TRect;
  50. begin
  51. inherited Paint;
  52. if (FToolBar <> nil) and (ClientWidth > 0) and (ClientHeight > 0) then
  53. begin
  54. ARect:= ClientRect;
  55. IconRect.Left:= (ARect.Width - FToolBar.ImagesWidth) div 2;
  56. IconRect.Top:= (ARect.Height - FToolBar.ImagesWidth) div 2;
  57. IconRect.Right:= IconRect.Left + FToolBar.ImagesWidth;
  58. IconRect.Bottom:= IconRect.Top + FToolBar.ImagesWidth;
  59. if Enabled then
  60. begin
  61. Canvas.Brush.Style:= bsSolid;
  62. Canvas.Brush.Color:= FButtonColor
  63. end
  64. else begin
  65. Canvas.Brush.Color:= clGrayText;
  66. Canvas.Brush.Style:= bsDiagCross;
  67. end;
  68. Canvas.Pen.Color:= clBtnText;
  69. Canvas.Rectangle(IconRect);
  70. end;
  71. end;
  72. procedure TToolButtonClr.ShowColorDialog;
  73. begin
  74. if not Enabled then Exit;
  75. if (FColorDialog = nil) then
  76. begin
  77. FColorDialog := TColorDialog.Create(Self);
  78. end;
  79. FColorDialog.Color := ButtonColor;
  80. if FColorDialog.Execute then
  81. begin
  82. ButtonColor := FColorDialog.Color;
  83. end;
  84. end;
  85. constructor TToolButtonClr.Create(TheOwner: TComponent);
  86. begin
  87. FButtonColor:= clRed;
  88. inherited Create(TheOwner);
  89. end;
  90. procedure TToolButtonClr.Click;
  91. begin
  92. inherited Click;
  93. ShowColorDialog;
  94. end;
  95. { TToolBarAdv }
  96. procedure TToolBarAdv.CalculatePreferredSize(var PreferredWidth,
  97. PreferredHeight: Integer; WithThemeSpace: Boolean);
  98. begin
  99. if IsVertical then
  100. WrapButtons(Height, PreferredWidth, PreferredHeight, True)
  101. else
  102. WrapButtons(Width, PreferredWidth, PreferredHeight, True);
  103. end;
  104. procedure TToolBarAdv.AlignControls(AControl: TControl;
  105. var RemainingClientRect: TRect);
  106. var
  107. NewWidth, NewHeight: integer;
  108. begin
  109. if tbfPlacingControls in FToolBarFlags then exit;
  110. Include(FToolBarFlags, tbfPlacingControls);
  111. DisableAlign;
  112. try
  113. AdjustClientRect(RemainingClientRect);
  114. if IsVertical then
  115. WrapButtons(Height, NewWidth, NewHeight, False)
  116. else
  117. WrapButtons(Width, NewWidth, NewHeight, False);
  118. finally
  119. Exclude(FToolBarFlags, tbfPlacingControls);
  120. EnableAlign;
  121. end;
  122. end;
  123. function TToolBarAdv.WrapButtons(UseSize: Integer; out NewWidth,
  124. NewHeight: Integer; Simulate: Boolean): Boolean;
  125. var
  126. ARect: TRect;
  127. X, Y: Integer;
  128. Vertical: Boolean;
  129. LeftToRight: Boolean;
  130. CurControl: TControl;
  131. StartX, StartY: Integer;
  132. FRowWidth, FRowHeight: Integer;
  133. procedure CalculatePosition;
  134. var
  135. NewBounds: TRect;
  136. StartedAtRowStart: Boolean;
  137. begin
  138. if IsVertical then
  139. begin
  140. NewBounds := Bounds(X, Y, FRowWidth, CurControl.Height);
  141. repeat
  142. if (not Wrapable) or
  143. (NewBounds.Top = StartY) or
  144. (NewBounds.Bottom <= ARect.Bottom) then
  145. begin
  146. // control fits into the column
  147. X := NewBounds.Left;
  148. Y := NewBounds.Top;
  149. Break;
  150. end;
  151. // try next column
  152. NewBounds.Top := StartY;
  153. NewBounds.Bottom := NewBounds.Top + CurControl.Height;
  154. Inc(NewBounds.Left, FRowWidth);
  155. Inc(NewBounds.Right, FRowWidth);
  156. until False;
  157. end
  158. else begin
  159. StartedAtRowStart := (X = StartX);
  160. if LeftToRight then
  161. NewBounds := Bounds(X, Y, CurControl.Width, FRowHeight)
  162. else begin
  163. NewBounds := Bounds(X - CurControl.Width, Y, CurControl.Width, FRowHeight);
  164. end;
  165. repeat
  166. if (not Wrapable) or
  167. (StartedAtRowStart) or
  168. (LeftToRight and ((NewBounds.Left = StartX) or (NewBounds.Right <= ARect.Right))) or
  169. ((not LeftToRight) and ((NewBounds.Right = StartX) or (NewBounds.Left >= ARect.Left))) then
  170. begin
  171. // control fits into the row
  172. X := NewBounds.Left;
  173. Y := NewBounds.Top;
  174. Break;
  175. end;
  176. StartedAtRowStart := True;
  177. // try next row
  178. if LeftToRight then
  179. begin
  180. NewBounds.Left := StartX;
  181. NewBounds.Right := NewBounds.Left + CurControl.Width;
  182. end else begin
  183. NewBounds.Right := StartX;
  184. NewBounds.Left := NewBounds.Right - CurControl.Width;
  185. end;
  186. Inc(NewBounds.Top, FRowHeight);
  187. Inc(NewBounds.Bottom, FRowHeight);
  188. until False;
  189. end;
  190. end;
  191. var
  192. I: Integer;
  193. W, H: Integer;
  194. CurClientRect: TRect;
  195. AdjustClientFrame: TRect;
  196. begin
  197. NewWidth := 0;
  198. NewHeight := 0;
  199. Result := True;
  200. Vertical := IsVertical;
  201. FRowWidth:= ButtonWidth;
  202. FRowHeight:= ButtonHeight;
  203. if Vertical then
  204. begin
  205. LeftToRight := True;
  206. end
  207. else begin
  208. LeftToRight := not UseRightToLeftAlignment;
  209. end;
  210. DisableAlign;
  211. BeginUpdate;
  212. try
  213. CurClientRect := ClientRect;
  214. if Vertical then
  215. Inc(CurClientRect.Bottom, UseSize - Height)
  216. else begin
  217. Inc(CurClientRect.Right, UseSize - Width);
  218. end;
  219. ARect := CurClientRect;
  220. AdjustClientRect(ARect);
  221. AdjustClientFrame.Left := ARect.Left - CurClientRect.Left;
  222. AdjustClientFrame.Top := ARect.Top - CurClientRect.Top;
  223. AdjustClientFrame.Right := CurClientRect.Right - ARect.Right;
  224. AdjustClientFrame.Bottom := CurClientRect.Bottom - ARect.Bottom;
  225. //DebugLn(['TToolBar.WrapButtons ',DbgSName(Self),' ARect=',dbgs(ARect)]);
  226. // important: top, left button must start in the AdjustClientRect top, left
  227. // otherwise Toolbar.AutoSize=true will create an endless loop
  228. if Vertical or LeftToRight then
  229. StartX := ARect.Left
  230. else begin
  231. StartX := ARect.Right;
  232. end;
  233. StartY := ARect.Top;
  234. X := StartX;
  235. Y := StartY;
  236. for I := 0 to ButtonList.Count - 1 do
  237. begin
  238. CurControl := TControl(ButtonList[I]);
  239. if not CurControl.IsControlVisible then
  240. Continue;
  241. CalculatePosition;
  242. W := CurControl.Width;
  243. H := CurControl.Height;
  244. if (not Simulate) and ((CurControl.Left <> X) or (CurControl.Top <> Y)) then
  245. begin
  246. CurControl.SetBounds(X, Y, W, H); // Note: do not use SetBoundsKeepBase
  247. end;
  248. // adjust NewWidth, NewHeight
  249. if LeftToRight then
  250. NewWidth := Max(NewWidth, X + W + AdjustClientFrame.Right)
  251. else begin
  252. NewWidth := Max(NewWidth, ARect.Right - X + ARect.Left + AdjustClientFrame.Right);
  253. end;
  254. NewHeight := Max(NewHeight, Y + H + AdjustClientFrame.Bottom);
  255. // step to next position
  256. if IsVertical then
  257. Inc(Y, H)
  258. else if LeftToRight then
  259. Inc(X, W);
  260. end;
  261. finally
  262. EndUpdate;
  263. EnableAlign;
  264. end;
  265. end;
  266. procedure Register;
  267. begin
  268. RegisterComponents('KASComponents', [TToolBarAdv]);
  269. RegisterNoIcon([TToolButtonClr]);
  270. end;
  271. end.