git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@42 05c56307-c608-d34a-929d-697000501d7a
712 lines
24 KiB
ObjectPascal
712 lines
24 KiB
ObjectPascal
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressLayoutControl common routines }
|
|
{ }
|
|
{ Copyright (c) 2001-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSLAYOUTCONTROL AND ALL }
|
|
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM }
|
|
{ ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
|
|
unit dxLayoutDragAndDrop;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Controls, Windows, Graphics,
|
|
cxClasses, cxControls, cxGraphics, dxLayoutControl;
|
|
|
|
type
|
|
TdxLayoutDragSource = (dsControl, dsCustomizeFormAvailableItems, dsCustomizeFormTreeViewItems);
|
|
|
|
{ TdxLayoutControlDragAndDropObject }
|
|
|
|
TdxLayoutControlDragAndDropObject = class(TcxDragAndDropObject)
|
|
private
|
|
FAreaPart: TdxLayoutAreaPart;
|
|
FDragImage: TcxDragImage;
|
|
FDragImageOffset: TPoint;
|
|
FDestinationControl: TdxCustomLayoutControl;
|
|
FDestinationGroup: TdxLayoutGroup;
|
|
FDestinationImage: TcxDragImage;
|
|
FDestinationItem: TdxCustomLayoutItem;
|
|
FHitTest: TdxCustomLayoutHitTest;
|
|
FNeedRepaintDestinationImage: Boolean;
|
|
FSource: TdxLayoutDragSource;
|
|
FSourceItem: TdxCustomLayoutItem;
|
|
FSourceItemBounds: TRect;
|
|
FStartDragPoint: TPoint;
|
|
|
|
function CanDrop: Boolean;
|
|
function CanRemove: Boolean;
|
|
function GetSourceControl: TdxCustomLayoutControl;
|
|
procedure ResetDragAndDropObjects;
|
|
procedure ResetDragAndDrop;
|
|
procedure SetAreaPart(Value: TdxLayoutAreaPart);
|
|
procedure SetDestinationControl(Value: TdxCustomLayoutControl);
|
|
procedure SetDestinationGroup(Value: TdxLayoutGroup);
|
|
procedure SetDestinationItem(Value: TdxCustomLayoutItem);
|
|
procedure SetSourceItem(Value: TdxCustomLayoutItem);
|
|
protected
|
|
procedure CreateDragImage;
|
|
procedure CreateDestinationImage;
|
|
procedure DirtyChanged; override;
|
|
function GetDragAndDropCursor(Accepted: Boolean): TCursor; override;
|
|
|
|
procedure PaintDestinationImage;
|
|
procedure PaintDragImage;
|
|
procedure RefreshDestinationImage;
|
|
procedure ShowDragImage(const P: TPoint);
|
|
|
|
property AreaPart: TdxLayoutAreaPart read FAreaPart write SetAreaPart;
|
|
property DestinationControl: TdxCustomLayoutControl read FDestinationControl write SetDestinationControl;
|
|
property DestinationGroup: TdxLayoutGroup read FDestinationGroup write SetDestinationGroup;
|
|
property DestinationItem: TdxCustomLayoutItem read FDestinationItem write SetDestinationItem;
|
|
property Source: TdxLayoutDragSource read FSource write FSource;
|
|
property SourceControl: TdxCustomLayoutControl read GetSourceControl;
|
|
property SourceItemBounds: TRect read FSourceItemBounds;
|
|
public
|
|
procedure BeginDragAndDrop; override;
|
|
procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); override;
|
|
procedure EndDragAndDrop(Accepted: Boolean); override;
|
|
procedure Init(ASource: TdxLayoutDragSource; ASourceItem: TdxCustomLayoutItem); virtual;
|
|
property SourceItem: TdxCustomLayoutItem read FSourceItem write SetSourceItem;
|
|
end;
|
|
|
|
{ TdxLayoutDragAndDropHelper }
|
|
|
|
TdxLayoutDragAndDropHelper = class(TdxLayoutControlPersistent)
|
|
private
|
|
FDragItem: TdxCustomLayoutItem;
|
|
FMouseDownPos: TPoint;
|
|
procedure BeginDragAndDrop(ASource: TdxLayoutDragSource);
|
|
function CanBeginDragAndDrop(X, Y: Integer): Boolean;
|
|
function GetDragAndDropObject: TdxLayoutControlDragAndDropObject;
|
|
protected
|
|
property DragAndDropObject: TdxLayoutControlDragAndDropObject read GetDragAndDropObject;
|
|
public
|
|
constructor Create(AControl: TdxCustomLayoutControl); override;
|
|
|
|
procedure InitializeDragItem(AItem: TdxCustomLayoutItem; X, Y: Integer);
|
|
procedure Reset;
|
|
procedure TryBeginDragAndDrop(X, Y: Integer; ASource: TdxLayoutDragSource);
|
|
|
|
property DragItem: TdxCustomLayoutItem read FDragItem;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Classes, SysUtils, Forms, cxLibraryConsts, cxGeometry;
|
|
|
|
const
|
|
dxLayoutSelectionBorderDefaultColor: TColor = $BD8753;
|
|
dxLayoutDestinationColor = $D0D0EE;
|
|
dxLayoutDestinationBorderColor = $000059;
|
|
|
|
type
|
|
TdxCustomLayoutControlAccess = class(TdxCustomLayoutControl);
|
|
TdxCustomLayoutItemAccess = class(TdxCustomLayoutItem);
|
|
TdxLayoutGroupAccess = class(TdxLayoutGroup);
|
|
TdxCustomLayoutItemViewInfoAccess = class(TdxCustomLayoutItemViewInfo);
|
|
TdxLayoutGroupViewInfoAccess = class(TdxLayoutGroupViewInfo);
|
|
TdxLayoutControlViewInfoAccess = class(TdxLayoutControlViewInfo);
|
|
TdxCustomLayoutItemPainterAccess = class(TdxCustomLayoutItemPainter);
|
|
|
|
{ TdxLayoutControlDragAndDropObject }
|
|
|
|
|
|
function TdxLayoutControlDragAndDropObject.CanDrop: Boolean;
|
|
begin
|
|
Result := (DestinationItem <> nil) or (SourceControl.ViewInfo.GetHitTest(CurMousePos).HitTestCode in
|
|
[{//#DG feature is not ready yet htTreeViewItems, }htClientArea, htGroup, htItem]);
|
|
end;
|
|
|
|
function TdxLayoutControlDragAndDropObject.CanRemove: Boolean;
|
|
begin
|
|
Result := (SourceControl.ViewInfo.GetHitTest(CurMousePos).HitTestCode in [htAvailableItems, htNone]) and
|
|
TdxCustomLayoutItemAccess(SourceItem).CanRemove and (Source <> dsCustomizeFormAvailableItems);
|
|
end;
|
|
|
|
function TdxLayoutControlDragAndDropObject.GetSourceControl: TdxCustomLayoutControl;
|
|
begin
|
|
Result := TdxCustomLayoutControl(inherited Control);
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.ResetDragAndDropObjects;
|
|
begin
|
|
SourceItem := nil;
|
|
DestinationItem := nil;
|
|
DestinationGroup := nil;
|
|
FHitTest := nil;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.ResetDragAndDrop;
|
|
begin
|
|
ResetDragAndDropObjects;
|
|
TdxCustomLayoutControlAccess(SourceControl).CustomizeFormUpdate([cfutContent, cfutSelection]);
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.SetAreaPart(Value: TdxLayoutAreaPart);
|
|
begin
|
|
if FAreaPart <> Value then
|
|
begin
|
|
FAreaPart := Value;
|
|
Dirty := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.SetDestinationControl(Value: TdxCustomLayoutControl);
|
|
begin
|
|
if FDestinationControl <> Value then
|
|
begin
|
|
FDestinationControl := Value;
|
|
Dirty := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.SetDestinationGroup(Value: TdxLayoutGroup);
|
|
begin
|
|
if FDestinationGroup <> Value then
|
|
begin
|
|
if FDestinationGroup <> nil then
|
|
FreeAndNil(FDestinationImage);
|
|
FDestinationGroup := Value;
|
|
if FDestinationGroup <> nil then
|
|
CreateDestinationImage;
|
|
Dirty := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.SetDestinationItem(Value: TdxCustomLayoutItem);
|
|
begin
|
|
if FDestinationItem <> Value then
|
|
begin
|
|
FDestinationItem := Value;
|
|
Dirty := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.SetSourceItem(Value: TdxCustomLayoutItem);
|
|
begin
|
|
if FSourceItem <> Value then
|
|
FSourceItem := Value;
|
|
end;
|
|
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.CreateDragImage;
|
|
begin
|
|
FDragImage := TcxDragImage.Create;
|
|
PaintDragImage;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.CreateDestinationImage;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if (DestinationItem = nil) or TdxCustomLayoutItemAccess(DestinationItem).IsAvailable then
|
|
Exit;
|
|
FDestinationImage := TcxDragImage.Create;
|
|
FDestinationImage.PopupParent := GetParentForm(DestinationControl);
|
|
R := DestinationGroup.ViewInfo.SelectionArea;
|
|
OffsetRect(R, -R.Left, -R.Top);
|
|
FDestinationImage.SetBounds(R.Left, R.Top, R.Right, R.Bottom);
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.DirtyChanged;
|
|
begin
|
|
inherited DirtyChanged;
|
|
FNeedRepaintDestinationImage := True;
|
|
end;
|
|
|
|
function TdxLayoutControlDragAndDropObject.GetDragAndDropCursor(Accepted: Boolean): TCursor;
|
|
begin
|
|
if CanDrop then
|
|
Result := crDefault
|
|
else
|
|
if CanRemove then
|
|
Result := crdxLayoutControlRemove
|
|
else
|
|
Result := crdxLayoutControlNoDrop;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.PaintDestinationImage;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
FDestinationImage.Canvas.SaveState;
|
|
try
|
|
R := FDestinationImage.ClientRect;
|
|
FDestinationImage.Canvas.FrameRect(R, dxLayoutDestinationBorderColor);
|
|
InflateRect(R, -1, -1);
|
|
FDestinationImage.Canvas.FillRect(R, dxLayoutDestinationColor);
|
|
R := TdxLayoutGroupViewInfoAccess(DestinationGroup.ViewInfo).GetAreaPartBounds(AreaPart, DestinationItem.ViewInfo);
|
|
with DestinationGroup.ViewInfo.SelectionArea do
|
|
OffsetRect(R, -Left, -Top);
|
|
FDestinationImage.Canvas.FrameRect(R, dxLayoutDestinationBorderColor);
|
|
finally
|
|
FDestinationImage.Canvas.RestoreState;
|
|
end;
|
|
FNeedRepaintDestinationImage := False;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.PaintDragImage;
|
|
var
|
|
AViewInfo: TdxCustomLayoutItemViewInfo;
|
|
|
|
function GetItemDragBounds: TRect;
|
|
begin
|
|
Result := AViewInfo.SelectionBorderRect;
|
|
end;
|
|
|
|
procedure CalculateDragImageOffset;
|
|
begin
|
|
if not SourceItem.ActuallyVisible then
|
|
FDragImageOffset := cxNullPoint
|
|
else
|
|
begin
|
|
case Source of
|
|
dsControl:
|
|
FDragImageOffset := cxPointOffset(GetItemDragBounds.TopLeft,
|
|
SourceControl.ScreenToClient(FStartDragPoint), False);
|
|
dsCustomizeFormTreeViewItems:
|
|
FDragImageOffset := cxPointOffset(GetItemDragBounds.TopLeft, cxRectCenter(GetItemDragBounds), False);
|
|
else
|
|
FDragImageOffset := cxNullPoint;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function GetViewInfoBounds(AHasBorderChanged: Boolean): TRect;
|
|
begin
|
|
if TdxCustomLayoutItemAccess(SourceItem).IsAvailable or not TdxCustomLayoutItemViewInfoAccess(AViewInfo).ActuallyVisible then
|
|
Result := Rect(-TdxCustomLayoutItemViewInfoAccess(AViewInfo).CalculateMinWidth, -TdxCustomLayoutItemViewInfoAccess(AViewInfo).CalculateMinHeight, 0, 0)
|
|
else
|
|
begin
|
|
Result := TdxCustomLayoutItemViewInfoAccess(AViewInfo).OriginalBounds;
|
|
if AHasBorderChanged then
|
|
Result := TdxLayoutGroupViewInfoAccess(AViewInfo).GetItemAreaBounds(Result);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ANeedDestroyViewInfo: Boolean;
|
|
APrevHasBorder: Boolean;
|
|
APrevBounds: TRect;
|
|
begin
|
|
if TdxCustomLayoutItemAccess(SourceItem).IsAvailable then
|
|
begin
|
|
AViewInfo := TdxCustomLayoutItemAccess(SourceItem).GetViewInfoClass.Create(SourceControl.ViewInfo, nil, SourceItem);
|
|
ANeedDestroyViewInfo := True;
|
|
end
|
|
else
|
|
begin
|
|
AViewInfo := SourceItem.ViewInfo;
|
|
ANeedDestroyViewInfo := False;
|
|
APrevBounds := AViewInfo.Bounds;
|
|
end;
|
|
try
|
|
APrevHasBorder := TdxCustomLayoutItemViewInfoAccess(SourceItem.ViewInfo).HasBorder;
|
|
TdxLayoutControlViewInfoAccess(SourceControl.ViewInfo).IsDragImagePainted := True;
|
|
try
|
|
AViewInfo.Calculate(GetViewInfoBounds(TdxCustomLayoutItemViewInfoAccess(SourceItem.ViewInfo).HasBorder <> APrevHasBorder));
|
|
|
|
FDragImage.SetBounds(0, 0, cxRectWidth(GetItemDragBounds), cxRectHeight(GetItemDragBounds));
|
|
FDragImage.Canvas.WindowOrg := GetItemDragBounds.TopLeft;
|
|
try
|
|
with TdxCustomLayoutItemPainterAccess(TdxCustomLayoutItemViewInfoAccess(AViewInfo).GetPainterClass.Create(FDragImage.Canvas, AViewInfo)) do
|
|
try
|
|
Paint;
|
|
DoDrawSelectionFrame;
|
|
PaintSpecificPart;
|
|
finally
|
|
Free;
|
|
end;
|
|
finally
|
|
FDragImage.Canvas.WindowOrg := cxNullPoint;
|
|
end;
|
|
CalculateDragImageOffset;
|
|
finally
|
|
TdxLayoutControlViewInfoAccess(SourceControl.ViewInfo).IsDragImagePainted := False;
|
|
end;
|
|
finally
|
|
if ANeedDestroyViewInfo then
|
|
AViewInfo.Destroy
|
|
else
|
|
AViewInfo.Calculate(APrevBounds);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.RefreshDestinationImage;
|
|
const
|
|
CustomizeFormHitTestCodes = [htCustomizeForm, htAvailableItems, htTreeViewItems];
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
if (DestinationGroup = nil) or (DestinationItem = nil) or (AreaPart = apNone) or (FHitTest.HitTestCode in CustomizeFormHitTestCodes) then Exit;
|
|
PaintDestinationImage;
|
|
if FDestinationImage.Visible then
|
|
FDestinationImage.Invalidate
|
|
else
|
|
begin
|
|
P := DestinationControl.ClientToScreen(DestinationGroup.ViewInfo.SelectionArea.TopLeft);
|
|
FDestinationImage.MoveTo(P);
|
|
FDestinationImage.Show;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.ShowDragImage(const P: TPoint);
|
|
begin
|
|
if FDragImage <> nil then
|
|
begin
|
|
FDragImage.MoveTo(P);
|
|
FDragImage.Show;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.BeginDragAndDrop;
|
|
begin
|
|
inherited BeginDragAndDrop;
|
|
//#DG SourceItem.SelectComponent([]);
|
|
TdxCustomLayoutControlAccess(SourceControl).DragAndDropBegan;
|
|
CreateDragImage;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.DragAndDrop(const P: TPoint; var Accepted: Boolean);
|
|
|
|
function FindDestLayoutControl(const P: TPoint): TdxCustomLayoutControl;
|
|
var
|
|
AControl: TWinControl;
|
|
AWnd: THandle;
|
|
begin
|
|
Result := nil;
|
|
AWnd := cxWindowFromPoint(P);
|
|
while (Result = nil) and (AWnd <> 0) do
|
|
begin
|
|
AControl := FindControl(AWnd);
|
|
if (AControl is TdxCustomLayoutControl) and (AControl.Owner = SourceControl.Owner) and
|
|
TdxCustomLayoutControlAccess(AControl).AllowDrop then
|
|
Result := TdxLayoutControl(AControl);
|
|
AWnd := GetAncestor(AWnd, GA_PARENT);
|
|
end;
|
|
if Result = nil then
|
|
Result := SourceControl;
|
|
end;
|
|
|
|
procedure DetermineDestinationControl(const P: TPoint);
|
|
begin
|
|
DestinationControl := FindDestLayoutControl(P);
|
|
end;
|
|
|
|
procedure DetermineDestinationItem;
|
|
begin
|
|
// DetermineDestinationItems(ADestItems);
|
|
// UpdatedestinationPlaces(AScreenPoint, ADestItems, ADestinationItem);
|
|
|
|
DestinationItem := FHitTest.GetDesinationItem;
|
|
if (DestinationItem = SourceItem) or
|
|
((DestinationItem is TdxLayoutItem) and TdxCustomLayoutItemAccess(DestinationItem).IsAvailable and (DestinationItem.Parent = nil)) or
|
|
((DestinationItem is TdxLayoutGroup) and not SourceItem.CanMoveTo(DestinationItem)) then
|
|
DestinationItem := nil;
|
|
end;
|
|
|
|
procedure DetermineAreaPart(const P: TPoint);
|
|
const
|
|
CustomizeFormTreeViewItemAreaPart: array [TdxLayoutDirection] of TdxLayoutAreaPart = (apRight, apBottom, apBottom);
|
|
var
|
|
AAreaPart: TdxLayoutAreaPart;
|
|
begin
|
|
AAreaPart := apNone;
|
|
if FHitTest.IsDeterminedAreaPart then
|
|
AAreaPart := FHitTest.GetAreaPart
|
|
else
|
|
if (DestinationItem <> nil) then
|
|
AAreaPart := TdxCustomLayoutItemViewInfoAccess(DestinationItem.ViewInfo).GetAreaPart(P);
|
|
AreaPart := AAreaPart;
|
|
end;
|
|
|
|
procedure DetermineDestinationGroup;
|
|
begin
|
|
if DestinationItem = nil then
|
|
DestinationGroup := nil
|
|
else
|
|
begin
|
|
if DestinationItem.IsRoot or (AreaPart in [apCenter, apFirstChild, apLastChild]) then
|
|
DestinationGroup := TdxLayoutGroup(DestinationItem)
|
|
else
|
|
DestinationGroup := DestinationItem.Parent;
|
|
end;
|
|
end;
|
|
|
|
procedure DetermineHitTest(const P: TPoint);
|
|
begin
|
|
if IsWindowVisible(DestinationControl.Handle) then
|
|
FHitTest := DestinationControl.ViewInfo.GetHitTest(P)
|
|
else
|
|
FHitTest := SourceControl.ViewInfo.GetHitTest(P);
|
|
end;
|
|
|
|
procedure UpdateDestinationImageState;
|
|
begin
|
|
if FNeedRepaintDestinationImage then
|
|
RefreshDestinationImage;
|
|
end;
|
|
|
|
var
|
|
AScreenPoint, ADestPoint, ADragImagePoint: TPoint;
|
|
begin
|
|
AScreenPoint := Control.ClientToScreen(P);
|
|
DetermineDestinationControl(AScreenPoint);
|
|
ADestPoint := DestinationControl.ScreenToClient(AScreenPoint);
|
|
|
|
ADragImagePoint := cxPointOffset(AScreenPoint, FDragImageOffset);
|
|
ShowDragImage(ADragImagePoint);
|
|
|
|
DetermineHitTest(ADestPoint);
|
|
DetermineDestinationItem;
|
|
DetermineAreaPart(ADestPoint);
|
|
DetermineDestinationGroup;
|
|
|
|
Accepted := AreaPart <> apNone;
|
|
|
|
UpdateDestinationImageState;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.EndDragAndDrop(Accepted: Boolean);
|
|
|
|
function GetDestPosition: Integer;
|
|
begin
|
|
case AreaPart of
|
|
apRight, apBottom, apAfter:
|
|
if DestinationItem = DestinationGroup then
|
|
Result := DestinationGroup.VisibleCount
|
|
else
|
|
Result := DestinationItem.VisibleIndex + 1;
|
|
apLeft, apTop, apBefore:
|
|
if DestinationItem = DestinationGroup then
|
|
Result := 0
|
|
else
|
|
Result := DestinationItem.VisibleIndex;
|
|
apLastChild:
|
|
Result := DestinationGroup.VisibleCount;
|
|
else
|
|
Result := 0;
|
|
end;
|
|
if (SourceItem.Parent = DestinationGroup) and (SourceItem.VisibleIndex < Result) then
|
|
Dec(Result);
|
|
end;
|
|
|
|
function GetLayoutDirection: TdxLayoutDirection;
|
|
begin
|
|
Result := DestinationGroup.LayoutDirection;
|
|
end;
|
|
|
|
function GetOrthogonalDirection: TdxLayoutDirection;
|
|
begin
|
|
Result := TdxLayoutGroupAccess(DestinationItem.Parent).GetHelperClass.GetOrthogonalDirection;
|
|
end;
|
|
|
|
function IsHorizontalAreaPart: Boolean;
|
|
begin
|
|
Result := AreaPart in [apLeft, apRight, apAfter, apBefore];
|
|
end;
|
|
|
|
function IsVerticalAreaPart: Boolean;
|
|
begin
|
|
Result := AreaPart in [apTop, apBottom, apAfter, apBefore];
|
|
end;
|
|
|
|
procedure DoInsert;
|
|
begin
|
|
SourceItem.MoveTo(DestinationGroup, GetDestPosition, True);
|
|
end;
|
|
|
|
procedure DoCreateGroup;
|
|
const
|
|
LayoutDirections: array[Boolean] of TdxLayoutDirection =
|
|
(ldVertical, ldHorizontal);
|
|
var
|
|
AGroup: TdxLayoutGroup;
|
|
begin
|
|
if DestinationItem.IsRoot then
|
|
begin
|
|
DestinationGroup.PutChildrenIntoHiddenGroup;
|
|
DestinationGroup.LayoutDirection := LayoutDirections[IsHorizontalAreaPart];
|
|
SourceItem.MoveTo(DestinationGroup, GetDestPosition, True);
|
|
end
|
|
else
|
|
begin
|
|
AGroup := DestinationItem.PutIntoHiddenGroup(GetOrthogonalDirection);
|
|
SourceItem.MoveTo(AGroup, GetDestPosition, True);
|
|
end;
|
|
end;
|
|
|
|
procedure DoContentInsert;
|
|
begin
|
|
DestinationGroup.PutChildrenIntoHiddenGroup;
|
|
DestinationGroup.LayoutDirection := GetOrthogonalDirection;
|
|
SourceItem.MoveTo(DestinationGroup, GetDestPosition, True);
|
|
end;
|
|
|
|
function CanProcessDrop: Boolean;
|
|
begin
|
|
Result := Accepted and (DestinationControl <> nil) and ((CanDrop and (DestinationItem <> nil)) or CanRemove);
|
|
end;
|
|
|
|
var
|
|
ANeedUpdateCustomizeForm: Boolean;
|
|
ALinkSelf: TcxObjectLink;
|
|
begin
|
|
FreeAndNil(FDragImage);
|
|
Dirty := True;
|
|
if CanProcessDrop then
|
|
begin
|
|
ANeedUpdateCustomizeForm := False;
|
|
TdxCustomLayoutControlAccess(SourceControl).CustomizeFormBeginUpdate;
|
|
TdxCustomLayoutControlAccess(DestinationControl).CustomizeFormBeginUpdate;
|
|
try
|
|
TdxCustomLayoutControlAccess(DestinationControl).SaveToUndo;
|
|
DestinationControl.BeginUpdate;
|
|
TdxCustomLayoutControlAccess(SourceControl).SaveToUndo;
|
|
SourceControl.BeginUpdate;
|
|
try
|
|
if CanDrop and (DestinationGroup <> nil) then
|
|
begin
|
|
ANeedUpdateCustomizeForm := True;
|
|
case TdxLayoutGroupViewInfoAccess(DestinationGroup.ViewInfo).GetActionType(AreaPart) of
|
|
atInsert:
|
|
DoInsert;
|
|
atCreateGroup:
|
|
DoCreateGroup;
|
|
atContentInsert:
|
|
DoContentInsert;
|
|
end;
|
|
end
|
|
else
|
|
if CanRemove then
|
|
begin
|
|
SourceItem.Parent := nil;
|
|
ANeedUpdateCustomizeForm := True;
|
|
end;
|
|
finally
|
|
ALinkSelf := cxAddObjectLink(SourceItem);
|
|
try
|
|
ResetDragAndDropObjects;
|
|
SourceControl.EndUpdate;
|
|
DestinationControl.EndUpdate;
|
|
if ALinkSelf.Ref <> nil then
|
|
(ALinkSelf.Ref as TdxCustomLayoutItem).MakeVisible;
|
|
finally
|
|
cxRemoveObjectLink(ALinkSelf);
|
|
end;
|
|
end;
|
|
finally
|
|
TdxCustomLayoutControlAccess(SourceControl).CustomizeFormCancelUpdate;
|
|
TdxCustomLayoutControlAccess(DestinationControl).CustomizeFormCancelUpdate;
|
|
if ANeedUpdateCustomizeForm then
|
|
begin
|
|
TdxCustomLayoutControlAccess(SourceControl).CustomizeFormUpdate([cfutContent, cfutSelection]);
|
|
if (DestinationControl <> SourceControl) and TdxCustomLayoutControlAccess(DestinationControl).IsCustomization then
|
|
TdxCustomLayoutControlAccess(DestinationControl).CustomizeFormUpdate([cfutContent, cfutSelection]);
|
|
end;
|
|
end;
|
|
SourceControl.Update;
|
|
if DestinationControl <> SourceControl then
|
|
DestinationControl.Update;
|
|
TdxCustomLayoutControlAccess(SourceControl).Modified;
|
|
end
|
|
else
|
|
ResetDragAndDrop;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TdxLayoutControlDragAndDropObject.Init(ASource: TdxLayoutDragSource;
|
|
ASourceItem: TdxCustomLayoutItem);
|
|
begin
|
|
SourceControl.Update;
|
|
Source := ASource;
|
|
SourceItem := ASourceItem;
|
|
FStartDragPoint := GetMouseCursorPos;
|
|
end;
|
|
|
|
{ TdxLayoutDragAndDropHelper }
|
|
|
|
constructor TdxLayoutDragAndDropHelper.Create(
|
|
AControl: TdxCustomLayoutControl);
|
|
begin
|
|
inherited Create(AControl);
|
|
Reset;
|
|
end;
|
|
|
|
procedure TdxLayoutDragAndDropHelper.InitializeDragItem(AItem: TdxCustomLayoutItem;
|
|
X, Y: Integer);
|
|
begin
|
|
FMouseDownPos := Point(X, Y);
|
|
FDragItem := AItem;
|
|
end;
|
|
|
|
procedure TdxLayoutDragAndDropHelper.Reset;
|
|
begin
|
|
FDragItem := nil;
|
|
FMouseDownPos := cxInvalidPoint;
|
|
end;
|
|
|
|
procedure TdxLayoutDragAndDropHelper.TryBeginDragAndDrop(X, Y: Integer;
|
|
ASource: TdxLayoutDragSource);
|
|
begin
|
|
if CanBeginDragAndDrop(X, Y) then
|
|
BeginDragAndDrop(ASource);
|
|
end;
|
|
|
|
function TdxLayoutDragAndDropHelper.CanBeginDragAndDrop(X, Y: Integer): Boolean;
|
|
begin
|
|
Result := TdxCustomLayoutControlAccess(Control).CanDragAndDrop and (Control.DragAndDropState = ddsNone) and
|
|
not cxPointIsEqual(FMouseDownPos, cxInvalidPoint) and not IsPointInDragDetectArea(FMouseDownPos, X, Y) and
|
|
(DragItem <> nil) and TdxCustomLayoutItemAccess(DragItem).CanDragAndDrop;
|
|
end;
|
|
|
|
procedure TdxLayoutDragAndDropHelper.BeginDragAndDrop(ASource: TdxLayoutDragSource);
|
|
begin
|
|
DragAndDropObject.Init(ASource, DragItem);
|
|
Control.BeginDragAndDrop;
|
|
end;
|
|
|
|
function TdxLayoutDragAndDropHelper.GetDragAndDropObject: TdxLayoutControlDragAndDropObject;
|
|
begin
|
|
Result := TdxLayoutControlDragAndDropObject(Control.DragAndDropObject);
|
|
end;
|
|
|
|
initialization
|
|
Screen.Cursors[crdxLayoutControlNoDrop] := LoadCursor(HInstance, 'DXLAYOUTCONTROLNODROP');
|
|
Screen.Cursors[crdxLayoutControlRemove] := LoadCursor(HInstance, 'DXLAYOUTCONTROLREMOVE');
|
|
|
|
end.
|