mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 02:57:59 +02:00
1034 lines
35 KiB
ObjectPascal
1034 lines
35 KiB
ObjectPascal
{
|
|
*****************************************************************************
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
|
|
Authors: Michael W. Vogel
|
|
|
|
}
|
|
|
|
unit DockedAnchorDesigner;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
// RTL, FCL
|
|
Classes, SysUtils, math, Types,
|
|
// LCL
|
|
LCLProc, Controls, LCLIntf, Forms, ExtCtrls, Graphics, Dialogs, Menus,
|
|
// IDEIntf
|
|
PropEdits,
|
|
// DockedFormEditor
|
|
DockedDesignForm, DockedBasicAnchorDesigner, DockedAnchorControl,
|
|
DockedOptionsIDE, DockedGrip, DockedTools, DockedStrConsts;
|
|
|
|
type
|
|
|
|
{ TAnchorDesigner }
|
|
|
|
TAnchorDesigner = class(TBasicAnchorDesigner)
|
|
private
|
|
FAnchorBarWidth: Integer;
|
|
FAnchorControls: TAnchorControls;
|
|
FAnchorGrips: TAnchorGrips;
|
|
FBackGround: TAnchorControl;
|
|
FBorderControl: TBorderControl;
|
|
FCurrentBounds: TRect;
|
|
FDesignControl: TWinControl;
|
|
FDesignForm: TDesignForm;
|
|
FMenuAttachDetach: TMenuItem;
|
|
FMousePos: TPoint;
|
|
FPopupMenu: TPopupMenu;
|
|
FPopupAnchors: TAnchors;
|
|
FPreviousControl: TAnchorControl;
|
|
FPreviewHint: THintWindow;
|
|
FSelectedControl: TAnchorControl;
|
|
FState: TAnchorStates;
|
|
FTargetControl: TAnchorControl;
|
|
FTargetHorzSide: TAnchorSideReference;
|
|
FTargetVertSide: TAnchorSideReference;
|
|
procedure AdjustGrips;
|
|
procedure AnchorControlMouseDown(Sender: TObject; {%H-}Button: TMouseButton; Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
|
|
procedure AnchorControlMouseMove(Sender: TObject; Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
|
|
procedure AnchorControlMouseUp(Sender: TObject; {%H-}Button: TMouseButton; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
|
|
procedure AnchorControlMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
|
|
procedure AnchorControlPaint(Sender: TObject);
|
|
procedure AnchorGripMouseDown(Sender: TObject; {%H-}Button: TMouseButton; Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
|
|
procedure AnchorGripMouseMove(Sender: TObject; Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
|
|
procedure AnchorGripMouseUp(Sender: TObject; {%H-}Button: TMouseButton; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
|
|
procedure BringToFront(AControl: TAnchorControl);
|
|
function CalculateRect(AControl: TControl): TRect;
|
|
procedure CreateAnchorControl(AControl: TControl; AParent: TWinControl);
|
|
procedure CreateAnchorGrips;
|
|
procedure CreateBackGround;
|
|
procedure CreatePopupMenu;
|
|
function FindNearestControl(APoint: TPoint): TAnchorControl;
|
|
function FindAnchorHorzSide(ARect: TRect; ARootPoint: TPoint; out Side: TAnchorSideReference): Boolean;
|
|
function FindAnchorVertSide(ARect: TRect; ARootPoint: TPoint; out Side: TAnchorSideReference): Boolean;
|
|
procedure MenuAttachDetachClick(Sender: TObject);
|
|
function MouseStartMoving: Boolean;
|
|
function MouseOffset: TPoint;
|
|
procedure PopupMenuAdapt(Sender: TObject);
|
|
procedure SelectedAdaptAnchors;
|
|
procedure SelectedAdaptBorder;
|
|
procedure SelectedAdaptBounds;
|
|
procedure SelectedAnchorNewTarget(AKind: TAnchorKind);
|
|
procedure SetSelectedControl(AValue: TAnchorControl);
|
|
procedure ShowPreviousHint;
|
|
public
|
|
constructor Create(ADesignForm: TDesignForm; AParent: TWinControl);
|
|
destructor Destroy; override;
|
|
procedure Abort; override;
|
|
procedure BeginUpdate; override;
|
|
procedure EndUpdate; override;
|
|
procedure Invalidate; override;
|
|
procedure Refresh; override;
|
|
procedure SetParent(AValue: TWinControl); override;
|
|
public
|
|
property SelectedControl: TAnchorControl read FSelectedControl write SetSelectedControl;
|
|
property State: TAnchorStates read FState write FState;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TAnchorDesigner }
|
|
|
|
procedure TAnchorDesigner.AdjustGrips;
|
|
var
|
|
LRect: TRect;
|
|
begin
|
|
if Assigned(FSelectedControl) and (not State.IsMoving or State.IsBordering) then
|
|
begin
|
|
LRect := FSelectedControl.BoundsRect;
|
|
FBorderControl.Parent := FSelectedControl.Parent;
|
|
FBorderControl.SetBounds(
|
|
LRect.Left - FSelectedControl.BorderSpacing.Around - FSelectedControl.BorderSpacing.Left,
|
|
LRect.Top - FSelectedControl.BorderSpacing.Around - FSelectedControl.BorderSpacing.Top,
|
|
LRect.Width + FSelectedControl.BorderSpacing.Around * 2 + FSelectedControl.BorderSpacing.Left + FSelectedControl.BorderSpacing.Right,
|
|
LRect.Height + FSelectedControl.BorderSpacing.Around * 2 + FSelectedControl.BorderSpacing.Top + FSelectedControl.BorderSpacing.Bottom);
|
|
FBorderControl.Visible := True;
|
|
FBorderControl.BringToFront;
|
|
FSelectedControl.BringToFront;
|
|
end else
|
|
FBorderControl.Visible := False;
|
|
FAnchorGrips.AdjustGrips(FSelectedControl);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.AnchorControlMouseDown(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
LSelectedControl: TAnchorControl;
|
|
begin
|
|
PopupMenuAdapt(Sender);
|
|
if not (State = []) then Exit;
|
|
if Assigned(OnDesignerSetFocus) then OnDesignerSetFocus();
|
|
if Sender = FBackGround then
|
|
begin
|
|
SelectedControl := nil;
|
|
Invalidate;
|
|
Exit;
|
|
end;
|
|
LSelectedControl := TAnchorControl(Sender);
|
|
if LSelectedControl.IsChildControl then
|
|
SelectedControl := TAnchorControl(LSelectedControl.Parent)
|
|
else
|
|
SelectedControl := LSelectedControl;
|
|
Invalidate;
|
|
if not (Shift = [ssLeft]) and not (Shift = [ssCtrl, ssLeft]) then Exit;
|
|
GetCursorPos(FMousePos);
|
|
Include(FState, asMouseDown);
|
|
{$IF Defined(LCLWin32) or Defined(LCLWin64)}
|
|
SetCapture(TWinControl(Sender).Handle);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TAnchorDesigner.AnchorControlMouseMove(Sender: TObject;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
LAllowMoving: Boolean;
|
|
begin
|
|
if not State.IsMouseDown then Exit;
|
|
if not (Shift = [ssLeft]) and not (Shift = [ssCtrl, ssLeft]) then Exit;
|
|
if not State.IsMoving then
|
|
begin
|
|
if ssCtrl in Shift then
|
|
Include(FState, asBordering);
|
|
if not State.IsBordering and not MouseStartMoving then Exit;
|
|
Include(FState, asMoving);
|
|
FPreviousControl := TAnchorControl.Create(FSelectedControl.Parent, FSelectedControl.RootControl);
|
|
FPreviousControl.Visible := False;
|
|
FPreviousControl.AssignAnchors(FSelectedControl);
|
|
if not State.IsBordering then
|
|
begin
|
|
FBackGround.Invalidate;
|
|
if DockedOptions.AllowSizing then
|
|
FState := FState + [asAnchorTop, asAnchorLeft, asAnchorRight, asAnchorBottom]
|
|
else
|
|
begin
|
|
LAllowMoving := True;
|
|
if (akTop in FPreviousControl.Anchors) and Assigned(FPreviousControl.AnchorSide[akTop].Control) then
|
|
LAllowMoving := False;
|
|
if (akLeft in FPreviousControl.Anchors) and Assigned(FPreviousControl.AnchorSide[akLeft].Control) then
|
|
LAllowMoving := False;
|
|
if (akRight in FPreviousControl.Anchors) and Assigned(FPreviousControl.AnchorSide[akRight].Control) then
|
|
LAllowMoving := False;
|
|
if (akBottom in FPreviousControl.Anchors) and Assigned(FPreviousControl.AnchorSide[akBottom].Control) then
|
|
LAllowMoving := False;
|
|
if LAllowMoving then
|
|
FState := FState + [asAnchorTop, asAnchorLeft, asAnchorRight, asAnchorBottom]
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if State.IsBordering then
|
|
begin
|
|
// borderspacing
|
|
SelectedAdaptBorder;
|
|
end else begin
|
|
// sizing
|
|
SelectedAdaptBounds;
|
|
end;
|
|
ShowPreviousHint;
|
|
AdjustGrips;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.AnchorControlMouseUp(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if not State.IsMouseDown then Exit;
|
|
Exclude(FState, asMouseDown);
|
|
|
|
if not State.IsMoving then
|
|
begin
|
|
GlobalDesignHook.SelectOnlyThis(SelectedControl.RootControl);
|
|
Exit;
|
|
end;
|
|
Exclude(FState, asMoving);
|
|
|
|
if not FSelectedControl.AnchorsValid then
|
|
begin
|
|
Abort;
|
|
Exit;
|
|
end;
|
|
FPreviewHint.Hide;
|
|
FSelectedControl.AssignToRoot_Full;
|
|
FreeAndNil(FPreviousControl);
|
|
|
|
Screen.Cursor := crDefault;
|
|
{$IF Defined(LCLWin32) or Defined(LCLWin64)}
|
|
ReleaseCapture;
|
|
{$ENDIF}
|
|
|
|
FState := [];
|
|
GlobalDesignHook.Modified(Self, 'Anchors');
|
|
GlobalDesignHook.SelectOnlyThis(SelectedControl.RootControl);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.AnchorControlMouseWheel(Sender: TObject;
|
|
Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
|
|
var Handled: Boolean);
|
|
begin
|
|
if Assigned(OnMouseWheel) then
|
|
OnMouseWheel(Sender, Shift, WheelDelta, MousePos, Handled);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.AnchorControlPaint(Sender: TObject);
|
|
begin
|
|
TAnchorControl(Sender).TargetAnchorSidesGet(FSelectedControl);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.AnchorGripMouseDown(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
PopupMenuAdapt(Sender);
|
|
if Assigned(OnDesignerSetFocus) then OnDesignerSetFocus();
|
|
if not (Shift = [ssLeft]) and not (Shift = [ssCtrl, ssLeft]) then Exit;
|
|
GetCursorPos(FMousePos);
|
|
Include(FState, asMouseDown);
|
|
{$IF Defined(LCLWin32) or Defined(LCLWin64)}
|
|
SetCapture(TWinControl(Sender).Handle);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TAnchorDesigner.AnchorGripMouseMove(Sender: TObject;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
LAnchoring: Boolean;
|
|
LMousePos: TPoint;
|
|
LTargetControl: TAnchorControl;
|
|
LRect: TRect;
|
|
begin
|
|
if not State.IsMouseDown then Exit;
|
|
if not (Shift = [ssLeft]) and not (Shift = [ssCtrl, ssLeft]) then Exit;
|
|
if not State.IsMoving then
|
|
begin
|
|
if ssCtrl in Shift then
|
|
Include(FState, asBordering);
|
|
Include(FState, asMoving);
|
|
FPreviousControl := TAnchorControl.Create(FSelectedControl.Parent, FSelectedControl.RootControl);
|
|
FPreviousControl.Visible := False;
|
|
FPreviousControl.AssignAnchors(FSelectedControl);
|
|
end;
|
|
|
|
if (Sender = FAnchorGrips.GripTopLeft) then FState := FState + [asAnchorTop, asAnchorLeft]
|
|
else if (Sender = FAnchorGrips.GripTopCenter) then FState := FState + [asAnchorTop]
|
|
else if (Sender = FAnchorGrips.GripTopRight) then FState := FState + [asAnchorTop, asAnchorRight]
|
|
else if (Sender = FAnchorGrips.GripCenterRight) then FState := FState + [asAnchorRight]
|
|
else if (Sender = FAnchorGrips.GripBottomRight) then FState := FState + [asAnchorBottom, asAnchorRight]
|
|
else if (Sender = FAnchorGrips.GripBottomCenter) then FState := FState + [asAnchorBottom]
|
|
else if (Sender = FAnchorGrips.GripBottomLeft) then FState := FState + [asAnchorBottom, asAnchorLeft]
|
|
else if (Sender = FAnchorGrips.GripCenterLeft) then FState := FState + [asAnchorLeft]
|
|
else
|
|
Exit;
|
|
|
|
if State.IsBordering then
|
|
begin
|
|
// borderspacing
|
|
SelectedAdaptBorder;
|
|
end else begin
|
|
// anchoring or sizing
|
|
LMousePos := Point(0, 0);
|
|
GetCursorPos(LMousePos);
|
|
LMousePos := FBackGround.ScreenToClient(LMousePos);
|
|
LTargetControl := FindNearestControl(LMousePos);
|
|
if Assigned(FTargetControl) and (FTargetControl <> LTargetControl) then
|
|
FTargetControl.Color := DockedOptions.AnchorControlColor;
|
|
FTargetControl := LTargetControl;
|
|
|
|
LRect := CalculateRect(FTargetControl);
|
|
LAnchoring := Assigned(FTargetControl);
|
|
if State.IsAnchoringHorz and LAnchoring then
|
|
LAnchoring := FindAnchorHorzSide(LRect, LMousePos, FTargetHorzSide);
|
|
if State.IsAnchoringVert and LAnchoring then
|
|
LAnchoring := FindAnchorVertSide(LRect, LMousePos, FTargetVertSide);
|
|
|
|
if LAnchoring then
|
|
begin
|
|
// use Anchors
|
|
FSelectedControl.AssignBounds(FPreviousControl);
|
|
SelectedAdaptAnchors;
|
|
FTargetControl.Color := DockedOptions.AnchorTargetColor;
|
|
end else begin
|
|
// size control
|
|
SelectedAdaptBounds;
|
|
FTargetControl.Color := DockedOptions.AnchorControlColor;
|
|
FTargetControl := nil;
|
|
end;
|
|
end;
|
|
ShowPreviousHint;
|
|
AdjustGrips;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.AnchorGripMouseUp(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if not State.IsMouseDown then Exit;
|
|
Exclude(FState, asMouseDown);
|
|
|
|
if not State.IsMoving then Exit;
|
|
Exclude(FState, asMoving);
|
|
|
|
if not FSelectedControl.AnchorsValid then
|
|
begin
|
|
Abort;
|
|
Exit;
|
|
end;
|
|
if not DockedOptions.AllowSizing then
|
|
begin
|
|
if State.IsAnchoringLeft and (FSelectedControl.AnchorSide[akLeft].Control = nil) then
|
|
begin
|
|
FSelectedControl.Left := FPreviousControl.Left;
|
|
FSelectedControl.Width := FPreviousControl.Width;
|
|
end;
|
|
if State.IsAnchoringRight and (FSelectedControl.AnchorSide[akRight].Control = nil) then
|
|
FSelectedControl.Width := FPreviousControl.Width;
|
|
if State.IsAnchoringTop and (FSelectedControl.AnchorSide[akTop].Control = nil) then
|
|
begin
|
|
FSelectedControl.Height := FPreviousControl.Height;
|
|
FSelectedControl.Top := FPreviousControl.Top;
|
|
end;
|
|
if State.IsAnchoringBottom and (FSelectedControl.AnchorSide[akBottom].Control = nil) then
|
|
FSelectedControl.Height := FPreviousControl.Height;
|
|
end;
|
|
FPreviewHint.Hide;
|
|
FSelectedControl.AssignToRoot_Anchors;
|
|
FSelectedControl.AssignToRoot_ControlsBounds(True);
|
|
|
|
if Assigned(FTargetControl) then FTargetControl.Color := DockedOptions.AnchorControlColor;
|
|
FTargetControl := nil;
|
|
FreeAndNil(FPreviousControl);
|
|
|
|
Screen.Cursor := crDefault;
|
|
{$IF Defined(LCLWin32) or Defined(LCLWin64)}
|
|
ReleaseCapture;
|
|
{$ENDIF}
|
|
|
|
FState := [];
|
|
GlobalDesignHook.Modified(Self, 'Anchors');
|
|
end;
|
|
|
|
procedure TAnchorDesigner.BringToFront(AControl: TAnchorControl);
|
|
begin
|
|
if not Assigned(AControl) then Exit;
|
|
if AControl = FBackGround then Exit;
|
|
AControl.BringToFront;
|
|
BringToFront(TAnchorControl(AControl.Parent));
|
|
end;
|
|
|
|
function TAnchorDesigner.CalculateRect(AControl: TControl): TRect;
|
|
var
|
|
LTopLeft, LBottomRight: TPoint;
|
|
begin
|
|
Result := FBackGround.ClientRect;
|
|
if not Assigned(AControl) then Exit;
|
|
if AControl = FBackGround then Exit;
|
|
|
|
LTopLeft := AControl.ClientToParent(Point(0, 0), FBackGround);
|
|
LBottomRight := AControl.ClientToParent(Point(AControl.Width, AControl.Height), FBackGround);
|
|
Result := Rect(LTopLeft.x, LTopLeft.y, LBottomRight.x, LBottomRight.y)
|
|
end;
|
|
|
|
procedure TAnchorDesigner.CreateAnchorControl(AControl: TControl; AParent: TWinControl);
|
|
var
|
|
LAnchorControl: TAnchorControl;
|
|
LWinControl: TWinControl;
|
|
i, LIndex: Integer;
|
|
begin
|
|
if csNoDesignSelectable in AControl.ControlStyle then
|
|
Exit;
|
|
LIndex := FAnchorControls.IndexOf(AControl);
|
|
if LIndex >= 0 then
|
|
begin
|
|
LAnchorControl := FAnchorControls[LIndex];
|
|
end else begin
|
|
LAnchorControl := TAnchorControl.Create(AParent, AControl);
|
|
LAnchorControl.OnMouseDown := @AnchorControlMouseDown;
|
|
LAnchorControl.OnMouseMove := @AnchorControlMouseMove;
|
|
LAnchorControl.OnMouseUp := @AnchorControlMouseUp;
|
|
LAnchorControl.OnPaint := @AnchorControlPaint;
|
|
LAnchorControl.OnMouseWheel := @AnchorControlMouseWheel;
|
|
LAnchorControl.PopupMenu := FPopupMenu;
|
|
FAnchorControls.Add(LAnchorControl);
|
|
end;
|
|
LAnchorControl.Validate;
|
|
LAnchorControl.Visible := True;
|
|
if (AControl is TWinControl)
|
|
and not (csOwnedChildrenNotSelectable in AControl.ControlStyle) then
|
|
begin
|
|
LWinControl := TWinControl(AControl);
|
|
for i := 0 to LWinControl.ControlCount - 1 do
|
|
CreateAnchorControl(LWinControl.Controls[i], LAnchorControl);
|
|
end;
|
|
if AControl = FDesignForm.SelectedControl then
|
|
SelectedControl := LAnchorControl;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.CreateAnchorGrips;
|
|
begin
|
|
FAnchorGrips := TAnchorGrips.Create;
|
|
FAnchorGrips.Parent := Parent;
|
|
FAnchorGrips.BackGround := FBackGround;
|
|
FAnchorGrips.OnMouseDown := @AnchorGripMouseDown;
|
|
FAnchorGrips.OnMouseMove := @AnchorGripMouseMove;
|
|
FAnchorGrips.OnMouseUp := @AnchorGripMouseUp;
|
|
FAnchorGrips.Hide;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.CreateBackGround;
|
|
begin
|
|
FBackGround := TAnchorControl.Create(Parent, FDesignControl);
|
|
FBackGround.BevelOuter := bvNone;
|
|
FBackGround.Align := alClient;
|
|
FBackGround.Name := 'AnchorBackGround';
|
|
FBackGround.Parent := Parent;
|
|
FBackGround.OnMouseDown := @AnchorControlMouseDown;
|
|
FBackGround.OnPaint := @AnchorControlPaint;
|
|
FBackGround.OnMouseWheel := @AnchorControlMouseWheel;
|
|
FBackGround.OnShowHint := nil;
|
|
FAnchorControls.Add(FBackGround);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.CreatePopupMenu;
|
|
begin
|
|
FPopupMenu := TPopupMenu.Create(FBackGround);
|
|
FAnchorGrips.PopupMenu := FPopupMenu;
|
|
FMenuAttachDetach := TMenuItem.Create(FPopupMenu);
|
|
FMenuAttachDetach.OnClick := @MenuAttachDetachClick;
|
|
FPopupMenu.Items.Add(FMenuAttachDetach);
|
|
end;
|
|
|
|
function TAnchorDesigner.FindNearestControl(APoint: TPoint): TAnchorControl;
|
|
var
|
|
LRect: TRect;
|
|
LBestDist, LDist: TPoint;
|
|
i: Integer;
|
|
begin
|
|
if SelectedControl.Parent is TAnchorControl then
|
|
Result := TAnchorControl(SelectedControl.Parent)
|
|
else
|
|
Exit(nil);
|
|
|
|
LRect := CalculateRect(FSelectedControl.Parent);
|
|
LBestDist.x := MinIntValue([abs(APoint.x - LRect.Left), abs(APoint.x - LRect.Right), DockedOptions.CaptureDistance]);
|
|
LBestDist.y := MinIntValue([abs(APoint.y - LRect.Top), abs(APoint.y - LRect.Bottom), DockedOptions.CaptureDistance]);
|
|
|
|
for i := 0 to FSelectedControl.Parent.ControlCount - 1 do
|
|
begin
|
|
if (FSelectedControl.Parent.Controls[i] = FSelectedControl)
|
|
or (FSelectedControl.Parent.Controls[i] = FPreviousControl)
|
|
or (FSelectedControl.Parent.Controls[i] = FBorderControl) then
|
|
Continue;
|
|
LRect := CalculateRect(FSelectedControl.Parent.Controls[i]);
|
|
|
|
if (APoint.x >= LRect.Left) and (APoint.x <= LRect.Right) then
|
|
LDist.x := 0
|
|
else
|
|
LDist.x := Min(abs(APoint.x - LRect.Left), abs(APoint.x - LRect.Right));
|
|
|
|
if (APoint.y >= LRect.Top) and (APoint.y <= LRect.Bottom) then
|
|
LDist.y := 0
|
|
else
|
|
LDist.y := Min(abs(APoint.y - LRect.Top), abs(APoint.y - LRect.Bottom));
|
|
|
|
if LDist.x + LDist.y < LBestDist.x + LBestDist.y then
|
|
begin
|
|
LBestDist := LDist;
|
|
Result := TAnchorControl(FSelectedControl.Parent.Controls[i]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TAnchorDesigner.FindAnchorHorzSide(ARect: TRect; ARootPoint: TPoint;
|
|
out Side: TAnchorSideReference): Boolean;
|
|
var
|
|
LDistLeft, LDistRight, LDistCenter: Integer;
|
|
begin
|
|
Result := False;
|
|
Side := asrTop;
|
|
if not State.IsAnchoringHorz then Exit;
|
|
|
|
LDistLeft := abs(ARect.Left - ARootPoint.x);
|
|
LDistRight := abs(ARect.Right - ARootPoint.x);
|
|
LDistCenter := abs((ARect.Left + ARect.Right) div 2 - ARootPoint.x);
|
|
|
|
// if other side is center anchored, skip center as target prevent endless sizing loop
|
|
if (State.IsAnchoringLeft and (FSelectedControl.AnchorSide[akRight].Side = asrCenter))
|
|
or (State.IsAnchoringRight and (FSelectedControl.AnchorSide[akLeft].Side = asrCenter)) then
|
|
LDistCenter := MaxInt;
|
|
|
|
if FTargetControl = FSelectedControl.Parent then
|
|
if State.IsAnchoringLeft then
|
|
LDistRight := MaxInt
|
|
else
|
|
LDistLeft := MaxInt;
|
|
|
|
if (LDistRight < LDistLeft) and (LDistRight < LDistCenter) then
|
|
begin
|
|
Side := asrBottom;
|
|
if LDistRight > DockedOptions.CaptureDistance then Exit;
|
|
Result := True;
|
|
end;
|
|
if not Result and (LDistCenter < LDistLeft) then
|
|
begin
|
|
Side := asrCenter;
|
|
if LDistCenter > DockedOptions.CaptureDistance then Exit;
|
|
Result := True;
|
|
end;
|
|
if not Result and (LDistLeft > DockedOptions.CaptureDistance) then Exit;
|
|
|
|
if State.IsAnchoringLeft then
|
|
Result := FSelectedControl.AnchorValid(akLeft, FTargetControl, Side)
|
|
else
|
|
Result := FSelectedControl.AnchorValid(akRight, FTargetControl, Side);
|
|
end;
|
|
|
|
function TAnchorDesigner.FindAnchorVertSide(ARect: TRect; ARootPoint: TPoint;
|
|
out Side: TAnchorSideReference): Boolean;
|
|
var
|
|
LDistTop, LDistBottom, LDistCenter: Integer;
|
|
begin
|
|
Result := False;
|
|
Side := asrTop;
|
|
if not State.IsAnchoringVert then Exit;
|
|
|
|
LDistTop := abs(ARect.Top - ARootPoint.y);
|
|
LDistBottom := abs(ARect.Bottom - ARootPoint.y);
|
|
LDistCenter := abs((ARect.Top + ARect.Bottom) div 2 - ARootPoint.y);
|
|
|
|
// if other side is center anchored, skip center as target prevent endless sizing loop
|
|
if (State.IsAnchoringTop and (FSelectedControl.AnchorSide[akBottom].Side = asrCenter))
|
|
or (State.IsAnchoringBottom and (FSelectedControl.AnchorSide[akTop].Side = asrCenter)) then
|
|
LDistCenter := MaxInt;
|
|
|
|
if FTargetControl = FSelectedControl.Parent then
|
|
if State.IsAnchoringTop then
|
|
LDistBottom := MaxInt
|
|
else
|
|
LDistTop := MaxInt;
|
|
|
|
if (LDistBottom < LDistTop) and (LDistBottom < LDistCenter) then
|
|
begin
|
|
Side := asrBottom;
|
|
if LDistBottom > DockedOptions.CaptureDistance then Exit;
|
|
Result := True;
|
|
end;
|
|
if not Result and (LDistCenter < LDistTop) then
|
|
begin
|
|
Side := asrCenter;
|
|
if LDistCenter > DockedOptions.CaptureDistance then Exit;
|
|
Result := True;
|
|
end;
|
|
if not Result and (LDistTop > DockedOptions.CaptureDistance) then Exit;
|
|
|
|
if State.IsAnchoringTop then
|
|
Result := FSelectedControl.AnchorValid(akTop, FTargetControl, Side)
|
|
else
|
|
Result := FSelectedControl.AnchorValid(akBottom, FTargetControl, Side);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.MenuAttachDetachClick(Sender: TObject);
|
|
var
|
|
LKind: TAnchorKind;
|
|
begin
|
|
case TAttachDetach(FMenuAttachDetach.Tag) of
|
|
adAttachControl:
|
|
begin
|
|
FSelectedControl.RemoveAnchorSides;
|
|
FSelectedControl.Anchors := [akLeft, akTop];
|
|
end;
|
|
adDetachControl:
|
|
FSelectedControl.RemoveAnchorSides;
|
|
adAttachPoint, adAttachSide:
|
|
for LKind := akTop to akBottom do
|
|
begin
|
|
if [LKind] * FPopupAnchors = [] then Continue;
|
|
FSelectedControl.RemoveAnchorSide(LKind);
|
|
FSelectedControl.Anchors := FSelectedControl.Anchors + [LKind];
|
|
end;
|
|
adDetachPoint, adDetachSide:
|
|
for LKind := akTop to akBottom do
|
|
begin
|
|
if [LKind] * FPopupAnchors = [] then Continue;
|
|
FSelectedControl.RemoveAnchorSide(LKind);
|
|
end;
|
|
end;
|
|
|
|
FSelectedControl.AssignToRoot_Anchors;
|
|
FState := [];
|
|
GlobalDesignHook.Modified(Self, 'Anchors');
|
|
GlobalDesignHook.SelectOnlyThis(FSelectedControl.RootControl);
|
|
end;
|
|
|
|
function TAnchorDesigner.MouseStartMoving: Boolean;
|
|
var
|
|
LMousePos: TPoint;
|
|
begin
|
|
LMousePos := MouseOffset;
|
|
Result := Max(abs(LMousePos.x), abs(LMousePos.y)) > DockedOptions.CaptureDistance;
|
|
end;
|
|
|
|
function TAnchorDesigner.MouseOffset: TPoint;
|
|
begin
|
|
Result := Point(0, 0);
|
|
GetCursorPos(Result);
|
|
Result := Result - FMousePos;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.PopupMenuAdapt(Sender: TObject);
|
|
var
|
|
LAttachDetach: TAttachDetach;
|
|
begin
|
|
FPopupAnchors := [];
|
|
if Sender is TAnchorControl then
|
|
begin
|
|
if TAnchorControl(Sender).Anchors = [] then
|
|
LAttachDetach := adAttachControl
|
|
else
|
|
LAttachDetach := adDetachControl;
|
|
end else
|
|
if Sender = FAnchorGrips.GripTopLeft then
|
|
begin
|
|
if FSelectedControl.Anchors * [akLeft, akTop] = [] then
|
|
LAttachDetach := adAttachPoint
|
|
else
|
|
LAttachDetach := adDetachPoint;
|
|
FPopupAnchors := FPopupAnchors + [akLeft, akTop];
|
|
end else
|
|
if Sender = FAnchorGrips.GripTopCenter then
|
|
begin
|
|
if FSelectedControl.Anchors * [akTop] = [] then
|
|
LAttachDetach := adAttachSide
|
|
else
|
|
LAttachDetach := adDetachSide;
|
|
FPopupAnchors := FPopupAnchors + [akTop];
|
|
end else
|
|
if Sender = FAnchorGrips.GripTopRight then
|
|
begin
|
|
if FSelectedControl.Anchors * [akTop, akRight] = [] then
|
|
LAttachDetach := adAttachPoint
|
|
else
|
|
LAttachDetach := adDetachPoint;
|
|
FPopupAnchors := FPopupAnchors + [akTop, akRight];
|
|
end else
|
|
if Sender = FAnchorGrips.GripCenterRight then
|
|
begin
|
|
if FSelectedControl.Anchors * [akRight] = [] then
|
|
LAttachDetach := adAttachSide
|
|
else
|
|
LAttachDetach := adDetachSide;
|
|
FPopupAnchors := FPopupAnchors + [akRight];
|
|
end else
|
|
if Sender = FAnchorGrips.GripBottomRight then
|
|
begin
|
|
if FSelectedControl.Anchors * [akBottom, akRight] = [] then
|
|
LAttachDetach := adAttachPoint
|
|
else
|
|
LAttachDetach := adDetachPoint;
|
|
FPopupAnchors := FPopupAnchors + [akBottom, akRight];
|
|
end else
|
|
if Sender = FAnchorGrips.GripBottomCenter then
|
|
begin
|
|
if FSelectedControl.Anchors * [akBottom] = [] then
|
|
LAttachDetach := adAttachSide
|
|
else
|
|
LAttachDetach := adDetachSide;
|
|
FPopupAnchors := FPopupAnchors + [akBottom];
|
|
end else
|
|
if Sender = FAnchorGrips.GripBottomLeft then
|
|
begin
|
|
if FSelectedControl.Anchors * [akBottom, akLeft] = [] then
|
|
LAttachDetach := adAttachPoint
|
|
else
|
|
LAttachDetach := adDetachPoint;
|
|
FPopupAnchors := FPopupAnchors + [akBottom, akLeft];
|
|
end else
|
|
if Sender = FAnchorGrips.GripCenterLeft then
|
|
begin
|
|
if FSelectedControl.Anchors * [akLeft] = [] then
|
|
LAttachDetach := adAttachSide
|
|
else
|
|
LAttachDetach := adDetachSide;
|
|
FPopupAnchors := FPopupAnchors + [akLeft];
|
|
end else
|
|
raise Exception.Create('TAnchorDesigner.PopupMenuAdapt: Wrong Sender');
|
|
FMenuAttachDetach.Caption := AttachDetachStr[LAttachDetach];
|
|
FMenuAttachDetach.Tag := ord(LAttachDetach);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.SelectedAdaptAnchors;
|
|
begin
|
|
if State.IsAnchoringHorz then
|
|
begin
|
|
if State.IsAnchoringLeft then
|
|
begin
|
|
SelectedAnchorNewTarget(akLeft);
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akRight);
|
|
end else begin
|
|
SelectedAnchorNewTarget(akRight);
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akLeft);
|
|
end;
|
|
end else begin
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akLeft);
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akRight);
|
|
end;
|
|
|
|
if State.IsAnchoringVert then
|
|
begin
|
|
if State.IsAnchoringTop then
|
|
begin
|
|
SelectedAnchorNewTarget(akTop);
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akBottom);
|
|
end else begin
|
|
SelectedAnchorNewTarget(akBottom);
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akTop);
|
|
end;
|
|
end else begin
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akTop);
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akBottom);
|
|
end;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.SelectedAdaptBorder;
|
|
var
|
|
LMouseOffset: TPoint;
|
|
LLeftBorder, LRightBorder, LTopBorder, LBottomBorder, LAroundBorder: TSpacingSize;
|
|
begin
|
|
LMouseOffset := MouseOffset;
|
|
LMouseOffset.x := LMouseOffset.x div DockedOptions.MouseBorderFactor;
|
|
LMouseOffset.y := LMouseOffset.y div DockedOptions.MouseBorderFactor;
|
|
|
|
if not DockedOptions.TreatBorder and not State.IsAnchoring then
|
|
begin
|
|
FSelectedControl.BorderSpacing.Around :=
|
|
Max(0, FPreviousControl.BorderSpacing.Around + LMouseOffset.x + LMouseOffset.y);
|
|
Exit;
|
|
end;
|
|
|
|
LAroundBorder := FPreviousControl.BorderSpacing.Around;
|
|
LLeftBorder := FPreviousControl.BorderSpacing.Left;
|
|
LRightBorder := FPreviousControl.BorderSpacing.Right;
|
|
LTopBorder := FPreviousControl.BorderSpacing.Top;
|
|
LBottomBorder := FPreviousControl.BorderSpacing.Bottom;
|
|
|
|
if DockedOptions.TreatBorder then
|
|
begin
|
|
LLeftBorder := LLeftBorder + LAroundBorder;
|
|
LRightBorder := LRightBorder + LAroundBorder;
|
|
LTopBorder := LTopBorder + LAroundBorder;
|
|
LBottomBorder := LBottomBorder + LAroundBorder;
|
|
end;
|
|
|
|
if State.IsAnchoring then
|
|
begin
|
|
if State.IsAnchoringLeft then LLeftBorder := Max(0, LLeftBorder + LMouseOffset.x);
|
|
if State.IsAnchoringRight then LRightBorder := Max(0, LRightBorder - LMouseOffset.x);
|
|
if State.IsAnchoringTop then LTopBorder := Max(0, LTopBorder + LMouseOffset.y);
|
|
if State.IsAnchoringBottom then LBottomBorder := Max(0, LBottomBorder - LMouseOffset.y);
|
|
end else begin
|
|
LLeftBorder := Max(0, LLeftBorder + LMouseOffset.x);
|
|
LRightBorder := Max(0, LRightBorder + LMouseOffset.x);
|
|
LTopBorder := Max(0, LTopBorder + LMouseOffset.y);
|
|
LBottomBorder := Max(0, LBottomBorder + LMouseOffset.y);
|
|
end;
|
|
|
|
if DockedOptions.TreatBorder then
|
|
begin
|
|
if State.IsAnchoring then
|
|
LAroundBorder := MinIntValue([LLeftBorder, LRightBorder, LTopBorder, LBottomBorder, LAroundBorder])
|
|
else
|
|
LAroundBorder := MinIntValue([LLeftBorder, LRightBorder, LTopBorder, LBottomBorder]);
|
|
|
|
LLeftBorder := LLeftBorder - LAroundBorder;
|
|
LRightBorder := LRightBorder - LAroundBorder;
|
|
LTopBorder := LTopBorder - LAroundBorder;
|
|
LBottomBorder := LBottomBorder - LAroundBorder;
|
|
end;
|
|
|
|
FSelectedControl.BorderSpacing.Around := Max(0, LAroundBorder);
|
|
FSelectedControl.BorderSpacing.Left := Max(0, LLeftBorder);
|
|
FSelectedControl.BorderSpacing.Right := Max(0, LRightBorder);
|
|
FSelectedControl.BorderSpacing.Top := Max(0, LTopBorder);
|
|
FSelectedControl.BorderSpacing.Bottom := Max(0, LBottomBorder);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.SelectedAdaptBounds;
|
|
var
|
|
LMouseOffset: TPoint;
|
|
LRect: TRect;
|
|
begin
|
|
LMouseOffset := MouseOffset;
|
|
LRect := FPreviousControl.BoundsRect;
|
|
|
|
if State.IsAnchoringLeft then
|
|
begin
|
|
FSelectedControl.RemoveAnchorSide(akLeft);
|
|
LRect.Left := LRect.Left + LMouseOffset.x;
|
|
end else
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akLeft);
|
|
if State.IsAnchoringRight then
|
|
begin
|
|
FSelectedControl.RemoveAnchorSide(akRight);
|
|
LRect.Right := LRect.Right + LMouseOffset.x;
|
|
end else
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akRight);
|
|
if State.IsAnchoringTop then
|
|
begin
|
|
FSelectedControl.RemoveAnchorSide(akTop);
|
|
LRect.Top := LRect.Top + LMouseOffset.y;
|
|
end else
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akTop);
|
|
if State.IsAnchoringBottom then
|
|
begin
|
|
FSelectedControl.RemoveAnchorSide(akBottom);
|
|
LRect.Bottom := LRect.Bottom + LMouseOffset.y;
|
|
end else
|
|
FSelectedControl.AssignAnchor(FPreviousControl, akBottom);
|
|
|
|
if FSelectedControl.RootControl.Constraints.MaxWidth > 0 then
|
|
LRect.Width := Min(LRect.Width, FSelectedControl.RootControl.Constraints.MaxWidth);
|
|
if FSelectedControl.RootControl.Constraints.MinWidth > 0 then
|
|
LRect.Width := Max(LRect.Width, FSelectedControl.RootControl.Constraints.MinWidth);
|
|
if FSelectedControl.RootControl.Constraints.MaxHeight > 0 then
|
|
LRect.Height := Min(LRect.Height, FSelectedControl.RootControl.Constraints.MaxHeight);
|
|
if FSelectedControl.RootControl.Constraints.MinHeight > 0 then
|
|
LRect.Height := Max(LRect.Height, FSelectedControl.RootControl.Constraints.MinHeight);
|
|
|
|
FSelectedControl.SetBounds(LRect.Left, LRect.Top, LRect.Width, LRect.Height);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.SelectedAnchorNewTarget(AKind: TAnchorKind);
|
|
begin
|
|
FSelectedControl.AnchorSide[AKind].Control := FTargetControl;
|
|
if AKind in [akLeft, akRight] then
|
|
FSelectedControl.AnchorSide[AKind].Side := FTargetHorzSide
|
|
else
|
|
FSelectedControl.AnchorSide[AKind].Side := FTargetVertSide;
|
|
FSelectedControl.Anchors := FSelectedControl.Anchors + [AKind];
|
|
end;
|
|
|
|
procedure TAnchorDesigner.SetSelectedControl(AValue: TAnchorControl);
|
|
begin
|
|
if FSelectedControl = AValue then Exit;
|
|
if Assigned(FSelectedControl) then
|
|
FSelectedControl.State := [acsNone];
|
|
if Assigned(AValue) and AValue.IsChildControl then
|
|
begin
|
|
FSelectedControl := nil;
|
|
Exit;
|
|
end;
|
|
FSelectedControl := AValue;
|
|
if Assigned(FSelectedControl) then
|
|
begin
|
|
FSelectedControl.State := [acsSelected];
|
|
BringToFront(FSelectedControl);
|
|
end;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.ShowPreviousHint;
|
|
var
|
|
LPos: TPoint;
|
|
s: String;
|
|
LRect: TRect;
|
|
LKind: TAnchorKind;
|
|
begin
|
|
LPos := Point(0, 0);
|
|
GetCursorPos(LPos);
|
|
|
|
s := EmptyStr;
|
|
if FPreviousControl.BorderSpacing.Around <> FSelectedControl.BorderSpacing.Around then
|
|
s := LinedString(s, 'BorderSpacing Around: ' + FSelectedControl.BorderSpacing.Around.ToString);
|
|
if FPreviousControl.BorderSpacing.Left <> FSelectedControl.BorderSpacing.Left then
|
|
s := LinedString(s, 'BorderSpacing Left: ' + FSelectedControl.BorderSpacing.Left.ToString);
|
|
if FPreviousControl.BorderSpacing.Top <> FSelectedControl.BorderSpacing.Top then
|
|
s := LinedString(s, 'BorderSpacing Top: ' + FSelectedControl.BorderSpacing.Top.ToString);
|
|
if FPreviousControl.BorderSpacing.Right <> FSelectedControl.BorderSpacing.Right then
|
|
s := LinedString(s, 'BorderSpacing Right: ' + FSelectedControl.BorderSpacing.Right.ToString);
|
|
if FPreviousControl.BorderSpacing.Bottom <> FSelectedControl.BorderSpacing.Bottom then
|
|
s := LinedString(s, 'BorderSpacing Bottom: ' + FSelectedControl.BorderSpacing.Bottom.ToString);
|
|
|
|
if FPreviousControl.Left <> FSelectedControl.Left then
|
|
s := LinedString(s, 'Left: ' + FSelectedControl.Left.ToString);
|
|
if FPreviousControl.Top <> FSelectedControl.Top then
|
|
s := LinedString(s, 'Top: ' + FSelectedControl.Top.ToString);
|
|
if FPreviousControl.Width <> FSelectedControl.Width then
|
|
s := LinedString(s, 'Width: ' + FSelectedControl.Width.ToString);
|
|
if FPreviousControl.Height <> FSelectedControl.Height then
|
|
s := LinedString(s, 'Height: ' + FSelectedControl.Height.ToString);
|
|
|
|
if FPreviousControl.Anchors <> FSelectedControl.Anchors then
|
|
s := LinedString(s, 'Anchors: ' + FSelectedControl.Anchors.ToString);
|
|
|
|
for LKind := akTop to akBottom do
|
|
if (FSelectedControl.AnchorSide[LKind].Control <> nil)
|
|
and ((FPreviousControl.AnchorSide[LKind].Control <> FSelectedControl.AnchorSide[LKind].Control)
|
|
or (FPreviousControl.AnchorSide[LKind].Side <> FSelectedControl.AnchorSide[LKind].Side))
|
|
then
|
|
s := LinedString(s, FSelectedControl.AnchorSideStr(LKind));
|
|
|
|
LRect := FPreviewHint.CalcHintRect(0, s, nil); //no maxwidth
|
|
LRect.Left := LPos.x + 15;
|
|
LRect.Top := LPos.y + 15;
|
|
LRect.Right := LRect.Left + LRect.Right;
|
|
LRect.Bottom := LRect.Top + LRect.Bottom;
|
|
FPreviewHint.ActivateHint(LRect, s);
|
|
end;
|
|
|
|
constructor TAnchorDesigner.Create(ADesignForm: TDesignForm; AParent: TWinControl);
|
|
begin
|
|
FState := [];
|
|
FDesignForm := ADesignForm;
|
|
Parent := AParent;
|
|
FAnchorBarWidth := -1;
|
|
FDesignControl := FDesignForm.DesignWinControl;
|
|
FAnchorControls := TAnchorControls.Create;
|
|
FBorderControl := TBorderControl.Create(nil);
|
|
FPreviewHint := THintWindow.Create(nil);
|
|
FPreviewHint.Visible := False;
|
|
FPreviewHint.HideInterval := 4000;
|
|
FPreviewHint.AutoHide := True;
|
|
CreateBackGround;
|
|
CreateAnchorGrips;
|
|
CreatePopupMenu;
|
|
end;
|
|
|
|
destructor TAnchorDesigner.Destroy;
|
|
begin
|
|
FPreviewHint.Free;
|
|
FBorderControl.Free;
|
|
FAnchorGrips.Free;
|
|
FAnchorControls.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.Abort;
|
|
begin
|
|
FPreviewHint.Hide;
|
|
if Assigned(FTargetControl) then FTargetControl.Color := DockedOptions.AnchorControlColor;
|
|
FTargetControl := nil;
|
|
if Assigned(FPreviousControl) then
|
|
begin
|
|
FSelectedControl.AssignFull(FPreviousControl);
|
|
FreeAndNil(FPreviousControl);
|
|
end;
|
|
Screen.Cursor := crDefault;
|
|
{$IF Defined(LCLWin32) or Defined(LCLWin64)}
|
|
if asMouseDown in State then
|
|
ReleaseCapture;
|
|
{$ENDIF}
|
|
FState := [];
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.BeginUpdate;
|
|
begin
|
|
if not Parent.Visible then Exit;
|
|
FAnchorGrips.Hide;
|
|
FBorderControl.Visible := False;
|
|
FAnchorControls.BeginUpdate;
|
|
FBackGround.Invalidate;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.EndUpdate;
|
|
begin
|
|
if not Parent.Visible then Exit;
|
|
FAnchorControls.EndUpdate;
|
|
if (FBackGround.Height <> FCurrentBounds.Height)
|
|
or (FBackGround.Width <> FCurrentBounds.Width) then
|
|
FBackGround.AssignToRoot_ControlsBounds(False);
|
|
end;
|
|
|
|
procedure TAnchorDesigner.Invalidate;
|
|
begin
|
|
AdjustGrips;
|
|
FBackGround.Invalidate;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.Refresh;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
FCurrentBounds := FDesignControl.BoundsRect;
|
|
SelectedControl := nil;
|
|
FAnchorControls.Invalid;
|
|
for i := 0 to FDesignControl.ControlCount - 1 do
|
|
CreateAnchorControl(FDesignControl.Controls[i], FBackGround);
|
|
FAnchorControls.CheckParents;
|
|
FAnchorControls.RemoveInvalid;
|
|
FAnchorControls.CheckProperties;
|
|
FAnchorControls.CheckAnchors;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TAnchorDesigner.SetParent(AValue: TWinControl);
|
|
begin
|
|
inherited SetParent(AValue);
|
|
if Assigned(FBackGround) then FBackGround.Parent := Parent;
|
|
if Assigned(FAnchorGrips) then FAnchorGrips.Parent := Parent;
|
|
end;
|
|
|
|
end.
|
|
|