mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-13 11:39:13 +02:00
fixed TSplitter resizing for alBottom, alRight from Pawel Piwowar
git-svn-id: trunk@6853 -
This commit is contained in:
parent
5baf8a8fef
commit
e2f04f299f
@ -20,7 +20,6 @@
|
||||
ToDo:
|
||||
- Fix changing Mouse cursor
|
||||
- Fix gtk look
|
||||
- AutoSnap
|
||||
- ResizeStyle
|
||||
|
||||
}
|
||||
@ -56,9 +55,9 @@ procedure TCustomSplitter.StartSplitterMove(Restart: boolean;
|
||||
const MouseXY: TPoint);
|
||||
begin
|
||||
if (not Restart) and FSplitDragging then exit;
|
||||
FSplitDragging:=true;
|
||||
FSplitDragging := True;
|
||||
fSplitterStartMouseXY:=MouseXY;
|
||||
fSplitterStartLeftTop:=Point(Left,Top);
|
||||
fSplitterStartLeftTop:= Point(Left,Top);
|
||||
end;
|
||||
|
||||
procedure TCustomSplitter.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
|
||||
@ -69,76 +68,303 @@ begin
|
||||
inherited MouseDown(Button, Shift, X, Y);
|
||||
// While resizing X, Y are not valid. Use absolute mouse position.
|
||||
GetCursorPos(MousePos);
|
||||
StartSplitterMove(true,MousePos);
|
||||
StartSplitterMove(True,MousePos);
|
||||
end;
|
||||
|
||||
function FindOppositeControl(Control: TControl): TControl;
|
||||
var
|
||||
i,count: Integer;
|
||||
CurControl: TControl;
|
||||
fRect: TRect;
|
||||
fPoint: TPoint;
|
||||
alignList: TAlignSet;
|
||||
begin
|
||||
Result := nil;
|
||||
count := Control.Parent.ControlCount;
|
||||
if count > 0 then begin
|
||||
fRect := Control.BoundsRect;
|
||||
case Control.Align of
|
||||
alTop: begin
|
||||
fPoint := fRect.BottomRight;
|
||||
fPoint.y := fPoint.y+1;
|
||||
Dec(fPoint.x);
|
||||
alignList := [alTop,alRight,alClient];
|
||||
end;
|
||||
alBottom: begin
|
||||
fPoint := fRect.TopLeft;
|
||||
Dec(fPoint.y);
|
||||
alignList := [alLeft,alBottom,alClient];
|
||||
end;
|
||||
alLeft: begin
|
||||
fPoint := fRect.BottomRight;
|
||||
Inc(fPoint.x);
|
||||
Dec(fPoint.y);
|
||||
alignList := [alLeft,alClient];
|
||||
end;
|
||||
alRight: begin
|
||||
fPoint := fRect.TopLeft;
|
||||
Dec(fPoint.x);
|
||||
alignList := [alRight,alClient];
|
||||
end;
|
||||
end; // case
|
||||
Dec(count);
|
||||
for i := 0 to count do begin
|
||||
CurControl := Control.Parent.Controls[i];
|
||||
if (CurControl <> Control)
|
||||
and CurControl.Visible
|
||||
and (CurControl.Align in alignList)
|
||||
and (PtInRect(CurControl.BoundsRect, fPoint))
|
||||
then Result := CurControl;
|
||||
if Assigned(Result) then Break;
|
||||
end; // for i
|
||||
end;
|
||||
end;
|
||||
|
||||
function FindVirtualOppositeControl(Control: TControl): TControl;
|
||||
function CompPos(CurControl, Control: TControl): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
case Control.Align of
|
||||
alTop:
|
||||
if (CurControl.Align = Control.Align)
|
||||
and (CurControl.Top >= Control.BoundsRect.Bottom)
|
||||
then Result := True;
|
||||
alBottom:
|
||||
if (CurControl.Align = Control.Align)
|
||||
and (CurControl.BoundsRect.Bottom <= Control.Top)
|
||||
then Result := True;
|
||||
alLeft:
|
||||
if (CurControl.Align = Control.Align)
|
||||
and (CurControl.Left >= Control.BoundsRect.Right)
|
||||
then Result := True;
|
||||
alRight:
|
||||
if (CurControl.Align = Control.Align)
|
||||
and (CurControl.BoundsRect.Right <= Control.Left)
|
||||
then Result := True;
|
||||
end;
|
||||
end;
|
||||
function OppositeControl(CurControl,Control: TControl): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
case Control.Align of
|
||||
alLeft: if (CurControl.Align = alRight) then Result := True;
|
||||
alRight: if (CurControl.Align = alLeft) then Result := True;
|
||||
alTop: if (CurControl.Align = alBottom) then Result := True;
|
||||
alBottom: if (CurControl.Align = alTop) then Result := True;
|
||||
end;
|
||||
end;
|
||||
var
|
||||
i,count: Integer;
|
||||
CurControl: TControl;
|
||||
begin
|
||||
Result := nil;
|
||||
count := Control.Parent.ControlCount;
|
||||
if count > 0 then begin
|
||||
Dec(count);
|
||||
for i := 0 to count do begin
|
||||
CurControl := Control.Parent.Controls[i];
|
||||
if (CurControl <> Control) then begin
|
||||
if ((Result = nil) and OppositeControl(CurControl, Control))
|
||||
or (Assigned(Result) and CompPos(CurControl, Result))
|
||||
then Result := CurControl;
|
||||
end;
|
||||
end; // for i
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomSplitter.MouseMove(Shift: TShiftState; X, Y: Integer);
|
||||
var
|
||||
AlignControl, LastControl, VirtualOppositeControl, ClientControl: TControl;
|
||||
|
||||
function GetParentClientSize: Integer;
|
||||
begin
|
||||
case Self.Align of
|
||||
alLeft, alRight: Result := Parent.ClientWidth;
|
||||
alTop, alBottom: Result := Parent.ClientHeight;
|
||||
end;
|
||||
end;
|
||||
function GetControlMinPos(Control: TControl): Integer;
|
||||
begin
|
||||
if Assigned(Control)
|
||||
then case Self.Align of
|
||||
alLeft,alRight: Result := Control.Left;
|
||||
alTop,alBottom: Result := Control.Top;
|
||||
end
|
||||
else case Self.Align of
|
||||
alLeft,alTop: Result := 0;
|
||||
alRight,alBottom: Result := GetParentClientSize;
|
||||
end;
|
||||
end;
|
||||
function GetControlSize(Control: TControl): Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
if Assigned(Control)
|
||||
then case Self.Align of
|
||||
alLeft, alRight: Result := Control.Width;
|
||||
alTop, alBottom: Result := Control.Height;
|
||||
end;
|
||||
end;
|
||||
function GetControlConstraintsMinSize(Control: TControl): Integer;
|
||||
begin
|
||||
case Self.Align of
|
||||
alLeft, alRight: Result := Control.Constraints.MinWidth;
|
||||
alTop, alBottom: Result := Control.Constraints.MinHeight;
|
||||
end;
|
||||
end;
|
||||
procedure SetAlignControlSize(NewSize: Integer);
|
||||
begin
|
||||
case Self.Align of
|
||||
alLeft:
|
||||
AlignControl.Width := NewSize;
|
||||
alRight:
|
||||
begin
|
||||
Parent.DisableAlign;
|
||||
AlignControl.Left := AlignControl.Left + (AlignControl.Width - NewSize);
|
||||
AlignControl.Width := NewSize;
|
||||
Parent.EnableAlign;
|
||||
end;
|
||||
alTop:
|
||||
AlignControl.Height := NewSize;
|
||||
alBottom:
|
||||
begin
|
||||
Parent.DisableAlign;
|
||||
AlignControl.Top := AlignControl.Top + (AlignControl.Height - NewSize);
|
||||
AlignControl.Height := NewSize;
|
||||
Parent.EnableAlign;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
function CalcNewSize(StartSize, EndSize, Offset: Integer): Integer;
|
||||
var
|
||||
NewSize: Integer;
|
||||
begin
|
||||
NewSize := GetControlSize(AlignControl);
|
||||
case Self.Align of
|
||||
alLeft, alTop: Inc(NewSize, Offset);
|
||||
alRight, alBottom: Dec(NewSize, Offset);
|
||||
end;
|
||||
|
||||
if NewSize > EndSize then NewSize := EndSize;
|
||||
if NewSize < StartSize then NewSize := StartSize;
|
||||
|
||||
if fAutoSnap and (NewSize < fMinSize)
|
||||
then NewSize := StartSize;
|
||||
Result := NewSize;
|
||||
end;
|
||||
function GetVirtualControlMinPos(Control: TControl): Integer;
|
||||
begin
|
||||
case Self.Align of
|
||||
alLeft: Result := Control.Left;
|
||||
alRight: Result := Control.BoundsRect.Right;
|
||||
alTop: Result := Control.Top;
|
||||
alBottom: Result := Control.BoundsRect.Bottom;
|
||||
end;
|
||||
end;
|
||||
function CalcOffset(X,Y: Integer): Integer;
|
||||
begin
|
||||
case Self.Align of
|
||||
alLeft, alRight:
|
||||
Result := (X-fSplitterStartMouseXY.X)
|
||||
- (Self.Left-fSplitterStartLeftTop.X);
|
||||
alTop, alBottom:
|
||||
Result := (Y-fSplitterStartMouseXY.Y)
|
||||
- (Self.Top-fSplitterStartLeftTop.Y);
|
||||
end;
|
||||
end;
|
||||
function FindClientControl: TControl;
|
||||
var
|
||||
CurControl: TControl;
|
||||
count: Integer;
|
||||
begin
|
||||
Result := nil;
|
||||
for count := Parent.ControlCount-1 downto 0 do begin
|
||||
CurControl := Parent.Controls[count];
|
||||
if (CurControl <> Self)
|
||||
and ((CurControl.Align = alClient)
|
||||
or ((Self.Align in [alTop,alBottom])
|
||||
and (CurControl.Align in [alLeft,alRight]))) then begin
|
||||
Result := CurControl;
|
||||
Break;
|
||||
end;
|
||||
end; // for count
|
||||
end; // function FindClientControl
|
||||
function FindLastControl(Control: TControl): TControl;
|
||||
var
|
||||
CurControl: TControl;
|
||||
begin
|
||||
CurControl := Control;
|
||||
while Assigned(CurControl) do begin
|
||||
Control := CurControl;
|
||||
CurControl := FindOppositeControl(Control);
|
||||
end;
|
||||
Result := Control;
|
||||
end; // function FindLastControl
|
||||
var
|
||||
Offset: Integer;
|
||||
MinLeft: Integer;
|
||||
MaxLeft: Integer;
|
||||
NewLeft: Integer;
|
||||
AlignControl: TControl;
|
||||
MinTop: Integer;
|
||||
MaxTop: Integer;
|
||||
NewTop: Integer;
|
||||
StartSize: Integer;
|
||||
EndSize: Integer;
|
||||
NewSize: Integer;
|
||||
MousePos: TPoint;
|
||||
begin
|
||||
inherited MouseMove(Shift, X, Y);
|
||||
if (ssLeft in Shift) and (Parent<>nil) then begin
|
||||
if not (Self.Align in [alLeft, alRight, alTop, alBottom]) then Exit;
|
||||
if (ssLeft in Shift) and (Parent <> nil) then begin
|
||||
AlignControl := FindAlignControl;
|
||||
if not Assigned(AlignControl) then Exit;
|
||||
|
||||
// While resizing X, Y are not valid. Use absolute mouse position.
|
||||
GetCursorPos(MousePos);
|
||||
StartSplitterMove(false,MousePos);
|
||||
if Align in [alLeft,alRight] then begin
|
||||
Offset:=(MousePos.X-fSplitterStartMouseXY.X)
|
||||
-(Left-fSplitterStartLeftTop.X);
|
||||
if Offset=0 then exit;
|
||||
MinLeft:=0;
|
||||
MaxLeft:=Parent.ClientWidth-Width;
|
||||
AlignControl:=FindAlignControl;
|
||||
if AlignControl<>nil then
|
||||
if Align=alLeft then
|
||||
MinLeft:=AlignControl.Left+MinSize
|
||||
else
|
||||
MaxLeft:=Parent.ClientWidth-Width-MinSize;
|
||||
NewLeft:=Left+Offset;
|
||||
if NewLeft>MaxLeft then NewLeft:=MaxLeft;
|
||||
if NewLeft<MinLeft then NewLeft:=MinLeft;
|
||||
AlignControl:=FindAlignControl;
|
||||
if not CheckNewSize(NewLeft) then exit;
|
||||
if AlignControl<>nil then begin
|
||||
if Align=alLeft then
|
||||
AlignControl.Width:=NewLeft-AlignControl.Left
|
||||
else
|
||||
AlignControl.Left:=NewLeft+Width;
|
||||
end else
|
||||
Left:=NewLeft;
|
||||
end
|
||||
else if Align in [alTop, alBottom] then begin
|
||||
Offset:=(MousePos.Y-fSplitterStartMouseXY.Y)
|
||||
-(Top-fSplitterStartLeftTop.Y);
|
||||
if Offset=0 then exit;
|
||||
MinTop:=0;
|
||||
MaxTop:=Parent.ClientHeight-Height;
|
||||
AlignControl:=FindAlignControl;
|
||||
if AlignControl<>nil then
|
||||
if Align=alTop then
|
||||
MinTop:=AlignControl.Top+MinSize
|
||||
else
|
||||
MaxTop:=Parent.ClientHeight-Height-MinSize;
|
||||
NewTop:=Top+Offset;
|
||||
if NewTop>MaxTop then NewTop:=MaxTop;
|
||||
if NewTop<MinTop then NewTop:=MinTop;
|
||||
AlignControl:=FindAlignControl;
|
||||
if not CheckNewSize(NewLeft) then exit;
|
||||
if AlignControl<>nil then begin
|
||||
if Align=alTop then
|
||||
AlignControl.Height:=NewTop-AlignControl.Top
|
||||
else
|
||||
AlignControl.Top:=NewTop+Height;
|
||||
end else
|
||||
Top:=NewTop;
|
||||
StartSplitterMove(False,MousePos);
|
||||
|
||||
Offset := CalcOffset(MousePos.X, MousePos.Y);
|
||||
if Offset = 0 then Exit;
|
||||
|
||||
ClientControl := FindClientControl;
|
||||
|
||||
StartSize := 1;
|
||||
if not fAutoSnap
|
||||
then Inc(StartSize, Max(fMinSize, GetControlConstraintsMinSize(AlignControl)));
|
||||
if StartSize > 1 then Dec(StartSize);
|
||||
|
||||
if Assigned(ClientControl)
|
||||
then EndSize := GetControlSize(AlignControl)
|
||||
+ GetControlSize(ClientControl)
|
||||
- fMinSize
|
||||
else begin
|
||||
VirtualOppositeControl := FindVirtualOppositeControl(Self);
|
||||
LastControl := FindLastControl(Self);
|
||||
case Self.Align of
|
||||
alLeft, alTop: begin
|
||||
if Assigned(VirtualOppositeControl) then
|
||||
begin
|
||||
EndSize := GetControlSize(AlignControl)
|
||||
+ (GetControlMinPos(VirtualOppositeControl)
|
||||
- (GetControlMinPos(LastControl)
|
||||
+ GetControlSize(LastControl)));
|
||||
end
|
||||
else EndSize := GetControlSize(AlignControl)
|
||||
+ (GetParentClientSize
|
||||
- GetControlMinPos(LastControl)
|
||||
- GetControlSize(LastControl))
|
||||
end;
|
||||
|
||||
alRight, alBottom: begin
|
||||
if Assigned(VirtualOppositeControl) then
|
||||
EndSize := GetControlSize(AlignControl)
|
||||
+ (GetControlMinPos(LastControl)
|
||||
- (GetControlMinPos(VirtualOppositeControl)
|
||||
+ GetControlSize(VirtualOppositeControl)))
|
||||
else EndSize := GetControlSize(AlignControl)
|
||||
+ GetControlMinPos(LastControl);
|
||||
end;
|
||||
end; // case Self.Align
|
||||
end;
|
||||
|
||||
NewSize := CalcNewSize(StartSize, EndSize, Offset);
|
||||
|
||||
// OnCanResize event
|
||||
if CheckNewSize(NewSize)
|
||||
then SetAlignControlSize(NewSize);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -146,9 +372,10 @@ procedure TCustomSplitter.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
|
||||
Y: Integer);
|
||||
begin
|
||||
inherited MouseUp(Button, Shift, X, Y);
|
||||
if not (Self.Align in [alLeft,alTop,alRight,alBottom]) then Exit;
|
||||
if FSplitDragging then begin
|
||||
if Assigned(OnMoved) then OnMoved(Self);
|
||||
FSplitDragging:=false;
|
||||
FSplitDragging := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -157,26 +384,33 @@ var
|
||||
i: Integer;
|
||||
CurControl: TControl;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (Parent=nil) then exit;
|
||||
for i:=Parent.ControlCount-1 downto 0 do begin
|
||||
CurControl:=Parent.Controls[i];
|
||||
if (CurControl.Align in ([alClient,Align]))
|
||||
and (CurControl.Visible)
|
||||
and (((Align=alLeft) and (CurControl.Left<Left))
|
||||
or ((Align=alTop) and (CurControl.Top<Top))
|
||||
or ((Align=alRight) and (CurControl.Left>Left))
|
||||
or ((Align=alBottom) and (CurControl.Top>Top)))
|
||||
Result := nil;
|
||||
if (Parent = nil) then Exit;
|
||||
for i := Parent.ControlCount-1 downto 0 do begin
|
||||
CurControl := Parent.Controls[i];
|
||||
if (CurControl <> Self)
|
||||
and (CurControl.Visible)
|
||||
and (CurControl.Align = Self.Align)
|
||||
then begin
|
||||
// candidate found
|
||||
if (Result=nil)
|
||||
or (((Align=alLeft) and (CurControl.Left>Result.Left))
|
||||
or ((Align=alTop) and (CurControl.Top>Result.Top))
|
||||
or ((Align=alRight) and (CurControl.Left<Result.Left))
|
||||
or ((Align=alBottom) and (CurControl.Top<Result.Top)))
|
||||
then
|
||||
// better candidate found
|
||||
Result:=CurControl;
|
||||
case Self.Align of
|
||||
alLeft:
|
||||
if (CurControl.Height = Self.Height)
|
||||
and (CurControl.Left+CurControl.Width = Self.Left)
|
||||
then Result := CurControl;
|
||||
alTop:
|
||||
if (CurControl.Width = Self.Width)
|
||||
and (CurControl.Top+CurControl.Height = Self.Top)
|
||||
then Result := CurControl;
|
||||
alRight:
|
||||
if (CurControl.Height = Self.Height)
|
||||
and (CurControl.Left-Self.Width = Self.Left)
|
||||
then Result := CurControl;
|
||||
alBottom:
|
||||
if (CurControl.Width = Self.Width)
|
||||
and (CurControl.Top-Self.Height = Self.Top)
|
||||
then Result := CurControl;
|
||||
end; // case Self.Align
|
||||
if Assigned(Result) then Break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -187,18 +421,18 @@ var
|
||||
OldWidth: Integer;
|
||||
OldHeight: Integer;
|
||||
begin
|
||||
if (Align=Value) or (not (Value in [alLeft,alTop,alRight,alBottom])) then
|
||||
exit;
|
||||
OldWidth:=Width;
|
||||
OldHeight:=Height;
|
||||
OldAlign:=Align;
|
||||
if (Self.Align = Value)
|
||||
or (not (Value in [alLeft,alTop,alRight,alBottom]))
|
||||
then Exit;
|
||||
OldWidth := Self.Width;
|
||||
OldHeight := Self.Height;
|
||||
OldAlign := Self.Align;
|
||||
inherited SetAlign(Value);
|
||||
if Self.Align in [alLeft,alRight]
|
||||
then Self.Cursor := crHSplit
|
||||
else Self.Cursor := crVSplit;
|
||||
CheckAlignment;
|
||||
if Align in [alLeft,alRight] then begin
|
||||
Cursor:=crHSplit;
|
||||
end else begin
|
||||
Cursor:=crVSplit;
|
||||
end;
|
||||
|
||||
if (OldAlign in [alLeft,alRight])=(Align in [alLeft,alRight]) then begin
|
||||
// keep width and height
|
||||
SetBounds(Left,Top,OldWidth,OldHeight);
|
||||
@ -210,7 +444,7 @@ end;
|
||||
|
||||
procedure TCustomSplitter.SetAnchors(const AValue: TAnchors);
|
||||
begin
|
||||
if AValue=Anchors then exit;
|
||||
if AValue = Anchors then exit;
|
||||
inherited SetAnchors(AValue);
|
||||
CheckAlignment;
|
||||
end;
|
||||
@ -218,16 +452,16 @@ end;
|
||||
procedure TCustomSplitter.CheckAlignment;
|
||||
begin
|
||||
case Align of
|
||||
alLeft: Anchors:=Anchors-[akRight]+[akLeft];
|
||||
alTop: Anchors:=Anchors-[akBottom]+[akTop];
|
||||
alRight: Anchors:=Anchors+[akRight]-[akLeft];
|
||||
alBottom: Anchors:=Anchors+[akBottom]-[akTop];
|
||||
alLeft: Anchors:=Anchors-[akRight]+[akLeft];
|
||||
alTop: Anchors:=Anchors-[akBottom]+[akTop];
|
||||
alRight: Anchors:=Anchors+[akRight]-[akLeft];
|
||||
alBottom: Anchors:=Anchors+[akBottom]-[akTop];
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCustomSplitter.CheckNewSize(var NewSize: integer): boolean;
|
||||
function TCustomSplitter.CheckNewSize(var NewSize: Integer): Boolean;
|
||||
begin
|
||||
Result:=true;
|
||||
Result := True;
|
||||
if Assigned(OnCanResize) then
|
||||
OnCanResize(Self,NewSize,Result);
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user