| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- unit KASComCtrls;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, Controls, ComCtrls, Graphics, Dialogs;
- type
- { TToolButtonClr }
- TToolButtonClr = class(TToolButton)
- private
- FButtonColor: TColor;
- FColorDialog: TColorDialog;
- procedure SetButtonColor(AValue: TColor);
- protected
- procedure Paint; override;
- procedure ShowColorDialog;
- public
- constructor Create(TheOwner: TComponent); override;
- procedure Click; override;
- property ButtonColor: TColor read FButtonColor write SetButtonColor;
- end;
- { TToolBarAdv }
- TToolBarAdv = class(TToolBar)
- private
- FToolBarFlags: TToolBarFlags;
- protected
- procedure CalculatePreferredSize(var PreferredWidth,
- PreferredHeight: Integer;
- {%H-}WithThemeSpace: Boolean); override;
- procedure AlignControls({%H-}AControl: TControl;
- var RemainingClientRect: TRect); override;
- function WrapButtons(UseSize: Integer; out NewWidth,
- NewHeight: Integer; Simulate: Boolean): Boolean;
- end;
- procedure Register;
- implementation
- uses
- Math;
- { TToolButtonClr }
- procedure TToolButtonClr.SetButtonColor(AValue: TColor);
- begin
- if FButtonColor <> AValue then
- begin
- FButtonColor:= AValue;
- Invalidate;
- end;
- end;
- procedure TToolButtonClr.Paint;
- var
- ARect, IconRect: TRect;
- begin
- inherited Paint;
- if (FToolBar <> nil) and (ClientWidth > 0) and (ClientHeight > 0) then
- begin
- ARect:= ClientRect;
- IconRect.Left:= (ARect.Width - FToolBar.ImagesWidth) div 2;
- IconRect.Top:= (ARect.Height - FToolBar.ImagesWidth) div 2;
- IconRect.Right:= IconRect.Left + FToolBar.ImagesWidth;
- IconRect.Bottom:= IconRect.Top + FToolBar.ImagesWidth;
- if Enabled then
- begin
- Canvas.Brush.Style:= bsSolid;
- Canvas.Brush.Color:= FButtonColor
- end
- else begin
- Canvas.Brush.Color:= clGrayText;
- Canvas.Brush.Style:= bsDiagCross;
- end;
- Canvas.Pen.Color:= clBtnText;
- Canvas.Rectangle(IconRect);
- end;
- end;
- procedure TToolButtonClr.ShowColorDialog;
- begin
- if not Enabled then Exit;
- if (FColorDialog = nil) then
- begin
- FColorDialog := TColorDialog.Create(Self);
- end;
- FColorDialog.Color := ButtonColor;
- if FColorDialog.Execute then
- begin
- ButtonColor := FColorDialog.Color;
- end;
- end;
- constructor TToolButtonClr.Create(TheOwner: TComponent);
- begin
- FButtonColor:= clRed;
- inherited Create(TheOwner);
- end;
- procedure TToolButtonClr.Click;
- begin
- inherited Click;
- ShowColorDialog;
- end;
- { TToolBarAdv }
- procedure TToolBarAdv.CalculatePreferredSize(var PreferredWidth,
- PreferredHeight: Integer; WithThemeSpace: Boolean);
- begin
- if IsVertical then
- WrapButtons(Height, PreferredWidth, PreferredHeight, True)
- else
- WrapButtons(Width, PreferredWidth, PreferredHeight, True);
- end;
- procedure TToolBarAdv.AlignControls(AControl: TControl;
- var RemainingClientRect: TRect);
- var
- NewWidth, NewHeight: integer;
- begin
- if tbfPlacingControls in FToolBarFlags then exit;
- Include(FToolBarFlags, tbfPlacingControls);
- DisableAlign;
- try
- AdjustClientRect(RemainingClientRect);
- if IsVertical then
- WrapButtons(Height, NewWidth, NewHeight, False)
- else
- WrapButtons(Width, NewWidth, NewHeight, False);
- finally
- Exclude(FToolBarFlags, tbfPlacingControls);
- EnableAlign;
- end;
- end;
- function TToolBarAdv.WrapButtons(UseSize: Integer; out NewWidth,
- NewHeight: Integer; Simulate: Boolean): Boolean;
- var
- ARect: TRect;
- X, Y: Integer;
- Vertical: Boolean;
- LeftToRight: Boolean;
- CurControl: TControl;
- StartX, StartY: Integer;
- FRowWidth, FRowHeight: Integer;
- procedure CalculatePosition;
- var
- NewBounds: TRect;
- StartedAtRowStart: Boolean;
- begin
- if IsVertical then
- begin
- NewBounds := Bounds(X, Y, FRowWidth, CurControl.Height);
- repeat
- if (not Wrapable) or
- (NewBounds.Top = StartY) or
- (NewBounds.Bottom <= ARect.Bottom) then
- begin
- // control fits into the column
- X := NewBounds.Left;
- Y := NewBounds.Top;
- Break;
- end;
- // try next column
- NewBounds.Top := StartY;
- NewBounds.Bottom := NewBounds.Top + CurControl.Height;
- Inc(NewBounds.Left, FRowWidth);
- Inc(NewBounds.Right, FRowWidth);
- until False;
- end
- else begin
- StartedAtRowStart := (X = StartX);
- if LeftToRight then
- NewBounds := Bounds(X, Y, CurControl.Width, FRowHeight)
- else begin
- NewBounds := Bounds(X - CurControl.Width, Y, CurControl.Width, FRowHeight);
- end;
- repeat
- if (not Wrapable) or
- (StartedAtRowStart) or
- (LeftToRight and ((NewBounds.Left = StartX) or (NewBounds.Right <= ARect.Right))) or
- ((not LeftToRight) and ((NewBounds.Right = StartX) or (NewBounds.Left >= ARect.Left))) then
- begin
- // control fits into the row
- X := NewBounds.Left;
- Y := NewBounds.Top;
- Break;
- end;
- StartedAtRowStart := True;
- // try next row
- if LeftToRight then
- begin
- NewBounds.Left := StartX;
- NewBounds.Right := NewBounds.Left + CurControl.Width;
- end else begin
- NewBounds.Right := StartX;
- NewBounds.Left := NewBounds.Right - CurControl.Width;
- end;
- Inc(NewBounds.Top, FRowHeight);
- Inc(NewBounds.Bottom, FRowHeight);
- until False;
- end;
- end;
- var
- I: Integer;
- W, H: Integer;
- CurClientRect: TRect;
- AdjustClientFrame: TRect;
- begin
- NewWidth := 0;
- NewHeight := 0;
- Result := True;
- Vertical := IsVertical;
- FRowWidth:= ButtonWidth;
- FRowHeight:= ButtonHeight;
- if Vertical then
- begin
- LeftToRight := True;
- end
- else begin
- LeftToRight := not UseRightToLeftAlignment;
- end;
- DisableAlign;
- BeginUpdate;
- try
- CurClientRect := ClientRect;
- if Vertical then
- Inc(CurClientRect.Bottom, UseSize - Height)
- else begin
- Inc(CurClientRect.Right, UseSize - Width);
- end;
- ARect := CurClientRect;
- AdjustClientRect(ARect);
- AdjustClientFrame.Left := ARect.Left - CurClientRect.Left;
- AdjustClientFrame.Top := ARect.Top - CurClientRect.Top;
- AdjustClientFrame.Right := CurClientRect.Right - ARect.Right;
- AdjustClientFrame.Bottom := CurClientRect.Bottom - ARect.Bottom;
- //DebugLn(['TToolBar.WrapButtons ',DbgSName(Self),' ARect=',dbgs(ARect)]);
- // important: top, left button must start in the AdjustClientRect top, left
- // otherwise Toolbar.AutoSize=true will create an endless loop
- if Vertical or LeftToRight then
- StartX := ARect.Left
- else begin
- StartX := ARect.Right;
- end;
- StartY := ARect.Top;
- X := StartX;
- Y := StartY;
- for I := 0 to ButtonList.Count - 1 do
- begin
- CurControl := TControl(ButtonList[I]);
- if not CurControl.IsControlVisible then
- Continue;
- CalculatePosition;
- W := CurControl.Width;
- H := CurControl.Height;
- if (not Simulate) and ((CurControl.Left <> X) or (CurControl.Top <> Y)) then
- begin
- CurControl.SetBounds(X, Y, W, H); // Note: do not use SetBoundsKeepBase
- end;
- // adjust NewWidth, NewHeight
- if LeftToRight then
- NewWidth := Max(NewWidth, X + W + AdjustClientFrame.Right)
- else begin
- NewWidth := Max(NewWidth, ARect.Right - X + ARect.Left + AdjustClientFrame.Right);
- end;
- NewHeight := Max(NewHeight, Y + H + AdjustClientFrame.Bottom);
- // step to next position
- if IsVertical then
- Inc(Y, H)
- else if LeftToRight then
- Inc(X, W);
- end;
- finally
- EndUpdate;
- EnableAlign;
- end;
- end;
- procedure Register;
- begin
- RegisterComponents('KASComponents', [TToolBarAdv]);
- RegisterNoIcon([TToolButtonClr]);
- end;
- end.
|