mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 04:16:06 +02:00
lcl: fix vertical toolbar button positioning + drawing of vertical separators
git-svn-id: trunk@30921 -
This commit is contained in:
parent
a75a29091c
commit
de0cfa211a
@ -1680,7 +1680,8 @@ type
|
||||
TToolBar = class(TToolWindow)
|
||||
private
|
||||
FButtonHeight: Integer;
|
||||
FRealizedButtonHeight: integer;
|
||||
FRealizedButtonHeight,
|
||||
FRealizedButtonWidth: integer;
|
||||
FButtons: TList;
|
||||
FButtonWidth: Integer;
|
||||
FDisabledImageChangeLink: TChangeLink;
|
||||
@ -1746,7 +1747,7 @@ type
|
||||
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
||||
procedure RepositionButton(Index: Integer);
|
||||
procedure RepositionButtons(Index: Integer);
|
||||
function WrapButtons(UseWidth: integer;
|
||||
function WrapButtons(UseSize: integer;
|
||||
out NewWidth, NewHeight: Integer;
|
||||
Simulate: boolean): Boolean;
|
||||
procedure CNDropDownClosed(var Message: TLMessage); message CN_DROPDOWNCLOSED;
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
}
|
||||
|
||||
function CompareToolBarControl(Control1, Control2: TControl): integer;
|
||||
function CompareToolBarControlHorz(Control1, Control2: TControl): integer;
|
||||
var
|
||||
ToolBar: TToolBar;
|
||||
Row1: Integer;
|
||||
@ -47,6 +47,34 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function CompareToolBarControlVert(Control1, Control2: TControl): integer;
|
||||
var
|
||||
ToolBar: TToolBar;
|
||||
Col1: Integer;
|
||||
Col2: Integer;
|
||||
HalfBtnWidth, BtnWidth: Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
if not (Control1.Parent is TToolBar) then Exit;
|
||||
|
||||
ToolBar := TToolBar(Control1.Parent);
|
||||
BtnWidth := ToolBar.FRealizedButtonWidth;
|
||||
if BtnWidth <= 0 then BtnWidth := 1;
|
||||
HalfBtnWidth := BtnWidth div 2;
|
||||
|
||||
Col1 := (Control1.Left + HalfBtnWidth) div BtnWidth;
|
||||
Col2 := (Control2.Left + HalfBtnWidth) div BtnWidth;
|
||||
Result := CompareValue(Col1, Col2);
|
||||
if Result = 0 then
|
||||
Result := CompareValue(Control1.Top, Control2.Top);
|
||||
if Result = 0 then
|
||||
begin
|
||||
Col1 := ToolBar.GetControlIndex(Control1);
|
||||
Col2 := ToolBar.GetControlIndex(Control2);
|
||||
Result := CompareValue(Col1, Col2);
|
||||
end;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TToolbar.Create
|
||||
Params: AOwner: the owner of the class
|
||||
@ -127,7 +155,10 @@ begin
|
||||
if tbfPlacingControls in FToolBarFlags then exit;
|
||||
Include(FToolBarFlags, tbfPlacingControls);
|
||||
try
|
||||
WrapButtons(Width, NewWidth, NewHeight, False);
|
||||
if IsVertical then
|
||||
WrapButtons(Height, NewWidth, NewHeight, False)
|
||||
else
|
||||
WrapButtons(Width, NewWidth, NewHeight, False);
|
||||
finally
|
||||
Exclude(FToolBarFlags, tbfPlacingControls);
|
||||
end;
|
||||
@ -211,8 +242,10 @@ end;
|
||||
|
||||
function TToolBar.IsVertical: Boolean;
|
||||
begin
|
||||
// any other logic?
|
||||
Result := Height > Width;
|
||||
if Align = alNone then
|
||||
Result := Height > Width
|
||||
else
|
||||
Result := Align in [alLeft, alRight];
|
||||
end;
|
||||
|
||||
class procedure TToolBar.WSRegisterClass;
|
||||
@ -506,19 +539,17 @@ end;
|
||||
If Wrapable=false, then the row is wrapped after the first button with
|
||||
Wrap=true.
|
||||
------------------------------------------------------------------------------}
|
||||
function TToolBar.WrapButtons(UseWidth: integer;
|
||||
function TToolBar.WrapButtons(UseSize: integer;
|
||||
out NewWidth, NewHeight: Integer; Simulate: boolean): Boolean;
|
||||
var
|
||||
ARect: TRect;
|
||||
x: Integer;
|
||||
y: Integer;
|
||||
NewControlWidth: Integer;
|
||||
x, y, w, h: Integer;
|
||||
NewControlWidth, NewControlHeight: Integer;
|
||||
CurControl: TControl;
|
||||
ObstacleControls: TFPList;
|
||||
FullSizeObstacleControls: TFPList;
|
||||
StartX: Integer;
|
||||
w: LongInt;
|
||||
h: LongInt;
|
||||
StartX, StartY: Integer;
|
||||
Vertical: Boolean;
|
||||
|
||||
procedure CalculatePosition;
|
||||
var
|
||||
@ -526,8 +557,7 @@ var
|
||||
NewBounds: TRect;
|
||||
SiblingBounds: TRect;
|
||||
j: Integer;
|
||||
PreferredBtnWidth: Integer;
|
||||
PreferredBtnHeight: Integer;
|
||||
PreferredBtnWidth, PreferredBtnHeight: Integer;
|
||||
Intersects: Boolean;
|
||||
IntersectsWithLimitedHeightControl: Boolean;
|
||||
StartedAtRowStart: Boolean;
|
||||
@ -538,24 +568,50 @@ var
|
||||
PreferredBtnWidth := 0;
|
||||
PreferredBtnHeight := 0;
|
||||
CurControl.GetPreferredSize(PreferredBtnWidth, PreferredBtnHeight);
|
||||
NewControlWidth := PreferredBtnWidth;
|
||||
if Vertical then
|
||||
begin
|
||||
NewControlHeight := PreferredBtnHeight;
|
||||
NewControlWidth := ButtonWidth;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NewControlHeight := ButtonHeight;
|
||||
NewControlWidth := PreferredBtnWidth;
|
||||
end;
|
||||
if (TToolButton(CurControl).Style in [tbsButton, tbsDropDown, tbsCheck]) then
|
||||
begin
|
||||
if Vertical then
|
||||
if (NewControlHeight < ButtonHeight) then
|
||||
NewControlHeight := ButtonHeight
|
||||
else
|
||||
else
|
||||
if (NewControlWidth < ButtonWidth) then
|
||||
NewControlWidth := ButtonWidth;
|
||||
end;
|
||||
end
|
||||
else
|
||||
if Vertical then
|
||||
begin
|
||||
NewControlWidth := ButtonWidth;
|
||||
NewControlHeight := CurControl.Height;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NewControlWidth := CurControl.Width;
|
||||
NewBounds := Bounds(x, y, NewControlWidth, ButtonHeight);
|
||||
NewControlHeight := ButtonHeight;
|
||||
end;
|
||||
NewBounds := Bounds(x, y, NewControlWidth, NewControlHeight);
|
||||
|
||||
//DebugLn(['CalculatePosition ',DbgSName(CurControl)]);
|
||||
StartedAtRowStart:=x=StartX;
|
||||
if Vertical then
|
||||
StartedAtRowStart := y = StartY
|
||||
else
|
||||
StartedAtRowStart := x = StartX;
|
||||
repeat
|
||||
// move control to the right, until it does not overlap
|
||||
IntersectsWithLimitedHeightControl:=false;
|
||||
j:=0;
|
||||
while j<ObstacleControls.Count do
|
||||
IntersectsWithLimitedHeightControl := False;
|
||||
j := 0;
|
||||
while j < ObstacleControls.Count do
|
||||
begin
|
||||
AlignedControl := TControl(ObstacleControls[j]);
|
||||
SiblingBounds := AlignedControl.BoundsRect;
|
||||
@ -563,34 +619,66 @@ var
|
||||
(SiblingBounds.Left < NewBounds.Right) and
|
||||
(SiblingBounds.Bottom > NewBounds.Top) and
|
||||
(SiblingBounds.Top < NewBounds.Bottom);
|
||||
if Intersects then begin
|
||||
if Intersects then
|
||||
begin
|
||||
//DebugLn(['CalculatePosition Move ',NewBounds.Left,'->',SiblingBounds.Right]);
|
||||
NewBounds.Left := SiblingBounds.Right;
|
||||
NewBounds.Right := NewBounds.Left + NewControlWidth;
|
||||
j:=0; // check again, needed, because ObstacleControls are not sorted
|
||||
if Vertical then
|
||||
begin
|
||||
NewBounds.Top := SiblingBounds.Bottom;
|
||||
NewBounds.Bottom := NewBounds.Top + NewControlHeight;
|
||||
end
|
||||
else
|
||||
begin
|
||||
NewBounds.Left := SiblingBounds.Right;
|
||||
NewBounds.Right := NewBounds.Left + NewControlWidth;
|
||||
end;
|
||||
j := 0; // check again, needed, because ObstacleControls are not sorted
|
||||
// (and can not be sorted, because they can overlap)
|
||||
if FullSizeObstacleControls.IndexOf(AlignedControl)<0 then
|
||||
IntersectsWithLimitedHeightControl:=true;
|
||||
end else
|
||||
if FullSizeObstacleControls.IndexOf(AlignedControl) < 0 then
|
||||
IntersectsWithLimitedHeightControl := True;
|
||||
end
|
||||
else
|
||||
inc(j);
|
||||
end;
|
||||
if (not Wrapable)
|
||||
or (NewBounds.Right <= ARect.Right) or (NewBounds.Left = StartX)
|
||||
or (StartedAtRowStart and not IntersectsWithLimitedHeightControl) then
|
||||
if Vertical then
|
||||
begin
|
||||
// control fits into the row
|
||||
//DebugLn(['CalculatePosition fits: ',DbgSName(CurControl),' ',dbgs(NewBounds)]);
|
||||
x := NewBounds.Left;
|
||||
y := NewBounds.Top;
|
||||
break;
|
||||
end;
|
||||
if (not Wrapable) or
|
||||
(NewBounds.Bottom <= ARect.Bottom) or (NewBounds.Top = StartY) or
|
||||
(StartedAtRowStart and not IntersectsWithLimitedHeightControl) then
|
||||
begin
|
||||
// control fits into the row
|
||||
//DebugLn(['CalculatePosition fits: ',DbgSName(CurControl),' ',dbgs(NewBounds)]);
|
||||
x := NewBounds.Left;
|
||||
y := NewBounds.Top;
|
||||
break;
|
||||
end;
|
||||
|
||||
// try next row
|
||||
NewBounds.Left := StartX;
|
||||
NewBounds.Right := NewBounds.Left + NewControlWidth;
|
||||
inc(NewBounds.Top, ButtonHeight);
|
||||
inc(NewBounds.Bottom, ButtonHeight);
|
||||
StartedAtRowStart:=true;
|
||||
// try next row
|
||||
NewBounds.Top := StartY;
|
||||
NewBounds.Bottom := NewBounds.Top + NewControlHeight;
|
||||
inc(NewBounds.Left, ButtonWidth);
|
||||
inc(NewBounds.Right, ButtonWidth);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (not Wrapable) or
|
||||
(NewBounds.Right <= ARect.Right) or (NewBounds.Left = StartX) or
|
||||
(StartedAtRowStart and not IntersectsWithLimitedHeightControl) then
|
||||
begin
|
||||
// control fits into the row
|
||||
//DebugLn(['CalculatePosition fits: ',DbgSName(CurControl),' ',dbgs(NewBounds)]);
|
||||
x := NewBounds.Left;
|
||||
y := NewBounds.Top;
|
||||
break;
|
||||
end;
|
||||
|
||||
// try next row
|
||||
NewBounds.Left := StartX;
|
||||
NewBounds.Right := NewBounds.Left + NewControlWidth;
|
||||
inc(NewBounds.Top, ButtonHeight);
|
||||
inc(NewBounds.Bottom, ButtonHeight);
|
||||
end;
|
||||
StartedAtRowStart := True;
|
||||
//DebugLn('CalculatePosition Next Row ',DbgSName(CurControl),' ',dbgs(NewBounds));
|
||||
until false;
|
||||
end;
|
||||
@ -618,6 +706,7 @@ var
|
||||
begin
|
||||
//DebugLn(['WrapButtons ',DbgSName(Self),' Wrapable=',Wrapable,' ',dbgs(BoundsRect)]);
|
||||
Result := True;
|
||||
Vertical := IsVertical;
|
||||
NewWidth := 0;
|
||||
NewHeight := 0;
|
||||
ObstacleControls := TFPList.Create;
|
||||
@ -628,7 +717,10 @@ begin
|
||||
DisableAlign;
|
||||
BeginUpdate;
|
||||
try
|
||||
GrowSide:=akBottom;
|
||||
if Vertical then
|
||||
GrowSide := akRight
|
||||
else
|
||||
GrowSide := akBottom;
|
||||
for i:=0 to ControlCount-1 do
|
||||
begin
|
||||
CurControl := Controls[i];
|
||||
@ -654,11 +746,19 @@ begin
|
||||
// sort OrderedControls
|
||||
if FRealizedButtonHeight = 0 then
|
||||
FRealizedButtonHeight := FButtonHeight;
|
||||
OrderedControls.Sort(TListSortCompare(@CompareToolBarControl));
|
||||
if FRealizedButtonWidth = 0 then
|
||||
FRealizedButtonWidth := FButtonWidth;
|
||||
if Vertical then
|
||||
OrderedControls.Sort(TListSortCompare(@CompareToolBarControlVert))
|
||||
else
|
||||
OrderedControls.Sort(TListSortCompare(@CompareToolBarControlHorz));
|
||||
|
||||
// position OrderedControls
|
||||
CurClientRect := ClientRect;
|
||||
inc(CurClientRect.Right, UseWidth - Width);
|
||||
if Vertical then
|
||||
inc(CurClientRect.Bottom, UseSize - Height)
|
||||
else
|
||||
inc(CurClientRect.Right, UseSize - Width);
|
||||
ARect := CurClientRect;
|
||||
AdjustClientRect(ARect);
|
||||
AdjustClientFrame.Left := ARect.Left - CurClientRect.Left;
|
||||
@ -669,8 +769,9 @@ begin
|
||||
// important: top, left button must start in the AdjustClientRect top, left
|
||||
// otherwise Toolbar.AutoSize=true will create an endless loop
|
||||
StartX := ARect.Left;
|
||||
StartY := ARect.Top;
|
||||
x := StartX;
|
||||
y := ARect.Top;
|
||||
y := StartY;
|
||||
for i := 0 to OrderedControls.Count - 1 do
|
||||
begin
|
||||
CurControl := TControl(OrderedControls[i]);
|
||||
@ -678,20 +779,19 @@ begin
|
||||
Continue;
|
||||
CalculatePosition;
|
||||
//DebugLn(['WrapButtons ',CurControl.Name,':',CurControl.ClassName,' ',x,',',y,',',CurControl.Width,'x',CurControl.Height]);
|
||||
if ButtonHeight <= 0 then
|
||||
h := CurControl.Height
|
||||
else
|
||||
h := ButtonHeight;
|
||||
if CurControl.AutoSize then
|
||||
begin
|
||||
w := CurControl.Width;
|
||||
h := CurControl.Height;
|
||||
end
|
||||
else
|
||||
begin
|
||||
w := NewControlWidth;
|
||||
h := NewControlHeight;
|
||||
end;
|
||||
|
||||
w := CurControl.Constraints.MinMaxWidth(w);
|
||||
h := CurControl.Constraints.MinMaxWidth(h);
|
||||
h := CurControl.Constraints.MinMaxHeight(h);
|
||||
if (CurControl.Left <> x) or (CurControl.Top <> y) or
|
||||
(CurControl.Width <> w) or (CurControl.Height <> h) then
|
||||
begin
|
||||
@ -709,15 +809,33 @@ begin
|
||||
NewHeight := Max(NewHeight, y + h + AdjustClientFrame.Bottom);
|
||||
|
||||
// step to next position
|
||||
inc(x,w);
|
||||
if (not Wrapable) and (CurControl is TToolButton) and
|
||||
(TToolButton(CurControl).Wrap) then
|
||||
if Vertical then
|
||||
begin
|
||||
// user forced wrap -> start new line
|
||||
x := StartX;
|
||||
inc(y, ButtonHeight);
|
||||
if not Simulate then
|
||||
inc(FRowCount);
|
||||
inc(y, h);
|
||||
if not Wrapable and
|
||||
(CurControl is TToolButton) and
|
||||
(TToolButton(CurControl).Wrap) then
|
||||
begin
|
||||
// user forced wrap -> start new line
|
||||
y := StartY;
|
||||
inc(x, ButtonWidth);
|
||||
if not Simulate then
|
||||
inc(FRowCount);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
inc(x, w);
|
||||
if not Wrapable and
|
||||
(CurControl is TToolButton) and
|
||||
(TToolButton(CurControl).Wrap) then
|
||||
begin
|
||||
// user forced wrap -> start new line
|
||||
x := StartX;
|
||||
inc(y, ButtonHeight);
|
||||
if not Simulate then
|
||||
inc(FRowCount);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
FRealizedButtonHeight := FButtonHeight;
|
||||
|
@ -174,18 +174,18 @@ procedure TToolButton.Paint;
|
||||
// on windows 7 divider can't be less than 4 pixels
|
||||
if FToolBar.IsVertical then
|
||||
begin
|
||||
if (ARect.Bottom - ARect.Top) > 4 then
|
||||
if (ARect.Bottom - ARect.Top) > 5 then
|
||||
begin
|
||||
ARect.Top := (ARect.Top + ARect.Bottom) div 2 - 2;
|
||||
ARect.Bottom := ARect.Top + 4;
|
||||
ARect.Top := (ARect.Top + ARect.Bottom) div 2 - 3;
|
||||
ARect.Bottom := ARect.Top + 5;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (ARect.Right - ARect.Left) > 4 then
|
||||
if (ARect.Right - ARect.Left) > 5 then
|
||||
begin
|
||||
ARect.Left := (ARect.Left + ARect.Right) div 2 - 2;
|
||||
ARect.Right := ARect.Left + 4;
|
||||
ARect.Left := (ARect.Left + ARect.Right) div 2 - 3;
|
||||
ARect.Right := ARect.Left + 5;
|
||||
end;
|
||||
end;
|
||||
ThemeServices.DrawElement(Canvas.GetUpdatedHandle([csBrushValid, csPenValid]),
|
||||
@ -202,12 +202,12 @@ procedure TToolButton.Paint;
|
||||
begin
|
||||
if FToolBar.IsVertical then
|
||||
begin
|
||||
if (ARect.Bottom - ARect.Top) > 8 then
|
||||
if (ARect.Bottom - ARect.Top) > 10 then
|
||||
begin
|
||||
ARect.Top := (ARect.Top + ARect.Bottom) div 2 - 4;
|
||||
ARect.Bottom := ARect.Top + 4;
|
||||
ARect.Top := (ARect.Top + ARect.Bottom) div 2 - 5;
|
||||
ARect.Bottom := ARect.Top + 5;
|
||||
DrawDivider(Details, ARect);
|
||||
OffsetRect(ARect, 0, 4);
|
||||
OffsetRect(ARect, 0, 5);
|
||||
DrawDivider(Details, ARect);
|
||||
end
|
||||
else
|
||||
@ -215,12 +215,12 @@ procedure TToolButton.Paint;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (ARect.Right - ARect.Left) > 8 then
|
||||
if (ARect.Right - ARect.Left) > 10 then
|
||||
begin
|
||||
ARect.Left := (ARect.Left + ARect.Right) div 2 - 4;
|
||||
ARect.Right := ARect.Left + 4;
|
||||
ARect.Left := (ARect.Left + ARect.Right) div 2 - 5;
|
||||
ARect.Right := ARect.Left + 5;
|
||||
DrawDivider(Details, ARect);
|
||||
OffsetRect(ARect, 4, 0);
|
||||
OffsetRect(ARect, 5, 0);
|
||||
DrawDivider(Details, ARect);
|
||||
end
|
||||
else
|
||||
@ -1014,10 +1014,16 @@ begin
|
||||
end
|
||||
else
|
||||
if Style = tbsDivider then
|
||||
PreferredWidth := 4
|
||||
if FToolBar.IsVertical then
|
||||
PreferredHeight := 5
|
||||
else
|
||||
PreferredWidth := 5
|
||||
else
|
||||
if Style = tbsSeparator then
|
||||
PreferredWidth := 8;
|
||||
if FToolBar.IsVertical then
|
||||
PreferredHeight := 10
|
||||
else
|
||||
PreferredWidth := 10;
|
||||
end;
|
||||
//DebugLn(['TToolButton.CalculatePreferredSize ',DbgSName(Self),' ',PreferredWidth,',',PreferredHeight,' Caption=',Caption]);
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user