Componentes.Terceros.DevExp.../official/x.48/ExpressLayout Control 2/Sources/dxLayoutImport.pas
2010-01-18 18:33:24 +00:00

1585 lines
46 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressLayoutControl main components }
{ }
{ 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 dxLayoutImport;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, cxClasses, dxLayoutControl, cxControls, cxStyles,
cxGraphics, ExtCtrls, cxContainer, cxLabel, cxLookAndFeelPainters, cxGroupBox,
Types, cxLookAndFeels, cxSplitter, Menus, cxDropDownEdit, cxCheckBox, cxButtons,
cxRadioGroup, cxEdit, cxTextEdit, cxMaskEdit, cxSpinEdit, ComCtrls, cxPC,
dxLayoutcxEditAdapters, dxLayoutLookAndFeels;
type
TdxAutoLayout = class;
{ TdxAutoLayoutItem }
TdxAutoLayoutItem = class
private
FAlign: TAlign;
FAutoLayout: TdxAutoLayout;
FBoundsRect: TRect;
FCaption: string;
FCaptionLayout: TdxCaptionLayout;
FControl: TControl;
FLabeled: Boolean;
FLabeledBoundsRect: TRect;
FLayoutControlItem: TdxCustomLayoutItem;
procedure ProcessAnchors;
public
constructor Create(AAutoLayout: TdxAutoLayout; AControl: TControl);
procedure Apply(AProcessAnchors: Boolean = True);
procedure Assign(Source: TdxAutoLayoutItem);
procedure CreateLayoutControlItem(AGroup: TdxLayoutGroup);
function CanResize: Boolean;
function CreateGroup(AGroup: TdxLayoutGroup): TdxLayoutGroup;
function CreateItem(AGroup: TdxLayoutGroup): TdxCustomLayoutItem;
function CreateSeparator(AGroup: TdxLayoutGroup): TdxCustomLayoutItem;
function CreateSplitter(AGroup: TdxLayoutGroup): TdxCustomLayoutItem;
function CreateTabbedGroup(AGroup: TdxLayoutGroup): TdxCustomLayoutItem;
function GetGroupCaption: string;
function GetLabelCaption: string;
function IsAligned: Boolean;
function IsButton: Boolean;
function IsGroup: Boolean;
function IsHiddenGroup: Boolean;
function IsLabel: Boolean;
function IsSeparator: Boolean;
function IsSplitter: Boolean;
function IsPageControl: Boolean;
function IsStandaloneLabel: Boolean;
function GetFocusControl: TWinControl;
procedure SetLabelInfo(ALabel: TControl);
property Align: TAlign read FAlign;
property BoundsRect: TRect read FBoundsRect;
property Caption: string read FCaption;
property CaptionLayout: TdxCaptionLayout read FCaptionLayout;
property Control: TControl read FControl;
property Labeled: Boolean read FLabeled;
property LayoutControlItem: TdxCustomLayoutItem read FLayoutControlItem;
end;
{ TdxAutoLayoutItemList }
TdxAutoLayoutItemList = class(TList)
private
function GetItem(Index: Integer): TdxAutoLayoutItem;
public
function CanConvert(ASide: TcxBorder): Boolean;
function First: TdxAutoLayoutItem;
procedure FreeItems;
function IsButtons: Boolean;
function Last: TdxAutoLayoutItem;
property Items[Index: Integer]: TdxAutoLayoutItem read GetItem; default;
end;
{ TdxAutoLayoutOwnedItemList }
TdxAutoLayoutOwnedItemList = class(TcxObjectList)
private
FAutoLayout: TdxAutoLayout;
function GetItem(Index: Integer): TdxAutoLayoutItem;
public
constructor Create(AAutoLayout: TdxAutoLayout);
function Add(AControl: TControl): TdxAutoLayoutItem;
procedure DeleteItems(AItems: TdxAutoLayoutItemList);
procedure Extract(AIndex: Integer);
function Find(AControl: TControl): TdxAutoLayoutItem;
function Remove(AControl: TControl): Boolean;
procedure RemoveItems(AItems: TdxAutoLayoutItemList);
property Items[Index: Integer]: TdxAutoLayoutItem read GetItem; default;
end;
{ TdxAutoLayoutHelper }
TdxAutoLayoutHelper = class
private
FAlignedItems: TdxAutoLayoutOwnedItemList;
FAligns: set of TAlign;
FBottommostItem: TdxAutoLayoutItem;
FContainer: TWinControl;
FItems: TdxAutoLayoutOwnedItemList;
FLeftmostItem: TdxAutoLayoutItem;
FNonAlignedBoundsRect: TRect;
FOwner: TdxAutoLayout;
FRightmostItem: TdxAutoLayoutItem;
FRoot: TdxLayoutGroup;
FTopmostItem: TdxAutoLayoutItem;
function CanExport(AControl: TControl): Boolean;
function FindBottommostItem: TdxAutoLayoutItem;
function FindLeftmostItem: TdxAutoLayoutItem;
function FindRightmostItem: TdxAutoLayoutItem;
function FindTopmostItem: TdxAutoLayoutItem;
function GetControlAtPos(X, Y: Integer): TControl;
function GetFocusControl(AItem: TdxAutoLayoutItem): TWinControl;
function GetItemCount: Integer;
function HasItemsAtRect(const R: TRect): Boolean;
procedure MakeNewRoot;
procedure PopulateItems;
procedure PopulateItemsAtRect(AItems: TdxAutoLayoutItemList; const R: TRect);
procedure ProcessLabels;
function UpdateUtmostItems: TRect;
protected
procedure CheckRootDirection(ADirection: TdxLayoutDirection);
procedure ConvertGroup(AItems: TdxAutoLayoutItemList; ASide: TcxBorder);
procedure DoAlignedControls;
procedure DoNonAlignedControls;
procedure DoExecute; virtual;
procedure GenerateAligned(AAlign: TAlign);
procedure GenerateAlignedLayout; virtual;
procedure GenerateNonAlignedLayout; virtual;
procedure GetSideItemGroup(AItems: TdxAutoLayoutItemList; ASide: TcxBorder);
procedure Initialize(AContainer: TWinControl; ARoot: TdxLayoutGroup); virtual;
property Owner: TdxAutoLayout read FOwner;
property Root: TdxLayoutGroup read FRoot;
public
constructor Create(AOwner: TdxAutoLayout);
destructor Destroy; override;
procedure Execute(AContainer: TWinControl; ARoot: TdxLayoutGroup);
property Container: TWinControl read FContainer;
property ItemCount: Integer read GetItemCount;
property Items: TdxAutoLayoutOwnedItemList read FItems;
end;
{ TdxAutoLayout }
TdxAutoLayout = class
private
FFocusControlDistanceX: Byte;
FFocusControlDistanceY: Byte;
FControl: TdxCustomLayoutControl;
FConvertPageControls: Boolean;
FRecursive: Boolean;
FSmartFindFocusControl: Boolean;
FUseLabeledItems: Boolean;
protected
procedure CorrectAlign(AGroup: TdxLayoutGroup);
procedure DoExecute(AContainer: TWinControl; ARecursive: Boolean = True); virtual;
property Control: TdxCustomLayoutControl read FControl;
property Recursive: Boolean read FRecursive;
public
constructor Create(AControl: TdxCustomLayoutControl);
procedure Execute(AContainer: TWinControl; ARecursive: Boolean = True);
property ConvertPageControls: Boolean read FConvertPageControls write FConvertPageControls default True;
property FocusControlDistanceX: Byte read FFocusControlDistanceX write FFocusControlDistanceX default 48;
property FocusControlDistanceY: Byte read FFocusControlDistanceY write FFocusControlDistanceY default 16;
property SmartFindFocusControl: Boolean read FSmartFindFocusControl write FSmartFindFocusControl default True;
property UseLabeledItems: Boolean read FUseLabeledItems write FUseLabeledItems default True;
end;
{ TfmImport }
TfmImport = class(TForm)
seDeltaX: TcxSpinEdit;
seDeltaY: TcxSpinEdit;
btnImport: TcxButton;
btnCancel: TcxButton;
cbContainers: TcxComboBox;
cbUseLabeledItems: TcxCheckBox;
cbAssociate: TcxCheckBox;
cbConvertPageControls: TcxCheckBox;
dxLayoutControl1Group_Root: TdxLayoutGroup;
dxLayoutControl1: TdxLayoutControl;
dxLayoutControl1Item1: TdxLayoutItem;
dxLayoutControl1Item2: TdxLayoutItem;
dxLayoutControl1Item3: TdxLayoutItem;
dxLayoutControl1Group2: TdxLayoutGroup;
dxLayoutControl1Item4: TdxLayoutItem;
dxLayoutControl1Item5: TdxLayoutItem;
dxLayoutControl1Group4: TdxLayoutGroup;
dxLayoutControl1Item6: TdxLayoutItem;
dxLayoutControl1Item7: TdxLayoutItem;
dxLayoutControl1Item8: TdxLayoutItem;
dxLayoutControl1LabeledItem1: TdxLayoutLabeledItem;
dxLayoutControl1LabeledItem2: TdxLayoutLabeledItem;
dxLayoutControl1Group5: TdxLayoutGroup;
dxLayoutLookAndFeelList1: TdxLayoutLookAndFeelList;
dxLayoutCxLookAndFeel2: TdxLayoutCxLookAndFeel;
procedure cbAssociateClick(Sender: TObject);
public
end;
procedure ImportLayout(ALayoutControl: TdxLayoutControl);
implementation
uses
cxGeometry, Math;
{$R *.dfm}
type
TControlAccess = class(TControl);
TWinControlAccess = class(TWinControl);
TLabelAccess = class(TCustomLabel);
TcxLabelAccess = class(TcxCustomLabel);
TdxLayoutGroupAcsess = class(TdxLayoutGroup);
TdxLayoutControlAccess = class(TdxLayoutControl);
TdxCustomLayoutItemAccess = class(TdxCustomLayoutItem);
TdxLayoutItemAccess = class(TdxLayoutItem);
TStaticTextAccess = class(TCustomStaticText);
TcxGroupBoxAccess = class(TcxCustomGroupBox);
TGroupBoxAccess = class(TCustomGroupBox);
TPanelAccess = class(TCustomPanel);
{ TdxSideItem }
TdxSideItem = class
private
FItems: TdxAutoLayoutItemList;
FSide: TcxBorder;
function GetDirection: TdxLayoutDirection;
protected
FOrder: Integer;
public
constructor Create(AItems: TdxAutoLayoutItemList; ASide: TcxBorder);
destructor Destroy; override;
property Direction: TdxLayoutDirection read GetDirection;
property Items: TdxAutoLayoutItemList read FItems write FItems;
property Side: TcxBorder read FSide write FSide;
end;
{ TdxSideItem }
TdxSideItemList = class(TcxObjectList)
private
FCurrentOrder: Integer;
FHelper: TdxAutoLayoutHelper;
function GetItem(Index: Integer): TdxSideItem;
protected
procedure SetCreationOrder(AFirst, ALast: Integer);
property Helper: TdxAutoLayoutHelper read FHelper;
public
constructor Create(AHelper: TdxAutoLayoutHelper);
function Add(AItems: TdxAutoLayoutItemList; ASide: TcxBorder): TdxSideItem;
procedure SortCreationOrder;
procedure Build;
property Items[Index: Integer]: TdxSideItem read GetItem; default;
end;
function CompareTop(Item1, Item2: Pointer): Integer;
begin
Result := TdxAutoLayoutItem(Item1).BoundsRect.Top - TdxAutoLayoutItem(Item2).BoundsRect.Top;
end;
function CompareBottom(Item1, Item2: Pointer): Integer;
begin
Result := TdxAutoLayoutItem(Item2).BoundsRect.Bottom - TdxAutoLayoutItem(Item1).BoundsRect.Bottom;
end;
function CompareLeft(Item1, Item2: Pointer): Integer;
begin
Result := TdxAutoLayoutItem(Item1).BoundsRect.Left - TdxAutoLayoutItem(Item2).BoundsRect.Left;
end;
function CompareRight(Item1, Item2: Pointer): Integer;
begin
Result := TdxAutoLayoutItem(Item2).BoundsRect.Right - TdxAutoLayoutItem(Item1).BoundsRect.Right;
end;
{ TdxSideItem }
constructor TdxSideItem.Create(AItems: TdxAutoLayoutItemList; ASide: TcxBorder);
var
I: Integer;
begin
FSide := ASide;
FItems := TdxAutoLayoutItemList.Create;
for I := 0 to AItems.Count - 1 do
FItems.Add(AItems[I]);
end;
destructor TdxSideItem.Destroy;
begin
FItems.Free;
inherited Destroy;
end;
function TdxSideItem.GetDirection: TdxLayoutDirection;
begin
if FSide in [bTop, bBottom] then
Result := ldHorizontal
else
Result := ldVertical;
end;
{ TdxSideItemList }
constructor TdxSideItemList.Create(AHelper: TdxAutoLayoutHelper);
begin
FHelper := AHelper;
end;
function TdxSideItemList.Add(AItems: TdxAutoLayoutItemList;
ASide: TcxBorder): TdxSideItem;
begin
Result := TdxSideItem.Create(AItems, ASide);
inherited Add(Result);
Helper.Items.DeleteItems(AItems);
end;
procedure TdxSideItemList.Build;
var
I: Integer;
ADirection: TdxLayoutDirection;
begin
if Count = 0 then Exit;
SortCreationOrder;
ADirection := Items[0].Direction;
Helper.CheckRootDirection(ADirection);
for I := 0 to Count - 1 do
begin
if ADirection <> Items[I].Direction then
begin
ADirection := Items[I].Direction;
Helper.CheckRootDirection(ADirection);
end;
Helper.ConvertGroup(Items[I].Items, Items[I].Side);
Application.ProcessMessages;
end;
end;
procedure TdxSideItemList.SetCreationOrder(AFirst, ALast: Integer);
var
I: Integer;
begin
for I := AFirst to ALast do
if Items[I].Side in [bTop, bLeft] then
begin
Items[I].FOrder := FCurrentOrder;
Inc(FCurrentOrder);
end;
for I := ALast downto AFirst do
if Items[I].Side in [bRight, bBottom] then
begin
Items[I].FOrder := FCurrentOrder;
Inc(FCurrentOrder);
end;
end;
function CompareOrder(Item1, Item2: Pointer): Integer;
begin
Result := TdxSideItem(Item1).FOrder - TdxSideItem(Item2).FOrder;
end;
procedure TdxSideItemList.SortCreationOrder;
var
ADirection: TdxLayoutDirection;
AIndex, AFirst: Integer;
begin
if Count < 2 then
begin
SetCreationOrder(0, Count - 1);
Exit;
end;
FCurrentOrder := 0;
AIndex := 0;
repeat
AFirst := AIndex;
ADirection := Items[AFirst].Direction;
while (AIndex < Count) and (ADirection = Items[AIndex].Direction) do
Inc(AIndex);
SetCreationOrder(AFirst, AIndex - 1);
until AIndex = Count;
Sort(CompareOrder);
end;
function TdxSideItemList.GetItem(Index: Integer): TdxSideItem;
begin
Result := TdxSideItem(inherited Items[Index]);
end;
{ TdxAutoLayoutControl }
constructor TdxAutoLayoutItem.Create(AAutoLayout: TdxAutoLayout; AControl: TControl);
begin
FAutoLayout := AAutoLayout;
FControl := AControl;
FBoundsRect := Control.BoundsRect;
FLabeledBoundsRect := FBoundsRect;
FAlign := Control.Align;
end;
procedure TdxAutoLayoutItem.Assign(Source: TdxAutoLayoutItem);
begin
FControl := Source.Control;
FBoundsRect := Source.BoundsRect;
FLabeledBoundsRect := Source.FLabeledBoundsRect;
FAlign := Source.Align;
end;
procedure TdxAutoLayoutItem.CreateLayoutControlItem(AGroup: TdxLayoutGroup);
begin
if IsPageControl then
FLayoutControlItem := CreateTabbedGroup(AGroup)
else if IsGroup then
FLayoutControlItem := CreateGroup(AGroup)
else if IsSplitter then
FLayoutControlItem := CreateSplitter(AGroup)
else if IsSeparator then
FLayoutControlItem := CreateSeparator(AGroup)
else
FLayoutControlItem := CreateItem(AGroup);
end;
function TdxAutoLayoutItem.CanResize: Boolean;
begin
Result := not IsButton;
end;
function TdxAutoLayoutItem.CreateGroup(AGroup: TdxLayoutGroup): TdxLayoutGroup;
begin
Result := AGroup.CreateGroup;
if AGroup.LayoutDirection = ldVertical then
Result.AlignHorz := ahClient
else
Result.AlignVert := avClient;
Result.Caption := GetGroupCaption;
Result.Hidden := IsHiddenGroup;
if FAutoLayout.Recursive and (TWinControl(Control).ControlCount > 0) then
begin
with TdxAutoLayoutHelper.Create(FAutoLayout) do
try
Execute(TWinControl(Control), Result);
finally
Free;
end;
end;
end;
function TdxAutoLayoutItem.CreateItem(AGroup: TdxLayoutGroup): TdxCustomLayoutItem;
begin
if FAutoLayout.UseLabeledItems and IsStandaloneLabel then
begin
Result := AGroup.CreateItem(TdxLayoutLabeledItem);
Result.Caption := GetLabelCaption;
end
else
Result := AGroup.CreateItemForControl(Control);
end;
function TdxAutoLayoutItem.CreateSeparator(AGroup: TdxLayoutGroup): TdxCustomLayoutItem;
begin
Result := AGroup.CreateItem(TdxLayoutSeparatorItem);
end;
function TdxAutoLayoutItem.CreateSplitter(AGroup: TdxLayoutGroup): TdxCustomLayoutItem;
begin
Result := AGroup.CreateItem(TdxLayoutSplitterItem);
end;
function TdxAutoLayoutItem.CreateTabbedGroup(AGroup: TdxLayoutGroup): TdxCustomLayoutItem;
var
AControlGroup: TdxLayoutGroup;
AcxPageControl: TcxPageControl;
APageControl: TPageControl;
I, APageIndex: Integer;
begin
AControlGroup := AGroup.CreateGroup;
if AGroup.LayoutDirection = ldVertical then
AControlGroup.AlignHorz := ahClient
else
AControlGroup.AlignVert := avClient;
if not FAutoLayout.ConvertPageControls then
begin
Result := CreateItem(AControlGroup);
Exit;
end;
AControlGroup.LayoutDirection := ldTabbed;
if FAutoLayout.Recursive then
begin
if Control is TPageControl then
begin
APageControl := TPageControl(Control);
APageIndex := APageControl.ActivePageIndex;
for I := 0 to APageControl.PageCount - 1 do
begin
APageControl.ActivePageIndex := I;
Application.ProcessMessages;
AGroup := AControlGroup.CreateGroup;
AGroup.Caption := APageControl.Pages[I].Caption;
with TdxAutoLayoutHelper.Create(FAutoLayout) do
try
Execute(APageControl.Pages[I], AGroup);
finally
Free;
end;
end;
AControlGroup.ItemIndex := APageIndex;
end
else
if Control is TcxPageControl then
begin
AcxPageControl := TcxPageControl(Control);
APageIndex := AcxPageControl.ActivePageIndex;
for I := 0 to AcxPageControl.PageCount - 1 do
begin
AcxPageControl.ActivePageIndex := I;
Application.ProcessMessages;
AGroup := AControlGroup.CreateGroup;
AGroup.Caption := AcxPageControl.Pages[I].Caption;
with TdxAutoLayoutHelper.Create(FAutoLayout) do
try
Execute(AcxPageControl.Pages[I], AGroup);
finally
Free;
end;
end;
AControlGroup.ItemIndex := APageIndex;
end
end;
Result := AControlGroup;
end;
function TdxAutoLayoutItem.GetGroupCaption: string;
begin
if Control is TCustomGroupBox then
Result := TGroupBoxAccess(Control).Caption
else if Control is TcxCustomGroupBox then
Result := TcxGroupBox(Control).Caption
else if Control is TCustomPanel then
Result := TPanelAccess(Control).Caption
else
Result := '';
end;
function TdxAutoLayoutItem.GetLabelCaption: string;
begin
if Control is TCustomLabel then
Result := TLabelAccess(Control).Caption
else if Control is TCustomStaticText then
Result := TStaticTextAccess(Control).Caption
else if Control is TcxCustomLabel then
Result := TcxCustomLabel(Control).Caption
else
Result := '';
end;
function TdxAutoLayoutItem.IsAligned: Boolean;
begin
Result := Align in [alLeft, alTop, alRight, alBottom];
end;
function TdxAutoLayoutItem.IsButton: Boolean;
begin
Result := (Control is TcxCustomButton) or (Control is TButton);
end;
function TdxAutoLayoutItem.IsGroup: Boolean;
begin
Result := ((Control is TCustomGroupBox) or (Control is TCustomPanel) or
(Control is TcxCustomGroupBox)) //and (TWinControl(Control).ControlCount > 0);
end;
function TdxAutoLayoutItem.IsHiddenGroup: Boolean;
begin
if Control is TCustomGroupBox then
Result := False
else if Control is TCustomPanel then
with TPanelAccess(Control) do
Result := (BorderStyle = bsNone) and (BevelInner = bvNone) and
(BevelOuter = bvNone) {$IFDEF DELPHI9} and (BevelKind = bkNone){$ENDIF}
else if Control is TcxCustomGroupBox then
Result := TcxGroupBoxAccess(Control).Style.BorderStyle = ebsNone
else
Result := True;
end;
function TdxAutoLayoutItem.IsLabel: Boolean;
begin
Result := (Control is TCustomLabel) or (Control is TCustomStaticText) or
(Control is TcxCustomLabel);
end;
function TdxAutoLayoutItem.IsSeparator: Boolean;
begin
Result := Control is TBevel;
if Result then
Result := TBevel(Control).Shape in [bsTopLine, bsBottomLine, bsLeftLine, bsRightLine];
end;
function TdxAutoLayoutItem.IsSplitter: Boolean;
begin
Result := Control is TSplitter;
if not Result then
Result := Control is TcxSplitter;
end;
function TdxAutoLayoutItem.IsPageControl: Boolean;
begin
Result := (Control is TPageControl) or (Control is TcxPageControl);
end;
function TdxAutoLayoutItem.IsStandaloneLabel: Boolean;
begin
Result := IsLabel and not FLabeled;
end;
procedure TdxAutoLayoutItem.SetLabelInfo(ALabel: TControl);
function GetCaptionLayout(ALabel: TControl): TdxCaptionLayout;
begin
if ALabel.BoundsRect.Right <= Control.BoundsRect.Left then
Result := clLeft
else
if ALabel.BoundsRect.Left >= Control.BoundsRect.Right then
Result := clRight
else
if ALabel.BoundsRect.Bottom <= Control.BoundsRect.Top then
Result := clTop
else
Result := clBottom;
end;
procedure CorrectBounds;
begin
FLabeledBoundsRect.Left := Min(FBoundsRect.Left, ALabel.BoundsRect.Left);
FLabeledBoundsRect.Top := Min(FBoundsRect.Top, ALabel.BoundsRect.Top);
FLabeledBoundsRect.Right := Max(FBoundsRect.Right, ALabel.BoundsRect.Right);
FLabeledBoundsRect.Bottom := Max(FBoundsRect.Bottom, ALabel.BoundsRect.Bottom);
end;
begin
FCaption := TControlAccess(ALabel).Caption;
FCaptionLayout := GetCaptionLayout(ALabel);
FLabeled := True;
CorrectBounds;
end;
function TdxAutoLayoutItem.GetFocusControl: TWinControl;
begin
if Control is TcxCustomLabel then
Result := TcxLabelAccess(Control).FocusControl
else
if Control is TCustomLabel then
Result := TLabelAccess(Control).FocusControl
else
if Control is TCustomStaticText then
Result := TStaticTextAccess(Control).FocusControl
else
Result := nil;
end;
procedure TdxAutoLayoutItem.Apply(AProcessAnchors: Boolean = True);
begin
if Labeled and (LayoutControlItem is TdxLayoutItem) then
begin
TdxLayoutItem(LayoutControlItem).Caption := Caption;
TdxLayoutItem(LayoutControlItem).CaptionOptions.Layout := CaptionLayout;
end;
Control.Width := cxRectWidth(BoundsRect);
Control.Height := cxRectHeight(BoundsRect);
if AProcessAnchors then
ProcessAnchors;
end;
procedure TdxAutoLayoutItem.ProcessAnchors;
const
AlignHorzs: array[Boolean, Boolean] of TdxLayoutAlignHorz =
((ahLeft, ahRight), (ahLeft, ahClient));
AlignVerts: array[Boolean, Boolean] of TdxLayoutAlignVert =
((avTop, avBottom), (avTop, avClient));
begin
if LayoutControlItem.IsRoot then Exit;
with Control do
begin
LayoutControlItem.AlignHorz := AlignHorzs[akLeft in Anchors, akRight in Anchors];
LayoutControlItem.AlignVert := AlignVerts[akTop in Anchors, akBottom in Anchors];
end;
end;
{ TdxAutoLayoutItemList }
function TdxAutoLayoutItemList.CanConvert(ASide: TcxBorder): Boolean;
var
I, J: Integer;
begin
Result := Count > 0;
if Result then
begin
if ASide in [bTop, bBottom] then
begin
for I := 0 to Count - 1 do
for J := I + 1 to Count - 1 do
if (Items[I].BoundsRect.Top > Items[J].BoundsRect.Bottom) or
(Items[J].BoundsRect.Top > Items[I].BoundsRect.Bottom) then
begin
Result := False;
Break;
end;
end
else
begin
for I := 0 to Count - 1 do
for J := I + 1 to Count - 1 do
if (Items[I].BoundsRect.Left > Items[J].BoundsRect.Right) or
(Items[J].BoundsRect.Left > Items[I].BoundsRect.Right) then
begin
Result := False;
Break;
end;
end;
end;
end;
function TdxAutoLayoutItemList.First: TdxAutoLayoutItem;
begin
Result := Items[0];
end;
procedure TdxAutoLayoutItemList.FreeItems;
var
I: Integer;
begin
for I := 0 to Count - 1 do
Items[I].Free;
Clear;
end;
function TdxAutoLayoutItemList.GetItem(Index: Integer): TdxAutoLayoutItem;
begin
Result := TdxAutoLayoutItem(inherited Items[Index]);
end;
function TdxAutoLayoutItemList.IsButtons: Boolean;
var
I: Integer;
begin
Result := Count > 0;
if Result then
for I := 0 to Count - 1 do
if not Items[I].IsButton then
begin
Result := False;
Break;
end;
end;
function TdxAutoLayoutItemList.Last: TdxAutoLayoutItem;
begin
Result := Items[Count - 1];
end;
{ TdxAutoLayoutOwnedItemList }
constructor TdxAutoLayoutOwnedItemList.Create(AAutoLayout: TdxAutoLayout);
begin
inherited Create;
FAutoLayout := AAutoLayout;
end;
function TdxAutoLayoutOwnedItemList.Add(AControl: TControl): TdxAutoLayoutItem;
begin
Result := TdxAutoLayoutItem.Create(FAutoLayout, AControl);
inherited Add(Result);
end;
procedure TdxAutoLayoutOwnedItemList.DeleteItems(AItems: TdxAutoLayoutItemList);
var
I, AIndex: Integer;
begin
for I := 0 to AItems.Count - 1 do
begin
AIndex := IndexOf(AItems[I]);
if AIndex >= 0 then
Delete(AIndex);
end;
end;
function TdxAutoLayoutOwnedItemList.Remove(AControl: TControl): Boolean;
var
I: Integer;
begin
Result := False;
for I := 0 to Count - 1 do
if AControl = Items[I].Control then
begin
Items[I].Free;
Delete(I);
Result := True;
Break;
end;
end;
procedure TdxAutoLayoutOwnedItemList.RemoveItems(AItems: TdxAutoLayoutItemList);
var
I, AIndex: Integer;
begin
for I := 0 to AItems.Count - 1 do
begin
AIndex := IndexOf(AItems[I]);
if AIndex >= 0 then
Extract(AIndex);
end;
end;
procedure TdxAutoLayoutOwnedItemList.Extract(AIndex: Integer);
begin
Items[AIndex].Free;
Delete(AIndex);
end;
function TdxAutoLayoutOwnedItemList.Find(AControl: TControl): TdxAutoLayoutItem;
var
I: Integer;
begin
Result := nil;
for I := 0 to Count - 1 do
if AControl = Items[I].Control then
begin
Result := Items[I];
Break;
end;
end;
function TdxAutoLayoutOwnedItemList.GetItem(Index: Integer): TdxAutoLayoutItem;
begin
Result := TdxAutoLayoutItem(inherited Items[Index]);
end;
{ TdxAutoLayoutHelper }
constructor TdxAutoLayoutHelper.Create(AOwner: TdxAutoLayout);
begin
inherited Create;
FOwner := AOwner;
FAlignedItems := TdxAutoLayoutOwnedItemList.Create(Owner);
FItems := TdxAutoLayoutOwnedItemList.Create(Owner);
end;
destructor TdxAutoLayoutHelper.Destroy;
begin
FreeAndNil(FItems);
FreeAndNil(FAlignedItems);
inherited Destroy;
end;
procedure TdxAutoLayoutHelper.Execute(AContainer: TWinControl;
ARoot: TdxLayoutGroup);
begin
Initialize(AContainer, ARoot);
PopulateItems;
ProcessLabels;
DoExecute;
end;
procedure TdxAutoLayoutHelper.CheckRootDirection(ADirection: TdxLayoutDirection);
function GetRootDirection: TdxLayoutDirection;
begin
if ADirection = ldHorizontal then
Result := ldVertical
else
Result := ldHorizontal;
end;
begin
if Root.Count > 0 then
MakeNewRoot;
Root.LayoutDirection := GetRootDirection
end;
procedure TdxAutoLayoutHelper.ConvertGroup(AItems: TdxAutoLayoutItemList;
ASide: TcxBorder);
const
HAlign: array[TcxBorder] of TdxLayoutAlignHorz = (ahLeft, ahClient, ahRight, ahClient);
VAlign: array[TcxBorder] of TdxLayoutAlignVert = (avClient, avTop, avClient, avBottom);
function NewGroup: TdxLayoutGroup;
const
Directions: array[TcxBorder] of TdxLayoutDirection =
(ldVertical, ldHorizontal, ldVertical, ldHorizontal);
HAlign: array[TcxBorder] of TdxLayoutAlignHorz = (ahLeft, ahClient, ahRight, ahClient);
VAlign: array[TcxBorder] of TdxLayoutAlignVert = (avClient, avTop, avClient, avBottom);
begin
Result := Root.CreateGroup;
with Result do
begin
AlignHorz := HAlign[ASide];
AlignVert := VAlign[ASide];
Hidden := True;
LayoutDirection := Directions[ASide];
end;
end;
procedure AddItems(AGroup: TdxLayoutGroup);
var
I: Integer;
ACanProcessAnchors: Boolean;
begin
if (AItems.Count > 1) or not AItems[0].CanResize then
AGroup := NewGroup;
for I := 0 to AItems.Count - 1 do
AItems[I].CreateLayoutControlItem(AGroup);
ACanProcessAnchors := AItems.CanConvert(ASide);
for I := 0 to AItems.Count - 1 do
AItems[I].Apply(ACanProcessAnchors and not AItems[I].IsSeparator);
if (AItems.Count = 1) and (AItems[0].CanResize) then
begin
AItems[0].LayoutControlItem.AlignHorz := HAlign[ASide];
AItems[0].LayoutControlItem.AlignVert := VAlign[ASide];
end;
end;
begin
if AItems.Count = 0 then Exit;
if ASide in [bTop, bBottom] then
AItems.Sort(CompareLeft)
else
AItems.Sort(CompareTop);
AddItems(Root);
Items.RemoveItems(AItems);
end;
procedure TdxAutoLayoutHelper.DoAlignedControls;
var
I: Integer;
AItem: TdxAutoLayoutItem;
begin
for I := ItemCount - 1 downto 0 do
begin
AItem := Items[I];
if AItem.IsAligned then
begin
FAlignedItems.Add(AItem.Control);
Items.Remove(AItem.Control);
end;
end;
GenerateAlignedLayout;
end;
procedure TdxAutoLayoutHelper.DoExecute;
begin
DoAlignedControls;
DoNonAlignedControls;
end;
procedure TdxAutoLayoutHelper.DoNonAlignedControls;
var
I: Integer;
begin
if ItemCount = 0 then Exit;
GenerateNonAlignedLayout;
for I := 0 to FAlignedItems.Count - 1 do
FAlignedItems[I].Apply;
end;
procedure TdxAutoLayoutHelper.Initialize(AContainer: TWinControl;
ARoot: TdxLayoutGroup);
begin
FRoot := ARoot;
FContainer := AContainer;
FAlignedItems.Clear;
FItems.Clear;
FAligns := [];
FNonAlignedBoundsRect := Container.ClientRect;
end;
procedure TdxAutoLayoutHelper.PopulateItems;
var
I: Integer;
begin
for I := 0 to Container.ControlCount - 1 do
if CanExport(Container.Controls[I]) then
Items.Add(Container.Controls[I]);
end;
procedure TdxAutoLayoutHelper.PopulateItemsAtRect(AItems: TdxAutoLayoutItemList;
const R: TRect);
var
I: Integer;
begin
AItems.Clear;
for I := 0 to ItemCount - 1 do
if cxRectIntersect(R, Items[I].BoundsRect) then
AItems.Add(Items[I]);
end;
procedure TdxAutoLayoutHelper.GenerateAligned(AAlign: TAlign);
var
L: TdxAutoLayoutItemList;
I: Integer;
ALastBounds: TRect;
begin
L := TdxAutoLayoutItemList.Create;
try
for I := 0 to FAlignedItems.Count - 1 do
if FAlignedItems[I].Align = AAlign then
L.Add(FAlignedItems[I]);
if L.Count > 1 then
case AAlign of
alTop: L.Sort(CompareTop);
alBottom: L.Sort(CompareBottom);
alLeft: L.Sort(CompareLeft);
alRight: L.Sort(CompareRight);
end;
if L.Count > 0 then
begin
Include(FAligns, AAlign);
ALastBounds := L.Last.BoundsRect;
case AAlign of
alTop: FNonAlignedBoundsRect.Top := ALastBounds.Bottom;
alBottom: FNonAlignedBoundsRect.Bottom := ALastBounds.Top;
alLeft: FNonAlignedBoundsRect.Left := ALastBounds.Right;
alRight: FNonAlignedBoundsRect.Right := ALastBounds.Bottom;
end;
end;
for I := 0 to L.Count - 1 do
L[I].CreateLayoutControlItem(Root);
finally
L.Free;
end;
end;
procedure TdxAutoLayoutHelper.GenerateAlignedLayout;
var
I: Integer;
begin
if FAlignedItems.Count = 0 then Exit;
GenerateAligned(alTop);
GenerateAligned(alBottom);
if FAligns * [alTop, alBottom] <> [] then
MakeNewRoot;
Root.LayoutDirection := ldHorizontal;
GenerateAligned(alLeft);
GenerateAligned(alRight);
if FAligns * [alLeft, alRight] <> [] then
MakeNewRoot;
Root.LayoutDirection := ldVertical;
GenerateAligned(alClient);
for I := 0 to FAlignedItems.Count - 1 do
FAlignedItems[I].Apply;
end;
procedure TdxAutoLayoutHelper.GenerateNonAlignedLayout;
var
ASides: array[TcxBorder] of TdxAutoLayoutItemList;
I, AMostSuitableSide: TcxBorder;
ATestSides: TcxBorders;
ASideOrder: TdxSideItemList;
function GetSideWeight(ASide: TcxBorder): Integer;
begin
Result := 0;
if not (ASide in ATestSides) then Exit;
Result := Result or (Ord(ASides[ASide].CanConvert(ASide)) shl 11);
Result := Result or ((ASides[ASide].Count and $FF) shl 3);
Result := Result or (Ord(ASides[ASide].IsButtons) shl 2);
Result := Result or (Ord(ASide) and $3);
end;
function GetMostSuitableSide: TcxBorder;
var
I: TcxBorder;
AWeight: Integer;
begin
Result := bLeft;
AWeight := GetSideWeight(Result);
for I := Succ(Low(TcxBorder)) to High(TcxBorder) do
if GetSideWeight(I) > AWeight then
begin
Result := I;
AWeight := GetSideWeight(Result);
end;
end;
procedure ProcessUngroupedItems(ASide: TcxBorder);
var
AUnroupedItems: TdxAutoLayoutItemList;
I: Integer;
begin
AUnroupedItems := TdxAutoLayoutItemList.Create;
try
for I := 0 to ItemCount - 1 do
AUnroupedItems.Add(Items[I]);
ConvertGroup(AUnroupedItems, ASide);
finally
AUnroupedItems.Free;
end;
end;
begin
AMostSuitableSide := bTop;
ASideOrder := TdxSideItemList.Create(Self);
try
for I := Low(TcxBorder) to High(TcxBorder) do
ASides[I] := TdxAutoLayoutItemList.Create;
try
while ItemCount > 0 do
begin
ATestSides := [];
for I := Low(TcxBorder) to High(TcxBorder) do
begin
GetSideItemGroup(ASides[I], I);
if ASides[I].CanConvert(I) then
Include(ATestSides, I);
end;
if ATestSides = [] then Break;
AMostSuitableSide := GetMostSuitableSide;
ASideOrder.Add(ASides[AMostSuitableSide], AMostSuitableSide);
if ItemCount = 1 then
begin
ASides[AMostSuitableSide].Clear;
ASides[AMostSuitableSide].Add(Items[0]);
ASideOrder.Add(ASides[AMostSuitableSide], AMostSuitableSide);
end;
end;
finally
for I := Low(TcxBorder) to High(TcxBorder) do
ASides[I].Free;
end;
ASideOrder.Build;
finally
ASideOrder.Free;
end;
ProcessUngroupedItems(AMostSuitableSide);
end;
procedure TdxAutoLayoutHelper.GetSideItemGroup(AItems: TdxAutoLayoutItemList;
ASide: TcxBorder);
procedure InitParams(out AIncX, AIncY, AEdge: Integer; out R: TRect);
const
DeltaX: array[TcxBorder] of Integer = (1, 0, -1, 0);
DeltaY: array[TcxBorder] of Integer = (0, 1, 0, -1);
var
APos: Integer;
begin
R := UpdateUtmostItems;
AIncX := DeltaX[ASide];
AIncY := DeltaY[ASide];
case ASide of
bTop:
begin
APos := FTopmostItem.BoundsRect.Bottom;
AEdge := R.Bottom;
R := cxRect(R.Left, APos, R.Right, APos + 1);
end;
bBottom:
begin
APos := FBottommostItem.BoundsRect.Top;
AEdge := R.Top;
R := cxRect(R.Left, APos, R.Right, APos + 1);
end;
bLeft:
begin
APos := FLeftmostItem.BoundsRect.Right;
AEdge := R.Right;
R := cxRect(APos, R.Top, APos + 1, R.Bottom);
end;
bRight:
begin
APos := FRightmostItem.BoundsRect.Left;
AEdge := R.Left;
R := cxRect(APos, R.Top, APos + 1, R.Bottom);
end;
end;
end;
function GetItemsBounds(const ANonItemsBounds: TRect): TRect;
begin
with ANonItemsBounds do
begin
case ASide of
bTop:
Result := cxRect(Left, FTopmostItem.BoundsRect.Top, Right, Top);
bBottom:
Result := cxRect(Left, Top, Right, FBottommostItem.BoundsRect.Bottom);
bLeft:
Result := cxRect(FLeftmostItem.BoundsRect.Left, Top, Left, Bottom);
else //bRight:
Result := cxRect(Left + 1, Top, FRightmostItem.BoundsRect.Right, Bottom);
end;
end;
end;
function Done(const R: TRect; AEdge: Integer): Boolean;
begin
case ASide of
bTop:
Result := R.Top > AEdge;
bBottom:
Result := R.Top < AEdge;
bLeft:
Result := R.Left > AEdge;
else //bRight:
Result := R.Left < AEdge;
end;
end;
var
AIncX, AIncY, AEdge: Integer;
R: TRect;
begin
AItems.Clear;
if ItemCount = 0 then Exit;
InitParams(AIncX, AIncY, AEdge, R);
repeat
OffsetRect(R, AIncX, AIncY);
if not HasItemsAtRect(R) then
begin
PopulateItemsAtRect(AItems, GetItemsBounds(R));
if AItems.Count > 0 then
Exit;
end;
until Done(R, AEdge);
end;
function TdxAutoLayoutHelper.GetFocusControl(
AItem: TdxAutoLayoutItem): TWinControl;
var
I, X, Y, DX, DY: Integer;
AControlX, AControlY: TControl;
begin
Result := AItem.GetFocusControl;
if (Result = nil) and Owner.SmartFindFocusControl then
begin
AControlX := nil;
DX := MaxInt;
Y := (AItem.BoundsRect.Top + AItem.BoundsRect.Bottom) div 2;
for I := AItem.BoundsRect.Right + 1 to Container.ClientWidth do
begin
AControlX := GetControlAtPos(I, Y);
if AControlX <> nil then
begin
if not (AControlX is TWinControl) then
AControlX := nil
else
DX := AControlX.Left - AItem.BoundsRect.Right;
Break;
end;
end;
if (AControlX <> nil) and (DX < Owner.FocusControlDistanceX) then
begin
Result := TWinControl(AControlX);
Exit;
end;
AControlY := nil;
DY := MaxInt;
X := (AItem.BoundsRect.Right + AItem.BoundsRect.Left) div 2;
for I := AItem.BoundsRect.Bottom + 1 to Container.ClientHeight do
begin
AControlY := GetControlAtPos(X, I);
if AControlY <> nil then
begin
if not (AControlY is TWinControl) then
AControlY := nil
else
DY := AControlY.Top - AItem.BoundsRect.Bottom;
Break;
end;
end;
if (AControlY <> nil) and (DY < Owner.FocusControlDistanceY) then
Result := TWinControl(AControlY);
end;
end;
function TdxAutoLayoutHelper.CanExport(AControl: TControl): Boolean;
begin
Result := (AControl <> Owner.Control) and (AControl <> Container) and
not (csNoDesignVisible in AControl.ControlStyle) and
not (csSubComponent in AControl.ComponentStyle);
end;
function TdxAutoLayoutHelper.FindBottommostItem: TdxAutoLayoutItem;
var
I: Integer;
begin
Result := Items[0];
for I := 1 to ItemCount - 1 do
if Items[I].BoundsRect.Bottom > Result.BoundsRect.Bottom then
Result := Items[I];
end;
function TdxAutoLayoutHelper.FindLeftmostItem: TdxAutoLayoutItem;
var
I: Integer;
begin
Result := Items[0];
for I := 1 to ItemCount - 1 do
if Items[I].BoundsRect.Left < Result.BoundsRect.Left then
Result := Items[I];
end;
function TdxAutoLayoutHelper.FindRightmostItem: TdxAutoLayoutItem;
var
I: Integer;
begin
Result := Items[0];
for I := 1 to ItemCount - 1 do
if Items[I].BoundsRect.Right > Result.BoundsRect.Right then
Result := Items[I];
end;
function TdxAutoLayoutHelper.FindTopmostItem: TdxAutoLayoutItem;
var
I: Integer;
begin
Result := Items[0];
for I := 1 to ItemCount - 1 do
if Items[I].BoundsRect.Top < Result.BoundsRect.Top then
Result := Items[I];
end;
function TdxAutoLayoutHelper.GetControlAtPos(X, Y: Integer): TControl;
var
I: Integer;
begin
Result := nil;
for I := 0 to Container.ControlCount - 1 do
if (Owner.Control <> Container.Controls[I]) and
cxRectPtIn(Container.Controls[I].BoundsRect, X, Y) then
begin
Result := Container.Controls[I];
Break;
end;
end;
function TdxAutoLayoutHelper.GetItemCount: Integer;
begin
Result := Items.Count;
end;
function TdxAutoLayoutHelper.HasItemsAtRect(const R: TRect): Boolean;
var
I: Integer;
begin
Result := False;
for I := 0 to ItemCount - 1 do
if cxRectIntersect(R, Items[I].BoundsRect) then
begin
Result := True;
Break;
end;
end;
procedure TdxAutoLayoutHelper.MakeNewRoot;
begin
FRoot := FRoot.CreateGroup;
FRoot.AlignHorz := ahClient;
FRoot.AlignVert := avClient;
FRoot.Hidden := True;
end;
procedure TdxAutoLayoutHelper.ProcessLabels;
var
I: Integer;
AControl: TWinControl;
AItem: TdxAutoLayoutItem;
begin
for I := ItemCount - 1 downto 0 do
if Items[I].IsLabel then
begin
AControl := GetFocusControl(Items[I]);
if AControl <> nil then
begin
AItem := Items.Find(AControl);
if AItem <> nil then
begin
AItem.SetLabelInfo(Items[I].Control);
Items.Extract(I);
end;
end;
end;
end;
function TdxAutoLayoutHelper.UpdateUtmostItems: TRect;
begin
FTopmostItem := FindTopmostItem;
FBottommostItem := FindBottommostItem;
FLeftmostItem := FindLeftmostItem;
FRightmostItem := FindRightmostItem;
Result := cxRect(FLeftmostItem.BoundsRect.Left, FTopmostItem.BoundsRect.Top,
FRightmostItem.BoundsRect.Right, FBottommostItem.BoundsRect.Bottom);
end;
{ TdxAutoLayout }
constructor TdxAutoLayout.Create(AControl: TdxCustomLayoutControl);
begin
inherited Create;
FControl := AControl;
FConvertPageControls := True;
FSmartFindFocusControl := True;
FFocusControlDistanceX := 48;
FFocusControlDistanceY := 16;
FUseLabeledItems := True;
end;
procedure TdxAutoLayout.DoExecute(AContainer: TWinControl; ARecursive: Boolean = True);
begin
FRecursive := ARecursive;
with TdxAutoLayoutHelper.Create(Self) do
try
Control.BeginUpdate;
try
Execute(AContainer, Control.Items);
CorrectAlign(Control.Items);
finally
Control.EndUpdate;
end;
finally
Free;
end;
end;
procedure TdxAutoLayout.Execute(AContainer: TWinControl; ARecursive: Boolean = True);
begin
if AContainer = nil then
Exit;
AContainer.DisableAlign;
try
DoExecute(AContainer, ARecursive);
finally
AContainer.EnableAlign;
end;
end;
procedure TdxAutoLayout.CorrectAlign(AGroup: TdxLayoutGroup);
procedure DoCorrectAlign(AItem: TdxCustomLayoutItem);
begin
if AItem.AlignHorz = TdxCustomLayoutItemAccess(AItem).GetParentManagedAlignHorz then
AItem.AlignHorz := ahParentManaged;
if AItem.AlignVert = TdxCustomLayoutItemAccess(AItem).GetParentManagedAlignVert then
AItem.AlignVert := avParentManaged;
end;
var
I: Integer;
begin
for I := 0 to AGroup.Count -1 do
begin
if AGroup[I] is TdxLayoutGroup then
CorrectAlign(TdxLayoutGroup(AGroup[I]));
DoCorrectAlign(AGroup[I]);
end;
end;
procedure ImportLayout(ALayoutControl: TdxLayoutControl);
function GetRoot: TWinControl;
begin
Result := ALayoutControl.Owner as TWinControl;
end;
function CanExport(AControl: TControl): Boolean;
begin
Result := (AControl <> ALayoutControl) and
not (csNoDesignVisible in AControl.ControlStyle) and not (csSubComponent in AControl.ComponentStyle);
end;
function AddItems(AControl: TWinControl; AStrings: TStrings;
AInsertionIndex: Integer): Boolean;
var
I: Integer;
begin
with AControl do
begin
Result := CanExport(AControl) and (csAcceptsControls in ControlStyle);
if Result then
begin
AStrings.InsertObject(AInsertionIndex, Name, AControl);
AInsertionIndex := AStrings.Count;
for I := 0 to ControlCount - 1 do
if Controls[I] is TWinControl then
if AddItems(TWinControl(Controls[I]), AStrings, AInsertionIndex) then
Inc(AInsertionIndex);
end;
end;
end;
var
ASaveCursor: TCursor;
begin
if ALayoutControl = nil then Exit;
with TfmImport.Create(nil) do
try
AddItems(GetRoot, cbContainers.Properties.Items, 0);
if cbContainers.Properties.Items.Count <> 0 then
cbContainers.ItemIndex := 0
else
btnImport.Enabled := False;
seDeltaX.Value := 48;
seDeltaY.Value := 16;
if ShowModal = mrOk then
begin
with TdxAutoLayout.Create(ALayoutControl) do
try
ConvertPageControls := cbConvertPageControls.Checked;
SmartFindFocusControl := cbAssociate.Checked;
UseLabeledItems := cbUseLabeledItems.Checked;
FocusControlDistanceX := seDeltaX.Value;
FocusControlDistanceY := seDeltaY.Value;
ASaveCursor := Screen.Cursor;
Screen.Cursor := crHourGlass;
try
Execute(TWinControl(cbContainers.Properties.Items.Objects[cbContainers.ItemIndex]), True);
finally
Screen.Cursor := ASaveCursor;
end;
finally
Free;
end;
ALayoutControl.AutoSize := True
end;
finally
Free;
end;
end;
procedure TfmImport.cbAssociateClick(Sender: TObject);
begin
seDeltaX.Enabled := cbAssociate.Checked;
seDeltaY.Enabled := cbAssociate.Checked;
end;
end.