From de0cfa211a54fa6f60916a20c43296f3e747c7cd Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 27 May 2011 06:39:29 +0000 Subject: [PATCH] lcl: fix vertical toolbar button positioning + drawing of vertical separators git-svn-id: trunk@30921 - --- lcl/comctrls.pp | 5 +- lcl/include/toolbar.inc | 234 ++++++++++++++++++++++++++++--------- lcl/include/toolbutton.inc | 38 +++--- 3 files changed, 201 insertions(+), 76 deletions(-) diff --git a/lcl/comctrls.pp b/lcl/comctrls.pp index 105faf68c1..d30c644568 100644 --- a/lcl/comctrls.pp +++ b/lcl/comctrls.pp @@ -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; diff --git a/lcl/include/toolbar.inc b/lcl/include/toolbar.inc index 5c97073387..46cb404ad9 100644 --- a/lcl/include/toolbar.inc +++ b/lcl/include/toolbar.inc @@ -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 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; diff --git a/lcl/include/toolbutton.inc b/lcl/include/toolbutton.inc index 5705316549..68c5959227 100644 --- a/lcl/include/toolbutton.inc +++ b/lcl/include/toolbutton.inc @@ -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;