{********************************************************************} { } { 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 dxLayoutControl; {$I cxVer.inc} interface uses Messages, Windows, SysUtils, Classes, Controls, Graphics, Forms, StdCtrls, ExtCtrls, IniFiles, Contnrs, dxCore, cxClasses, cxGeometry, cxGraphics, cxControls, cxLookAndFeels, cxLibraryConsts, dxLayoutLookAndFeels, dxLayoutCommon, cxPC, dxControlSelection; const htError = -1; htNone = 0; htCustomizeForm = 1; htItem = 10; htGroup = 20; htClientArea = 30; htAvailableItems = 40; htTreeViewItems = 50; dxLayoutItemControlDefaultMinHeight = 20; dxLayoutItemControlDefaultMinWidth = 20; dxLayoutItemMinSize = 5; // DXM_FREEITEM = WM_DX + 25; DXM_PLACECONTROLS = WM_DX + 26; DXM_BUILDSELECTIONLAYER = WM_DX + 27; type //Base TdxCustomLayoutItem = class; TdxCustomLayoutItemClass = class of TdxCustomLayoutItem; TdxLayoutItem = class; TdxLayoutGroup = class; TdxLayoutGroupClass = class of TdxLayoutGroup; TdxCustomLayoutControl = class; //Secondary TdxLayoutAlignmentConstraint = class; TdxCustomLayoutHitTest = class; TdxLayoutGroupHelper = class; TdxLayoutGroupHelperClass = class of TdxLayoutGroupHelper; //Painter TdxCustomLayoutItemPainterClass = class of TdxCustomLayoutItemPainter; TdxCustomLayoutItemPainter = class; TdxLayoutItemPainterClass = class of TdxLayoutItemPainter; TdxLayoutItemPainter = class; TdxLayoutGroupPainterClass = class of TdxLayoutGroupPainter; TdxLayoutGroupPainter = class; TdxLayoutControlPainterClass = class of TdxLayoutControlPainter; TdxLayoutControlPainter = class; TdxLayoutItemControlPainterClass = class of TdxLayoutItemControlPainter; TdxLayoutItemControlPainter = class; TdxCustomLayoutItemCaptionPainterClass = class of TdxCustomLayoutItemCaptionPainter; TdxCustomLayoutItemCaptionPainter = class; // ViewInfo TdxCustomLayoutElementViewInfo = class; TdxCustomLayoutItemElementViewInfo = class; TdxCustomLayoutItemCaptionViewInfo = class; TdxCustomLayoutItemViewInfoClass = class of TdxCustomLayoutItemViewInfo; TdxCustomLayoutItemViewInfo = class; TdxLayoutItemControlViewInfo = class; TdxLayoutItemViewInfoClass = class of TdxLayoutItemViewInfo; TdxLayoutItemViewInfo = class; TdxLayoutGroupViewInfoClass = class of TdxLayoutGroupViewInfo; TdxLayoutGroupViewInfo = class; TdxLayoutControlViewInfoClass = class of TdxLayoutControlViewInfo; TdxLayoutControlViewInfo = class; TdxLayoutGroupViewInfoSpecific = class; TdxLayoutGroupViewInfoSpecificClass = class of TdxLayoutGroupViewInfoSpecific; // custom item TdxLayoutAlignHorz = (ahLeft, ahCenter, ahRight, ahClient, ahParentManaged); TdxLayoutAlignVert = (avTop, avCenter, avBottom, avClient, avParentManaged); TdxLayoutAutoAlign = (aaHorizontal, aaVertical); TdxLayoutAutoAligns = set of TdxLayoutAutoAlign; TdxLayoutDirection = (ldHorizontal, ldVertical, ldTabbed); TdxLayoutAreaPart = (apNone, apLeft, apTop, apRight, apBottom, apCenter, apBeforeContent, apAfterContent); TdxCustomLayoutItemOptions = class(TPersistent) private FItem: TdxCustomLayoutItem; protected procedure Changed; virtual; property Item: TdxCustomLayoutItem read FItem; public constructor Create(AItem: TdxCustomLayoutItem); virtual; end; TdxCustomLayoutItemCaptionOptions = class(TdxCustomLayoutItemOptions) private FAlignHorz: TAlignment; FShowAccelChar: Boolean; procedure SetAlignHorz(Value: TAlignment); procedure SetShowAccelChar(Value: Boolean); public constructor Create(AItem: TdxCustomLayoutItem); override; published property AlignHorz: TAlignment read FAlignHorz write SetAlignHorz default taLeftJustify; property ShowAccelChar: Boolean read FShowAccelChar write SetShowAccelChar default True; end; TdxCustomLayoutItemCaptionOptionsClass = class of TdxCustomLayoutItemCaptionOptions; TdxLayoutOffsets = class(TdxCustomLayoutItemOptions) private FBottom: Integer; FLeft: Integer; FRight: Integer; FTop: Integer; function GetValue(Index: Integer): Integer; procedure SetValue(Index: Integer; Value: Integer); published property Bottom: Integer index 1 read GetValue write SetValue default 0; property Left: Integer index 2 read GetValue write SetValue default 0; property Right: Integer index 3 read GetValue write SetValue default 0; property Top: Integer index 4 read GetValue write SetValue default 0; end; IdxLayoutSelectableItem = interface ['{2887168D-78EB-44A0-A440-E284B01BE407}'] function CanDelete: Boolean; function IsChild(AOwner: TdxCustomLayoutControl): Boolean; procedure SelectComponent(AShift: TShiftState = []); procedure SelectParent; procedure SelectionChanged; function IsVisible: Boolean; end; TdxLayoutItemChangeType = (ictHard, ictMedium, ictLight); TdxCustomLayoutItem = class(TComponent, IdxLayoutLookAndFeelUser, IdxLayoutSelectableItem) private FAlignHorz: TdxLayoutAlignHorz; FAlignmentConstraint: TdxLayoutAlignmentConstraint; FAlignVert: TdxLayoutAlignVert; FAllowRemove: Boolean; FCachedTextHeight: Integer; FCaption: string; FCaptionOptions: TdxCustomLayoutItemCaptionOptions; FContainer: TdxCustomLayoutControl; FEnabled: Boolean; FLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; FOffsets: TdxLayoutOffsets; FParent: TdxLayoutGroup; FShowCaption: Boolean; FViewInfo: TdxCustomLayoutItemViewInfo; FVisible: Boolean; FOnCaptionClick: TNotifyEvent; function GetRealAlignHorz: TdxLayoutAlignHorz; function GetRealAlignVert: TdxLayoutAlignVert; function GetActuallyVisible: Boolean; function GetAutoAligns: TdxLayoutAutoAligns; function GetAlignHorz: TdxLayoutAlignHorz; function GetAlignVert: TdxLayoutAlignVert; function GetCaptionForCustomizeForm: string; function GetHasMouse: Boolean; function GetIndex: Integer; function GetIsAvailable: Boolean; function GetIsDesigning: Boolean; function GetIsDestroying: Boolean; function GetIsDragged: Boolean; function GetIsLoading: Boolean; function GetIsSelected: Boolean; function GetIsRoot: Boolean; function GetVisibleIndex: Integer; procedure SetAlignHorz(Value: TdxLayoutAlignHorz); procedure SetAlignmentConstraint(Value: TdxLayoutAlignmentConstraint); procedure SetAlignVert(Value: TdxLayoutAlignVert); procedure SetAutoAligns(Value: TdxLayoutAutoAligns); procedure SetCaption(const Value: string); procedure SetContainer(Value: TdxCustomLayoutControl); procedure SetEnabled(Value: Boolean); procedure SetLayoutLookAndFeel(Value: TdxCustomLayoutLookAndFeel); procedure SetHasMouse(Value: Boolean); procedure SetIndex(Value: Integer); procedure SetParent(Value: TdxLayoutGroup); procedure SetShowCaption(Value: Boolean); procedure SetVisible(Value: Boolean); procedure SetVisibleIndex(Value: Integer); function IsAlignHorzStored: Boolean; function IsAlignVertStored: Boolean; protected procedure SetName(const Value: TComponentName); override; procedure SetParentComponent(Value: TComponent); override; procedure LayoutLookAndFeelChanged; virtual; procedure LayoutLookAndFeelChanging; virtual; // IdxLayoutLookAndFeelUser procedure IdxLayoutLookAndFeelUser.BeginLookAndFeelDestroying = BeginLayoutLookAndFeelUserDestroying; procedure IdxLayoutLookAndFeelUser.EndLookAndFeelDestroying = EndLayoutLookAndFeelUserDestroying; procedure IdxLayoutLookAndFeelUser.LookAndFeelChanged = LayoutLookAndFeelUserChanged; procedure IdxLayoutLookAndFeelUser.LookAndFeelDestroyed = LayoutLookAndFeelUserDestroyed; procedure BeginLayoutLookAndFeelUserDestroying; stdcall; procedure EndLayoutLookAndFeelUserDestroying; stdcall; procedure LayoutLookAndFeelUserChanged; stdcall; procedure LayoutLookAndFeelUserDestroyed; stdcall; function CanFocusOnClick(X, Y: Integer): Boolean; virtual; function CanProcessAccel(out AItem: TdxCustomLayoutItem): Boolean; virtual; abstract; function CanRemove: Boolean; virtual; procedure ContainerChanged; virtual; procedure DoCaptionDown; dynamic; procedure DoCaptionClick; dynamic; procedure DoPack; virtual; function DoProcessAccel: Boolean; dynamic; procedure EnabledChanged; virtual; function GetParentManagedAlignHorz: TdxLayoutAlignHorz; virtual; function GetParentManagedAlignVert: TdxLayoutAlignVert; virtual; function GetBaseName: string; virtual; function GetCursor(X, Y: Integer): TCursor; virtual; function GetEnabledForWork: Boolean; virtual; function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; virtual; function GetParentHelperClass: TdxLayoutGroupHelperClass; function GetShowCaption: Boolean; virtual; // #DG !!! function GetViewInfoClass: TdxCustomLayoutItemViewInfoClass; virtual; abstract; function GetVisible: Boolean; function HasControl: Boolean; virtual; procedure BeforeCalculateViewInfo; virtual; procedure AfterCalculateViewInfo; virtual; function IsParentGroup(AParentGroup: TdxLayoutGroup): Boolean; function IsChildItem(AChildItem: TdxCustomLayoutItem): Boolean; function HasCaption: Boolean; virtual; // #DG !!! procedure Init; virtual; procedure MouseEnter; dynamic; procedure MouseLeave; dynamic; procedure CustomizationMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic; procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic; procedure ProcessAccel; dynamic; function ProcessDialogChar(ACharCode: Word): Boolean; virtual; procedure RestoreItemControlSize; virtual; abstract; function GetCaptionOptionsClass: TdxCustomLayoutItemCaptionOptionsClass; virtual; procedure ResetCachedTextHeight; //IdxLayoutSelectableItem function CanDelete: Boolean; virtual; function IsChild(AOwner: TdxCustomLayoutControl): Boolean; virtual; procedure SelectComponent(AShift: TShiftState = []); virtual; procedure SelectParent; virtual; procedure SelectionChanged; virtual; function IdxLayoutSelectableItem.IsVisible = IsSelectableItemVisible; function IsSelectableItemVisible: Boolean; virtual; property CachedTextHeight: Integer read FCachedTextHeight write FCachedTextHeight; property EnabledForWork: Boolean read GetEnabledForWork; property HasMouse: Boolean read GetHasMouse write SetHasMouse; property IsAvailable: Boolean read GetIsAvailable; property IsDesigning: Boolean read GetIsDesigning; property IsDestroying: Boolean read GetIsDestroying; property IsDragged: Boolean read GetIsDragged; property IsLoading: Boolean read GetIsLoading; property IsSelected: Boolean read GetIsSelected; public constructor Create(AOwner: TComponent); override; procedure BeforeDestruction; override; destructor Destroy; override; function GetParentComponent: TComponent; override; function HasParent: Boolean; override; procedure Changed(AType: TdxLayoutItemChangeType = ictHard); function CanMoveTo(AParent: TdxCustomLayoutItem): Boolean; virtual; procedure MakeVisible; function Move(AParent: TdxLayoutGroup; AIndex: Integer; APack: Boolean = False): Boolean; function MoveTo(AParent: TdxLayoutGroup; AVisibleIndex: Integer; APack: Boolean = False): Boolean; procedure Pack; function PutIntoHiddenGroup(ALayoutDirection: TdxLayoutDirection): TdxLayoutGroup; property ActuallyVisible: Boolean read GetActuallyVisible; property CaptionForCustomizeForm: string read GetCaptionForCustomizeForm; property Container: TdxCustomLayoutControl read FContainer write SetContainer; property Index: Integer read GetIndex write SetIndex; property IsRoot: Boolean read GetIsRoot; property Parent: TdxLayoutGroup read FParent write SetParent; property ViewInfo: TdxCustomLayoutItemViewInfo read FViewInfo; property VisibleIndex: Integer read GetVisibleIndex write SetVisibleIndex; published property AutoAligns: TdxLayoutAutoAligns read GetAutoAligns write SetAutoAligns stored False; // obsolette property AlignHorz: TdxLayoutAlignHorz read GetAlignHorz write SetAlignHorz stored IsAlignHorzStored; property AlignVert: TdxLayoutAlignVert read GetAlignVert write SetAlignVert stored IsAlignVertStored; property AlignmentConstraint: TdxLayoutAlignmentConstraint read FAlignmentConstraint write SetAlignmentConstraint; property AllowRemove: Boolean read FAllowRemove write FAllowRemove default True; property Caption: string read FCaption write SetCaption; property CaptionOptions: TdxCustomLayoutItemCaptionOptions read FCaptionOptions write FCaptionOptions; property Enabled: Boolean read FEnabled write SetEnabled default True; property LookAndFeel: TdxCustomLayoutLookAndFeel read FLayoutLookAndFeel write SetLayoutLookAndFeel stored False; // osolette property LayoutLookAndFeel: TdxCustomLayoutLookAndFeel read FLayoutLookAndFeel write SetLayoutLookAndFeel; property Offsets: TdxLayoutOffsets read FOffsets write FOffsets; property ShowCaption: Boolean read GetShowCaption write SetShowCaption default True; property Visible: Boolean read FVisible write SetVisible default True; property OnCaptionClick: TNotifyEvent read FOnCaptionClick write FOnCaptionClick; end; // item TdxCustomLayoutControlAdapter = class(TPersistent) private FItem: TdxLayoutItem; function GetControl: TControl; function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; protected function AllowCheckSize: Boolean; virtual; procedure HideControlBorder; virtual; procedure Init; virtual; function ShowBorder: Boolean; virtual; function ShowItemCaption: Boolean; virtual; function UseItemColor: Boolean; virtual; property Control: TControl read GetControl; property Item: TdxLayoutItem read FItem; property LayoutLookAndFeel: TdxCustomLayoutLookAndFeel read GetLayoutLookAndFeel; public constructor Create(AItem: TdxLayoutItem); virtual; procedure LayoutLookAndFeelChanged; virtual; class procedure Register(AControlClass: TControlClass); class procedure Unregister(AControlClass: TControlClass); end; TdxCustomLayoutControlAdapterClass = class of TdxCustomLayoutControlAdapter; TdxCaptionLayout = (clLeft, clTop, clRight, clBottom); TdxAlignmentVert = (tavTop, tavCenter, tavBottom); TdxLayoutItemCaptionOptions = class(TdxCustomLayoutItemCaptionOptions) private FAlignVert: TdxAlignmentVert; FLayout: TdxCaptionLayout; FWidth: Integer; procedure SetAlignVert(Value: TdxAlignmentVert); procedure SetLayout(Value: TdxCaptionLayout); procedure SetWidth(Value: Integer); published constructor Create(AItem: TdxCustomLayoutItem); override; property AlignVert: TdxAlignmentVert read FAlignVert write SetAlignVert default tavCenter; property Layout: TdxCaptionLayout read FLayout write SetLayout default clLeft; property Width: Integer read FWidth write SetWidth default 0; end; TdxLayoutItemControlOptions = class(TdxCustomLayoutItemOptions) private FAutoAlignment: Boolean; FAutoColor: Boolean; FFixedSize: Boolean; FMinHeight: Integer; FMinWidth: Integer; FOpaque: Boolean; FShowBorder: Boolean; procedure SetAutoAlignment(Value: Boolean); procedure SetAutoColor(Value: Boolean); procedure SetFixedSize(Value: Boolean); procedure SetMinHeight(Value: Integer); procedure SetMinWidth(Value: Integer); procedure SetOpaque(Value: Boolean); procedure SetShowBorder(Value: Boolean); public constructor Create(AItem: TdxCustomLayoutItem); override; published property AutoAlignment: Boolean read FAutoAlignment write SetAutoAlignment default True; property AutoColor: Boolean read FAutoColor write SetAutoColor default False; property FixedSize: Boolean read FFixedSize write SetFixedSize default False; property MinHeight: Integer read FMinHeight write SetMinHeight default dxLayoutItemControlDefaultMinHeight; property MinWidth: Integer read FMinWidth write SetMinWidth default dxLayoutItemControlDefaultMinWidth; property Opaque: Boolean read FOpaque write SetOpaque default False; property ShowBorder: Boolean read FShowBorder write SetShowBorder default True; end; TdxLayoutItemControlOptionsClass = class of TdxLayoutItemControlOptions; TdxLayoutItem = class(TdxCustomLayoutItem) private FControl: TControl; FControlLocked: Boolean; FControlAdapter: TdxCustomLayoutControlAdapter; FControlOptions: TdxLayoutItemControlOptions; FControlSizeBeforeDestruction: TPoint; FOriginalControlSize: TPoint; FDesignSelectorControls: TcxComponentList; FDefaultControlWndProc: TWndMethod; function GetCaptionOptions: TdxLayoutItemCaptionOptions; function GetViewInfo: TdxLayoutItemViewInfo; procedure SetCaptionOptions(Value: TdxLayoutItemCaptionOptions); procedure SetControl(Value: TControl); function CanFocusControlOnCaptionClick: Boolean; procedure CreateControlAdapter; //procedure PostFree; protected function CanDelete: Boolean; override; function CanFocusOnClick(X, Y: Integer): Boolean; override; function CanProcessAccel(out AItem: TdxCustomLayoutItem): Boolean; override; procedure ContainerChanged; override; procedure DoCaptionDown; override; procedure EnabledChanged; override; function GetParentManagedAlignVert: TdxLayoutAlignVert; override; function GetBaseName: string; override; function GetViewInfoClass: TdxCustomLayoutItemViewInfoClass; override; procedure Init; override; procedure Loaded; override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure ProcessAccel; override; procedure RestoreItemControlSize; override; procedure CustomizationMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure AfterCalculateViewInfo; override; procedure LayoutLookAndFeelChanged; override; function GetCaptionOptionsClass: TdxCustomLayoutItemCaptionOptionsClass; override; function GetControlOptionsClass: TdxLayoutItemControlOptionsClass; virtual; function CanFocusControl: Boolean; virtual; function CanTabStopControl: Boolean; procedure ControlWndProc(var Message: TMessage); virtual; function HasControl: Boolean; override; function HasWinControl: Boolean; procedure SaveControlSizeBeforeDestruction; procedure SaveOriginalControlSize; procedure SetControlEnablement; procedure SetControlFocus; procedure SetControlVisibility; procedure UpdateDesignSelectors; property ControlAdapter: TdxCustomLayoutControlAdapter read FControlAdapter; property ControlSizeBeforeDestruction: TPoint read FControlSizeBeforeDestruction; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; property OriginalControlSize: TPoint read FOriginalControlSize write FOriginalControlSize; property ViewInfo: TdxLayoutItemViewInfo read GetViewInfo; published property CaptionOptions: TdxLayoutItemCaptionOptions read GetCaptionOptions write SetCaptionOptions; property Control: TControl read FControl write SetControl; property ControlOptions: TdxLayoutItemControlOptions read FControlOptions write FControlOptions; end; TdxLayoutItemClass = class of TdxLayoutItem; // group TdxLayoutGroupHelper = class public class function GetChildItemsAlignHorz: TdxLayoutAlignHorz; virtual; class function GetChildItemsAlignVert: TdxLayoutAlignVert; virtual; class function GetOrthogonalDirection: TdxLayoutDirection; virtual; abstract; class function GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; virtual; abstract; end; TdxLayoutHorizontalGroupHelper = class(TdxLayoutGroupHelper) public class function GetChildItemsAlignHorz: TdxLayoutAlignHorz; override; class function GetChildItemsAlignVert: TdxLayoutAlignVert; override; class function GetOrthogonalDirection: TdxLayoutDirection; override; class function GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; override; end; TdxLayoutVerticalGroupHelper = class(TdxLayoutGroupHelper) public class function GetChildItemsAlignHorz: TdxLayoutAlignHorz; override; class function GetChildItemsAlignVert: TdxLayoutAlignVert; override; class function GetOrthogonalDirection: TdxLayoutDirection; override; class function GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; override; end; TdxLayoutTabbedGroupHelper = class(TdxLayoutHorizontalGroupHelper) public class function GetChildItemsAlignHorz: TdxLayoutAlignHorz; override; class function GetChildItemsAlignVert: TdxLayoutAlignVert; override; class function GetOrthogonalDirection: TdxLayoutDirection; override; class function GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; override; end; TdxLayoutGroup = class(TdxCustomLayoutItem) private FItemIndex: Integer; FHidden: Boolean; FIsUserDefined: Boolean; FItems: TcxComponentList; FVisibleItems: TcxComponentList; FLayoutDirection: TdxLayoutDirection; FLocked: Boolean; FLayoutLookAndFeelException: Boolean; FShowBorder: Boolean; FUseIndent: Boolean; function GetCount: Integer; function GetItem(Index: Integer): TdxCustomLayoutItem; function GetShowBorder: Boolean; function GetViewInfo: TdxLayoutGroupViewInfo; function GetVisibleCount: Integer; function GetVisibleItem(Index: Integer): TdxCustomLayoutItem; procedure SetItemIndex(Value: Integer); procedure SetHidden(Value: Boolean); procedure SetLayoutDirection(Value: TdxLayoutDirection); procedure SetLocked(Value: Boolean); procedure SetLayoutLookAndFeelException(Value: Boolean); procedure SetShowBorder(Value: Boolean); procedure SetUseIndent(Value: Boolean); procedure AddItem(AItem: TdxCustomLayoutItem); procedure ExtractItem(AItem: TdxCustomLayoutItem); procedure ItemListChanged(Sender: TObject; AComponent: TComponent; AAction: TcxComponentCollectionNotification); function IsChildActuallyVisible(AChild: TdxCustomLayoutItem): Boolean; function GetChildLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; protected procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; procedure Loaded; override; procedure SetChildOrder(Child: TComponent; Order: Integer); override; procedure SetParentComponent(Value: TComponent); override; // TdxCustomLayoutItem function CanDelete: Boolean; override; function CanProcessAccel(out AItem: TdxCustomLayoutItem): Boolean; override; function CanRemove: Boolean; override; procedure ContainerChanged; override; procedure DoPack; override; procedure EnabledChanged; override; function GetBaseName: string; override; function GetShowCaption: Boolean; override; function GetViewInfoClass: TdxCustomLayoutItemViewInfoClass; override; function ProcessDialogChar(ACharCode: Word): Boolean; override; procedure RestoreItemControlSize; override; procedure LayoutLookAndFeelChanged; override; procedure LayoutLookAndFeelChanging; override; procedure BeforeCalculateViewInfo; override; procedure AfterCalculateViewInfo; override; function CanDestroy: Boolean; virtual; procedure BuildVisibleItemsList; function GetHelperClass: TdxLayoutGroupHelperClass; function AllowDrawChild(AChild: TdxCustomLayoutItem): Boolean; virtual; procedure ChangeItemIndex(AItem: TdxCustomLayoutItem; Value: Integer); procedure ChangeItemVisibleIndex(AItem: TdxCustomLayoutItem; Value: Integer); function GetItemIndex(AItemVisibleIndex: Integer): Integer; function IndexOf(AItem: TdxCustomLayoutItem): Integer; function VisibleIndexOf(AItem: TdxCustomLayoutItem): Integer; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function CreateGroup(AGroupClass: TdxLayoutGroupClass = nil): TdxLayoutGroup; function CreateItem(AItemClass: TdxCustomLayoutItemClass = nil): TdxCustomLayoutItem; function CreateItemForControl(AControl: TControl): TdxLayoutItem; function CanMoveTo(AParent: TdxCustomLayoutItem): Boolean; override; procedure MoveChildrenToParent; function PutChildrenIntoHiddenGroup: TdxLayoutGroup; property Count: Integer read GetCount; property Items[Index: Integer]: TdxCustomLayoutItem read GetItem; default; property IsUserDefined: Boolean read FIsUserDefined; property ViewInfo: TdxLayoutGroupViewInfo read GetViewInfo; property VisibleCount: Integer read GetVisibleCount; property VisibleItems[Index: Integer]: TdxCustomLayoutItem read GetVisibleItem; published property ItemIndex: Integer read FItemIndex write SetItemIndex default 0; property Hidden: Boolean read FHidden write SetHidden default False; property LayoutDirection: TdxLayoutDirection read FLayoutDirection write SetLayoutDirection default ldVertical; property Locked: Boolean read FLocked write SetLocked default False; property LookAndFeelException: Boolean read FLayoutLookAndFeelException write SetLayoutLookAndFeelException stored False; // obsolette property LayoutLookAndFeelException: Boolean read FLayoutLookAndFeelException write SetLayoutLookAndFeelException default False; property ShowBorder: Boolean read GetShowBorder write SetShowBorder default True; property UseIndent: Boolean read FUseIndent write SetUseIndent default True; end; // alignment constraint TdxLayoutAlignmentConstraintKind = (ackLeft, ackTop, ackRight, ackBottom); TdxLayoutAlignmentConstraint = class(TComponent) private FControl: TdxCustomLayoutControl; FItems: TList; FKind: TdxLayoutAlignmentConstraintKind; function GetCount: Integer; function GetItem(Index: Integer): TdxCustomLayoutItem; procedure SetKind(Value: TdxLayoutAlignmentConstraintKind); procedure CreateItems; procedure DestroyItems; procedure InternalAddItem(AItem: TdxCustomLayoutItem); procedure InternalRemoveItem(AItem: TdxCustomLayoutItem); protected procedure SetParentComponent(Value: TComponent); override; procedure BeginUpdate; function CanAddItem(AItem: TdxCustomLayoutItem): Boolean; virtual; procedure Changed; virtual; procedure EndUpdate; property Control: TdxCustomLayoutControl read FControl; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function GetParentComponent: TComponent; override; function HasParent: Boolean; override; procedure AddItem(AItem: TdxCustomLayoutItem); procedure RemoveItem(AItem: TdxCustomLayoutItem); property Count: Integer read GetCount; property Items[Index: Integer]: TdxCustomLayoutItem read GetItem; published property Kind: TdxLayoutAlignmentConstraintKind read FKind write SetKind default ackLeft; end; TdxLayoutAlignmentConstraintClass = class of TdxLayoutAlignmentConstraint; { DragAndDrop } TdxLayoutDragSource = (dsControl, dsCustomizeFormAvailableItems, dsCustomizeFormTreeViewItems); { TdxLayoutControlDragAndDropObject } TdxLayoutControlDragAndDropObject = class(TcxDragAndDropObject) private FAreaPart: TdxLayoutAreaPart; FDragImage: TcxDragImage; FDragImageOffset: TPoint; FDestinationControl: TdxCustomLayoutControl; FDestinationGroup: TdxLayoutGroup; FDestinationImage: TcxDragDestinationImage; FDestinationItem: TdxCustomLayoutItem; FNeedRepaintDestinationImage: Boolean; FSource: TdxLayoutDragSource; FSourceItem: TdxCustomLayoutItem; FSourceItemBounds: TRect; FStartDragPoint: TPoint; function CanDrop: Boolean; function CanRemove: Boolean; function GetSourceControl: TdxCustomLayoutControl; 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 destructor Destroy; override; 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; { TdxLayoutControlPersistent } TdxLayoutControlPersistent = class(TPersistent) private FControl: TdxCustomLayoutControl; protected procedure Changed; virtual; function GetOwner: TPersistent; override; public constructor Create(AControl: TdxCustomLayoutControl); virtual; property Control: TdxCustomLayoutControl read FControl; 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; { controls } TdxStoringOptions = class(TPersistent) private FIniFileName: string; FRegistryPath: string; FStoreToIniFile: Boolean; FStoreToRegistry: Boolean; protected function CanStoreToIniFile: Boolean; function CanStoreToRegistry: Boolean; function CanRestoreFromIniFile: Boolean; function CanRestoreFromRegistry: Boolean; public procedure Assign(Source: TPersistent); override; published property IniFileName: string read FIniFileName write FIniFileName; property RegistryPath: string read FRegistryPath write FRegistryPath; property StoreToIniFile: Boolean read FStoreToIniFile write FStoreToIniFile default False; property StoreToRegistry: Boolean read FStoreToRegistry write FStoreToRegistry default False; end; TdxLayoutAutoContentSize = (acsWidth, acsHeight); TdxLayoutAvailableItemsViewKind = (oivkList, oivkTree); TdxLayoutCustomizeFormUpdateType = (cfutCaption, cfutContent, cfutSelection); TdxLayoutCustomizeFormUpdateTypes = set of TdxLayoutCustomizeFormUpdateType; TdxLayoutAutoContentSizes = set of TdxLayoutAutoContentSize; TdxCustomLayoutControl = class(TcxControl, IdxLayoutLookAndFeelUser, IdxLayoutComponent, IdxSkinSupport, IdxLayoutDesignerHelper, IdxLayoutSelectionChanged) private FAlignmentConstraints: TList; FAutoControlAlignment: Boolean; FAutoControlTabOrders: Boolean; FBoldFont: TFont; FFocusControlOnItemCaptionClick: Boolean; FItemWithMouse: TdxCustomLayoutItem; FLeftPos: Integer; FOptionsStoring: TdxStoringOptions; FRightButtonPressed: Boolean; FShowHiddenGroupsBounds: Boolean; FTopPos: Integer; FUpdateLockCount: Integer; // Objects FRootGroup: TdxLayoutGroup; FLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; FPainter: TdxLayoutControlPainter; FViewInfo: TdxLayoutControlViewInfo; // Items FAbsoluteItems: TcxComponentList; FAvailableItems: TcxComponentList; // Customization FShowDesignSelectors: Boolean; FHighlightRoot: Boolean; FCustomization: Boolean; FCustomizationControls: TcxComponentList; FCustomizeAvailableItemsViewKind: TdxLayoutAvailableItemsViewKind; FCustomizeForm: TCustomForm; FCustomizeFormBounds: TRect; FCustomizeFormClass: TFormClass; FCustomizeFormTabbedView: Boolean; FCustomizeFormUpdateLockCount: Integer; // Internal Flags FIsPlaceControlsNeeded: Boolean; FIsPlacingControls: Boolean; // Storing FStoredStream: TMemoryStream; FOnCustomization: TNotifyEvent; // Get/Set Properties function GetAbsoluteItem(Index: Integer): TdxCustomLayoutItem; function GetAbsoluteItemCount: Integer; function GetAlignmentConstraint(Index: Integer): TdxLayoutAlignmentConstraint; function GetAlignmentConstraintCount: Integer; function GetAllowDrop: Boolean; function GetAvailableItem(Index: Integer): TdxCustomLayoutItem; function GetAvailableItemCount: Integer; function GetAutoContentSizes: TdxLayoutAutoContentSizes; function GetContentBounds: TRect; function GetLayoutDirection: TdxLayoutDirection; function GetOccupiedClientWidth: Integer; function GetOccupiedClientHeight: Integer; function GetSelectedControlCount: Integer; procedure SetAutoContentSizes(Value: TdxLayoutAutoContentSizes); procedure SetAutoControlAlignment(Value: Boolean); procedure SetAutoControlTabOrders(Value: Boolean); procedure SetCustomization(Value: Boolean); procedure SetCustomizeAvailableItemsViewKind(Value: TdxLayoutAvailableItemsViewKind); procedure SetCustomizeFormTabbedView(Value: Boolean); procedure SetShowDesignSelectors(Value: Boolean); procedure SetHighlightRoot(Value: Boolean); procedure SetIsPlaceControlsNeeded(Value: Boolean); procedure SetRootGroup(Value: TdxLayoutGroup); procedure SetItemWithMouse(Value: TdxCustomLayoutItem); procedure SetLeftPos(Value: Integer); procedure SetLayoutDirection(Value: TdxLayoutDirection); procedure SetLayoutLookAndFeel(Value: TdxCustomLayoutLookAndFeel); procedure SetShowHiddenGroupsBounds(Value: Boolean); procedure SetTopPos(Value: Integer); // Storing procedure SetOptionsStoring(Value: TdxStoringOptions); function GetIniFileName: string; function GetRegistryPath: string; function GetStoreInIniFile: Boolean; function GetStoreInRegistry: Boolean; procedure SetIniFileName(const Value: string); procedure SetRegistryPath(const Value: string); procedure SetStoreInIniFile(const Value: Boolean); procedure SetStoreInRegistry(const Value: Boolean); procedure CreateHandlers; procedure DestroyHandlers; // Constraints procedure CreateConstraints; procedure DestroyConstraints; procedure AddAlignmentConstraint(AConstraint: TdxLayoutAlignmentConstraint); procedure RemoveAlignmentConstraint(AConstraint: TdxLayoutAlignmentConstraint); // Items procedure AddAbsoluteItem(AItem: TdxCustomLayoutItem); procedure ExtractAbsoluteItem(AItem: TdxCustomLayoutItem); procedure AddAvailableItem(AItem: TdxCustomLayoutItem); procedure ExtractAvailableItem(AItem: TdxCustomLayoutItem); procedure AvailableItemListChanged(Sender: TObject; AComponent: TComponent; AAction: TcxComponentCollectionNotification); // Selection procedure UpdateCustomizationControls; // Other procedure InitializeSubControlsCxLookAndFeel; procedure PlaceControls(AItemViewInfo: TdxCustomLayoutItemViewInfo); procedure RefreshBoldFont; procedure WMNCDestroy(var Message: TWMNCDestroy); message WM_NCDESTROY; {$IFNDEF DELPHI7} procedure WMPrintClient(var Message: TWMPrintClient); message WM_PRINTCLIENT; {$ENDIF} procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE; procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; //procedure CMFreeItem(var Message: TMessage); message CM_FREEITEM; procedure DXMPlaceControls(var Message: TMessage); message DXM_PLACECONTROLS; procedure DXMBuildSelectionLayer(var Message: TMessage); message DXM_BUILDSELECTIONLAYER; protected FSelectionHelper: IdxLayoutSelectionHelper; function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override; procedure AlignControls(AControl: TControl; var Rect: TRect); override; function AllowAutoDragAndDropAtDesignTime(X, Y: Integer; Shift: TShiftState): Boolean; override; function AllowDragAndDropWithoutFocus: Boolean; override; procedure BoundsChanged; override; function CanDrag(X, Y: Integer): Boolean; override; function CanFocusOnClick(X, Y: Integer): Boolean; override; procedure CreateParams(var Params: TCreateParams); override; procedure DblClick; override; procedure FontChanged; override; {$IFNDEF DELPHI12} procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; {$ENDIF} function GetCursor(X, Y: Integer): TCursor; override; function HasBackground: Boolean; override; function IsInternalControl(AControl: TControl): Boolean; override; procedure Loaded; override; procedure Paint; override; procedure SetName(const Value: TComponentName); override; {$IFDEF DELPHI7} procedure SetParentBackground(Value: Boolean); override; {$ENDIF} procedure WriteState(Writer: TWriter); override; procedure WndProc(var Message: TMessage); override; function GetDesignHitTest(X, Y: Integer; Shift: TShiftState): Boolean; override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseLeave(AControl: TControl); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure InitScrollBarsParameters; override; function NeedsToBringInternalControlsToFront: Boolean; override; procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); override; function CanDragAndDrop: Boolean; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; override; function StartDragAndDrop(const P: TPoint): Boolean; override; function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; function GetCxLookAndFeel: TcxLookAndFeel; // IdxLayoutLookAndFeelUser procedure IdxLayoutLookAndFeelUser.BeginLookAndFeelDestroying = BeginLayoutLookAndFeelUserDestroying; procedure IdxLayoutLookAndFeelUser.EndLookAndFeelDestroying = EndLayoutLookAndFeelUserDestroying; procedure IdxLayoutLookAndFeelUser.LookAndFeelChanged = LayoutLookAndFeelUserChanged; procedure IdxLayoutLookAndFeelUser.LookAndFeelDestroyed = LayoutLookAndFeelUserDestroyed; procedure BeginLayoutLookAndFeelUserDestroying; stdcall; procedure EndLayoutLookAndFeelUserDestroying; stdcall; procedure LayoutLookAndFeelUserChanged; stdcall; procedure LayoutLookAndFeelUserDestroyed; stdcall; // IdxLayoutComponent procedure SelectionChanged; stdcall; function GetPainterClass: TdxLayoutControlPainterClass; virtual; function GetViewInfoClass: TdxLayoutControlViewInfoClass; virtual; procedure AssignItemWithMouse(X, Y: Integer); function CalculateCustomizeFormBounds(const AFormBounds: TRect): TRect; function CanMultiSelect: Boolean; virtual; function CanShowSelection: Boolean; virtual; procedure CheckLeftPos(var Value: Integer); procedure CheckPositions; procedure CheckTopPos(var Value: Integer); procedure CustomizeFormBeginUpdate; procedure CustomizeFormCancelUpdate; procedure CustomizeFormEndUpdate; procedure CustomizeFormUpdate(AUpdateTypes: TdxLayoutCustomizeFormUpdateTypes); procedure DoCustomization; dynamic; procedure DragAndDropBegan; dynamic; function GetAlignmentConstraintClass: TdxLayoutAlignmentConstraintClass; dynamic; function GetDefaultGroupClass: TdxLayoutGroupClass; virtual; function GetDefaultItemClass: TdxLayoutItemClass; virtual; function GetDesignSelectorRect: TRect; function IsCustomization: Boolean; function IsToolSelected: Boolean; function IsUpdateLocked: Boolean; procedure LayoutChanged(ANeedPack: Boolean = True); procedure CreateRootGroup; procedure PostBuildSelectionLayer; virtual; //procedure PostFree(AObject: TObject); procedure ScrollContent(APrevPos, ACurPos: Integer; AHorzScrolling: Boolean); procedure LoadFromCustomIniFile(AIniFile: TCustomIniFile; const ARootSection: string); virtual; procedure SaveToCustomIniFile(AIniFile: TCustomIniFile; const ARootSection: string); virtual; // IdxLayoutDesignerHelper function CanDeleteComponent(AComponent: TComponent): Boolean; procedure ClearSelection; procedure GetSelection(AList: TList); function IsComponentSelected(AComponent: TPersistent): Boolean; procedure SelectComponent(AComponent: TPersistent; AShift: TShiftState = []); procedure SetSelection(AList: TList); function UniqueName(const BaseName: string): string; //IdxLayoutSelectionChanged procedure IdxLayoutSelectionChanged.SelectionChanged = LayoutSelectionChanged; procedure LayoutSelectionChanged(ASelection: TList; AAction: TdxLayoutSelectionAction); property AllowDrop: Boolean read GetAllowDrop; property BoldFont: TFont read FBoldFont; property IsPlaceControlsNeeded: Boolean read FIsPlaceControlsNeeded write SetIsPlaceControlsNeeded; property ItemWithMouse: TdxCustomLayoutItem read FItemWithMouse write SetItemWithMouse; property cxLookAndFeel: TcxLookAndFeel read GetCxLookAndFeel; property SelectedControlCount: Integer read GetSelectedControlCount; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure BeginDragAndDrop; override; {$IFDEF DELPHI12} procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; {$ENDIF} procedure Clear; function CreateAlignmentConstraint: TdxLayoutAlignmentConstraint; function FindItem(AControl: TControl): TdxLayoutItem; overload; function FindItem(const AName: string): TdxCustomLayoutItem; overload; function GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; overload; function GetHitTest(X, Y: Integer): TdxCustomLayoutHitTest; overload; procedure BeginUpdate; procedure CancelUpdate; procedure EndUpdate(ANeedPack: Boolean = True); function CreateGroup(AGroupClass: TdxLayoutGroupClass = nil; AParent: TdxLayoutGroup = nil): TdxLayoutGroup; function CreateItem(AItemClass: TdxCustomLayoutItemClass = nil; AParent: TdxLayoutGroup = nil): TdxCustomLayoutItem; function CreateItemForControl(AControl: TControl; AParent: TdxLayoutGroup = nil): TdxLayoutItem; // Storing function CanRestore: Boolean; procedure Restore; procedure Store; procedure LoadFromIniFile(const AFileName: string); procedure LoadFromRegistry(const ARegistryPath: string); procedure LoadFromStream(AStream: TStream); procedure SaveToIniFile(const AFileName: string); procedure SaveToRegistry(const ARegistryPath: string); procedure SaveToStream(AStream: TStream); property AbsoluteItemCount: Integer read GetAbsoluteItemCount; property AbsoluteItems[Index: Integer]: TdxCustomLayoutItem read GetAbsoluteItem; property AlignmentConstraintCount: Integer read GetAlignmentConstraintCount; property AlignmentConstraints[Index: Integer]: TdxLayoutAlignmentConstraint read GetAlignmentConstraint; property AutoContentSizes: TdxLayoutAutoContentSizes read GetAutoContentSizes write SetAutoContentSizes; property LayoutDirection: TdxLayoutDirection read GetLayoutDirection write SetLayoutDirection; property AutoControlAlignment: Boolean read FAutoControlAlignment write SetAutoControlAlignment default True; property AutoControlTabOrders: Boolean read FAutoControlTabOrders write SetAutoControlTabOrders default True; property AvailableItemCount: Integer read GetAvailableItemCount; property AvailableItems[Index: Integer]: TdxCustomLayoutItem read GetAvailableItem; property FocusControlOnItemCaptionClick: Boolean read FFocusControlOnItemCaptionClick write FFocusControlOnItemCaptionClick default False; property Items: TdxLayoutGroup read FRootGroup; property IsPlacingControls: Boolean read FIsPlacingControls; property LeftPos: Integer read FLeftPos write SetLeftPos; property LookAndFeel: TdxCustomLayoutLookAndFeel read FLayoutLookAndFeel write SetLayoutLookAndFeel; property LayoutLookAndFeel: TdxCustomLayoutLookAndFeel read FLayoutLookAndFeel write SetLayoutLookAndFeel; property ShowHiddenGroupsBounds: Boolean read FShowHiddenGroupsBounds write SetShowHiddenGroupsBounds; property TopPos: Integer read FTopPos write SetTopPos; // Customization properties property Customization: Boolean read FCustomization write SetCustomization; property CustomizeAvailableItemsViewKind: TdxLayoutAvailableItemsViewKind read FCustomizeAvailableItemsViewKind write SetCustomizeAvailableItemsViewKind; property CustomizeForm: TCustomForm read FCustomizeForm; property CustomizeFormBounds: TRect read FCustomizeFormBounds write FCustomizeFormBounds; property CustomizeFormClass: TFormClass read FCustomizeFormClass write FCustomizeFormClass; // must be descendant of TdxLayoutControlCustomizeFormClass property CustomizeFormTabbedView: Boolean read FCustomizeFormTabbedView write SetCustomizeFormTabbedView; property ShowDesignSelectors: Boolean read FShowDesignSelectors write SetShowDesignSelectors; property HighlightRoot: Boolean read FHighlightRoot write SetHighlightRoot; property ContentBounds: TRect read GetContentBounds; property OccupiedClientWidth: Integer read GetOccupiedClientWidth; property OccupiedClientHeight: Integer read GetOccupiedClientHeight; // Storing properties property OptionsStoring: TdxStoringOptions read FOptionsStoring write SetOptionsStoring; property IniFileName: string read GetIniFileName write SetIniFileName; property RegistryPath: string read GetRegistryPath write SetRegistryPath; property StoreInIniFile: Boolean read GetStoreInIniFile write SetStoreInIniFile; property StoreInRegistry: Boolean read GetStoreInRegistry write SetStoreInRegistry; property Painter: TdxLayoutControlPainter read FPainter; property ViewInfo: TdxLayoutControlViewInfo read FViewInfo; property OnCustomization: TNotifyEvent read FOnCustomization write FOnCustomization; end; TdxLayoutControl = class(TdxCustomLayoutControl) published property Align; property Anchors; {$IFDEF DELPHI6} property BevelEdges; property BevelInner; property BevelOuter; property BevelKind; property BevelWidth; property BorderWidth; {$ENDIF} property Constraints; property DragCursor; property DragKind; property DragMode; property Enabled; property FocusOnClick; property Font; {$IFDEF DELPHI7} property ParentBackground default False; {$ENDIF} property ParentFont; property ParentShowHint; property PopupMenu; property ShowHint; property TabOrder; property TabStop; property Visible; property AutoContentSizes stored False; // obsolette property AutoControlAlignment; property AutoControlTabOrders; property AutoSize; property FocusControlOnItemCaptionClick; property LookAndFeel stored False; // obsolette property LayoutLookAndFeel; // Customization properties property CustomizeFormTabbedView default False; property ShowDesignSelectors default True; property HighlightRoot default True; // Storing properties property OptionsStoring; property IniFileName stored False; // obsolette property RegistryPath stored False; // obsolette property StoreInIniFile stored False; // obsolette property StoreInRegistry stored False; // obsolette property OnClick; property OnContextPopup; property OnDblClick; property OnDragDrop; property OnDragOver; property OnEndDock; property OnEndDrag; property OnEnter; property OnExit; property OnKeyDown; property OnKeyPress; property OnKeyUp; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnMouseWheel; property OnMouseWheelDown; property OnMouseWheelUp; property OnResize; property OnStartDock; property OnStartDrag; property OnCustomization; property OnMouseEnter; property OnMouseLeave; end; { hit tests } TdxCustomLayoutHitTestClass = class of TdxCustomLayoutHitTest; TdxCustomLayoutHitTest = class public function Cursor: TCursor; dynamic; class function HitTestCode: Integer; virtual; class function Instance: TdxCustomLayoutHitTest; function GetGroupForInsert: TdxLayoutGroup; virtual; end; TdxLayoutNoneHitTest = class(TdxCustomLayoutHitTest) public class function HitTestCode: Integer; override; end; TdxCustomLayoutItemHitTestClass = class of TdxCustomLayoutItemHitTest; TdxCustomLayoutItemHitTest = class(TdxCustomLayoutHitTest) private FItem: TdxCustomLayoutItem; public property Item: TdxCustomLayoutItem read FItem write FItem; end; TdxLayoutItemHitTest = class(TdxCustomLayoutItemHitTest) private function GetItem: TdxLayoutItem; procedure SetItem(Value: TdxLayoutItem); public class function HitTestCode: Integer; override; function GetGroupForInsert: TdxLayoutGroup; override; property Item: TdxLayoutItem read GetItem write SetItem; end; TdxLayoutGroupHitTest = class(TdxCustomLayoutItemHitTest) private function GetItem: TdxLayoutGroup; procedure SetItem(Value: TdxLayoutGroup); public class function HitTestCode: Integer; override; function GetGroupForInsert: TdxLayoutGroup; override; property Item: TdxLayoutGroup read GetItem write SetItem; end; TdxLayoutCustomizeFormHitTest = class(TdxCustomLayoutHitTest) public class function HitTestCode: Integer; override; end; TdxLayoutCustomizeFormAvailableItemsHitTest = class(TdxCustomLayoutHitTest) public class function HitTestCode: Integer; override; end; TdxLayoutCustomizeFormTreeViewItemsHitTest = class(TdxCustomLayoutHitTest) public class function HitTestCode: Integer; override; end; TdxLayoutClientAreaHitTest = class(TdxCustomLayoutHitTest) private FControl: TdxCustomLayoutControl; public class function HitTestCode: Integer; override; property Control: TdxCustomLayoutControl read FControl write FControl; end; { Painters } { TdxCustomLayoutElementPainter } TdxCustomLayoutElementPainter = class private FCanvas: TcxCanvas; FViewInfo: TdxCustomLayoutElementViewInfo; protected property Canvas: TcxCanvas read FCanvas; property ViewInfo: TdxCustomLayoutElementViewInfo read FViewInfo; public constructor Create(ACanvas: TcxCanvas; AViewInfo: TdxCustomLayoutElementViewInfo); virtual; procedure Paint; virtual; abstract; end; { TdxCustomLayoutItemElementPainter } TdxCustomLayoutItemElementPainter = class(TdxCustomLayoutElementPainter) private function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; function GetViewInfo: TdxCustomLayoutItemElementViewInfo; protected property LayoutLookAndFeel: TdxCustomLayoutLookAndFeel read GetLayoutLookAndFeel; property ViewInfo: TdxCustomLayoutItemElementViewInfo read GetViewInfo; end; TdxCustomLayoutItemCaptionPainter = class(TdxCustomLayoutItemElementPainter) private function GetViewInfo: TdxCustomLayoutItemCaptionViewInfo; protected procedure DoDrawText; virtual; procedure AfterDrawText; virtual; procedure BeforeDrawText; virtual; procedure DrawBackground; virtual; procedure DrawText; property ViewInfo: TdxCustomLayoutItemCaptionViewInfo read GetViewInfo; public procedure Paint; override; end; TdxLayoutGroupCaptionPainter = class(TdxCustomLayoutItemCaptionPainter); TdxLayoutItemCaptionPainter = class(TdxCustomLayoutItemCaptionPainter); TdxCustomLayoutItemPainter = class(TdxCustomLayoutElementPainter) private function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; function GetViewInfo: TdxCustomLayoutItemViewInfo; protected function GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; virtual; abstract; procedure DoDrawBackground; virtual; procedure DoDrawCaption; virtual; procedure DoDrawSpecificPart; virtual; procedure DoDrawSelectionFrame; virtual; procedure DrawBackground; virtual; procedure DrawCaption; virtual; procedure DrawContent; virtual; procedure DrawItem; function CanDrawBackground: Boolean; virtual; function CanDrawCaption: Boolean; virtual; function CanPaint: Boolean; virtual; function CanPaintSpecificPart: Boolean; virtual; property LayoutLookAndFeel: TdxCustomLayoutLookAndFeel read GetLayoutLookAndFeel; property ViewInfo: TdxCustomLayoutItemViewInfo read GetViewInfo; public procedure Paint; override; // DragImagePaint procedure PaintSpecificPart; virtual; procedure PaintDesignFeatures; virtual; end; { TdxLayoutItemControlPainter } TdxLayoutItemControlPainter = class(TdxCustomLayoutItemElementPainter) private function GetViewInfo: TdxLayoutItemControlViewInfo; protected procedure DrawBorders; virtual; property ViewInfo: TdxLayoutItemControlViewInfo read GetViewInfo; public procedure Paint; override; end; TdxLayoutItemPainter = class(TdxCustomLayoutItemPainter) private function GetViewInfo: TdxLayoutItemViewInfo; protected function CanDrawBackground: Boolean; override; function CanDrawCaption: Boolean; override; function CanPaintSpecificPart: Boolean; override; function GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; override; function GetControlPainterClass: TdxLayoutItemControlPainterClass; virtual; procedure DoDrawControlBorder; virtual; procedure DoDrawSpecificPart; override; procedure DrawContent; override; procedure DrawControlBorder; virtual; property ViewInfo: TdxLayoutItemViewInfo read GetViewInfo; end; { TdxLayoutGroupPainter } TdxLayoutGroupPainter = class(TdxCustomLayoutItemPainter) private function GetViewInfo: TdxLayoutGroupViewInfo; protected function GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; override; procedure DoDrawSpecificPart; override; procedure DoDrawSelectionFrame; override; procedure DoDrawBackground; override; procedure DrawContent; override; procedure DoDrawBorders; virtual; procedure DoDrawRestSpace; virtual; procedure DoDrawBoundsFrame; virtual; procedure DrawBorders; virtual; procedure DrawBoundsFrame; virtual; procedure DrawItems; virtual; procedure DrawRestSpace; virtual; procedure DrawItemsArea; virtual; property ViewInfo: TdxLayoutGroupViewInfo read GetViewInfo; public procedure PaintSpecificPart; override; procedure PaintDesignFeatures; override; end; // Layout Control { TdxCustomLayoutControlHandler } TdxCustomLayoutControlHandler = class private FControl: TdxCustomLayoutControl; function GetViewInfo: TdxLayoutControlViewInfo; protected property Control: TdxCustomLayoutControl read FControl; property ViewInfo: TdxLayoutControlViewInfo read GetViewInfo; public constructor Create(AControl: TdxCustomLayoutControl); virtual; end; TdxLayoutControlPainter = class(TdxCustomLayoutControlHandler) protected function GetInternalCanvas: TcxCanvas; virtual; procedure MakeCanvasClipped(ACanvas: TcxCanvas); procedure DrawBackground(ACanvas: TcxCanvas); virtual; procedure DrawDesignSelector(ACanvas: TcxCanvas); virtual; procedure DrawItems(ACanvas: TcxCanvas); virtual; procedure DrawDesignFeatures(ACanvas: TcxCanvas); procedure PlaceControls(AItemViewInfo: TdxCustomLayoutItemViewInfo); property InternalCanvas: TcxCanvas read GetInternalCanvas; public function GetCanvas: TcxCanvas; virtual; procedure Paint; virtual; end; { ViewInfos } { TdxCustomLayoutElementViewInfo } TdxCustomLayoutElementViewInfo = class private FBounds: TRect; protected function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; virtual; abstract; public procedure Calculate(const ABounds: TRect); virtual; property Bounds: TRect read FBounds; property LayoutLookAndFeel: TdxCustomLayoutLookAndFeel read GetLayoutLookAndFeel; end; { TdxCustomLayoutItemElementViewInfo } TdxCustomLayoutItemElementViewInfo = class(TdxCustomLayoutElementViewInfo) private FItemViewInfo: TdxCustomLayoutItemViewInfo; FHeight: Integer; FPressed: Boolean; FWidth: Integer; function GetItem: TdxCustomLayoutItem; function GetHeight: Integer; function GetWidth: Integer; procedure SetHeight(Value: Integer); procedure SetWidth(Value: Integer); protected function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; override; function GetEnabled: Boolean; virtual; function GetEnabledForWork: Boolean; virtual; function GetCursor(X, Y: Integer): TCursor; virtual; function GetVisible: Boolean; virtual; procedure Invalidate(const ABounds: TRect); virtual; procedure MouseEnter; dynamic; procedure MouseLeave; dynamic; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic; procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic; function WantsMouse(X, Y: Integer): Boolean; property Item: TdxCustomLayoutItem read GetItem; property ItemViewInfo: TdxCustomLayoutItemViewInfo read FItemViewInfo; property Pressed: Boolean read FPressed write FPressed; property Visible: Boolean read GetVisible; public constructor Create(AItemViewInfo: TdxCustomLayoutItemViewInfo); virtual; function CalculateMinHeight: Integer; virtual; function CalculateMinWidth: Integer; virtual; function CalculateHeight: Integer; virtual; function CalculateWidth: Integer; virtual; property Enabled: Boolean read GetEnabled; property EnabledForWork: Boolean read GetEnabledForWork; property Height: Integer read GetHeight write SetHeight; property Width: Integer read GetWidth write SetWidth; end; TdxCustomLayoutItemCaptionViewInfo = class(TdxCustomLayoutItemElementViewInfo) private FHotTracked: Boolean; function GetCanvas: TcxCanvas; function GetIsCustomization: Boolean; function GetTextHeight: Integer; function GetTextWidth: Integer; procedure SetHotTracked(Value: Boolean); protected function GetCursor(X, Y: Integer): TCursor; override; function GetVisible: Boolean; override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseLeave; override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; function CalculateTextFlags: Integer; virtual; function CanDoCaptionClick(X, Y: Integer): Boolean; virtual; function GetAlignHorz: TAlignment; virtual; function GetAlignVert: TdxAlignmentVert; virtual; abstract; function GetColor: TColor; virtual; function GetFont: TFont; virtual; function GetHotTrackBounds: TRect; virtual; function GetHotTrackStyles: TdxLayoutHotTrackStyles; virtual; function GetIsDefaultColor: Boolean; virtual; function GetIsHotTrackable: Boolean; virtual; function GetIsTextUnderlined: Boolean; virtual; function GetIsTransparent: Boolean; virtual; function GetMultiLine: Boolean; virtual; abstract; function GetOptions: TdxLayoutLookAndFeelCaptionOptions; virtual; function GetText: string; virtual; function GetTextAreaBounds: TRect; virtual; function GetTextColor: TColor; virtual; function GetTextHotColor: TColor; virtual; function GetTextNormalColor: TColor; virtual; function GetVisibleText: string; virtual; function IsPointInHotTrackBounds(const P: TPoint): Boolean; virtual; procedure PrepareCanvas; virtual; property AlignHorz: TAlignment read GetAlignHorz; property AlignVert: TdxAlignmentVert read GetAlignVert; property Canvas: TcxCanvas read GetCanvas; property HotTrackBounds: TRect read GetHotTrackBounds; property HotTrackStyles: TdxLayoutHotTrackStyles read GetHotTrackStyles; property IsCustomization: Boolean read GetIsCustomization; property IsDefaultColor: Boolean read GetIsDefaultColor; property IsHotTrackable: Boolean read GetIsHotTrackable; property IsTransparent: Boolean read GetIsTransparent; property MultiLine: Boolean read GetMultiLine; property Options: TdxLayoutLookAndFeelCaptionOptions read GetOptions; property TextHeight: Integer read GetTextHeight; property TextWidth: Integer read GetTextWidth; public function CalculateHeight: Integer; override; function CalculateWidth: Integer; override; property Color: TColor read GetColor; property Font: TFont read GetFont; property HotTracked: Boolean read FHotTracked write SetHotTracked; property IsTextUnderlined: Boolean read GetIsTextUnderlined; property Text: string read GetText; property TextAreaBounds: TRect read GetTextAreaBounds; property TextColor: TColor read GetTextColor; property VisibleText: string read GetVisibleText; end; TdxCustomLayoutItemCaptionViewInfoClass = class of TdxCustomLayoutItemCaptionViewInfo; TdxCustomLayoutItemViewInfo = class(TdxCustomLayoutElementViewInfo) private FOffsets: array[TdxLayoutSide] of Integer; FCaptionViewInfo: TdxCustomLayoutItemCaptionViewInfo; FContainerViewInfo: TdxLayoutControlViewInfo; FParentViewInfo: TdxLayoutGroupViewInfo; FElements: TObjectList; FElementWithMouse: TdxCustomLayoutItemElementViewInfo; FItem: TdxCustomLayoutItem; FNotifyComponent: TcxFreeNotificator; function GetMinHeight: Integer; function GetMinWidth: Integer; function GetHeight: Integer; function GetWidth: Integer; function GetAlignHorz: TdxLayoutAlignHorz; function GetAlignVert: TdxLayoutAlignVert; function GetBackgroundBounds: TRect; function GetCanPaint: Boolean; function GetIsAvailable: Boolean; function GetIsCustomization: Boolean; function GetIsDragged: Boolean; function GetIsDraggedWithParent: Boolean; function GetIsDragImagePainted: Boolean; function GetOffset(ASide: TdxLayoutSide): Integer; function GetOffsetsHeight: Integer; function GetOffsetsWidth: Integer; function GetSelected: Boolean; function GetSelectionArea: TRect; function GetSelectionBorderRect: TRect; procedure SetElementWithMouse(Value: TdxCustomLayoutItemElementViewInfo); procedure SetOffset(ASide: TdxLayoutSide; Value: Integer); function CreateHitTest: TdxCustomLayoutItemHitTest; protected procedure DoCreateViewInfos; virtual; procedure CreateViewInfos; procedure DestroyViewInfos; virtual; procedure FreeNotification(AComponent: TComponent); virtual; function CanDrawBackground: Boolean; virtual; function GetBackgroundColor: TColor; virtual; function GetCaptionViewInfoClass: TdxCustomLayoutItemCaptionViewInfoClass; virtual; abstract; function GetHitTestClass: TdxCustomLayoutItemHitTestClass; virtual; abstract; function GetPainterClass: TdxCustomLayoutItemPainterClass; virtual; abstract; function CalculateMinHeight: Integer; function CalculateMinWidth: Integer; function CalculateHeight: Integer; function CalculateWidth: Integer; function DoCalculateHeight(AIsMinHeight: Boolean): Integer; virtual; function DoCalculateWidth(AIsMinWidth: Boolean): Integer; virtual; function CalculateOffset(ASide: TdxLayoutSide): Integer; virtual; function GetAreaPart(const P: TPoint): TdxLayoutAreaPart; virtual; function GetActuallyVisible: Boolean; virtual; function GetColor: TColor; virtual; abstract; function GetCursor(X, Y: Integer): TCursor; virtual; function GetElement(AIndex: Integer): TdxCustomLayoutItemElementViewInfo; function GetElementCount: Integer; function GetEnabled: Boolean; virtual; function GetEnabledForWork: Boolean; virtual; function GetIsDefaultColor: Boolean; virtual; abstract; function GetIsTransparent: Boolean; virtual; function GetOptions: TdxCustomLayoutLookAndFeelOptions; virtual; abstract; function HasBackground: Boolean; function HasCaption: Boolean; virtual; // #DG !!! function HasBorder: Boolean; virtual; procedure MouseEnter; dynamic; procedure MouseLeave; dynamic; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic; procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic; function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; override; // selections procedure PaintSelectionLayer; virtual; function IsParentLocked: Boolean; function IsParentSelected: Boolean; property ActuallyVisible: Boolean read GetActuallyVisible; property BackgroundBounds: TRect read GetBackgroundBounds; property CanPaint: Boolean read GetCanPaint; // todo: rename property ContainerViewInfo: TdxLayoutControlViewInfo read FContainerViewInfo; property ElementCount: Integer read GetElementCount; property Elements[Index: Integer]: TdxCustomLayoutItemElementViewInfo read GetElement; property ElementWithMouse: TdxCustomLayoutItemElementViewInfo read FElementWithMouse write SetElementWithMouse; property IsAvailable: Boolean read GetIsAvailable; property IsCustomization: Boolean read GetIsCustomization; property IsDefaultColor: Boolean read GetIsDefaultColor; property IsDragged: Boolean read GetIsDragged; property IsDraggedWithParent: Boolean read GetIsDraggedWithParent; property IsDragImagePainted: Boolean read GetIsDragImagePainted; property IsTransparent: Boolean read GetIsTransparent; property Item: TdxCustomLayoutItem read FItem; property OffsetsHeight: Integer read GetOffsetsHeight; property OffsetsWidth: Integer read GetOffsetsWidth; property Options: TdxCustomLayoutLookAndFeelOptions read GetOptions; property ParentViewInfo: TdxLayoutGroupViewInfo read FParentViewInfo; public constructor Create(AContainerViewInfo: TdxLayoutControlViewInfo; AParentViewInfo: TdxLayoutGroupViewInfo; AItem: TdxCustomLayoutItem); virtual; destructor Destroy; override; procedure Calculate(const ABounds: TRect); override; procedure CalculateTabOrders(var AAvailTabOrder: Integer); virtual; abstract; function GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; virtual; function GetItemWithMouse(const P: TPoint): TdxCustomLayoutItem; virtual; procedure ResetOffset(ASide: TdxLayoutSide); property AlignHorz: TdxLayoutAlignHorz read GetAlignHorz; property AlignVert: TdxLayoutAlignVert read GetAlignVert; property CaptionViewInfo: TdxCustomLayoutItemCaptionViewInfo read FCaptionViewInfo; property Color: TColor read GetColor; property Enabled: Boolean read GetEnabled; property EnabledForWork: Boolean read GetEnabledForWork; property MinWidth: Integer read GetMinWidth; property MinHeight: Integer read GetMinHeight; property Width: Integer read GetWidth; property Height: Integer read GetHeight; property Offsets[ASide: TdxLayoutSide]: Integer read GetOffset write SetOffset; property Selected: Boolean read GetSelected; property SelectionBorderRect: TRect read GetSelectionBorderRect; property SelectionArea: TRect read GetSelectionArea; end; { ItemViewInfos } { TdxLayoutItemCaptionViewInfo } TdxLayoutItemCaptionViewInfo = class(TdxCustomLayoutItemCaptionViewInfo) private function GetItem: TdxLayoutItem; function GetItemViewInfo: TdxLayoutItemViewInfo; protected function GetAlignVert: TdxAlignmentVert; override; function GetIsFixedWidth: Boolean; virtual; function GetMultiLine: Boolean; override; function GetTextAreaBounds: TRect; override; property IsFixedWidth: Boolean read GetIsFixedWidth; property Item: TdxLayoutItem read GetItem; property ItemViewInfo: TdxLayoutItemViewInfo read GetItemViewInfo; public function CalculateWidth: Integer; override; function CalculateMinWidth: Integer; override; end; TdxLayoutItemControlViewInfoClass = class of TdxLayoutItemControlViewInfo; TdxLayoutItemControlViewInfo = class(TdxCustomLayoutItemElementViewInfo) private FControlBounds: TRect; function GetBorderColor: TColor; function GetBorderStyle: TdxLayoutBorderStyle; function GetControl: TControl; function GetItem: TdxLayoutItem; function GetItemViewInfo: TdxLayoutItemViewInfo; function GetOpaqueControl: Boolean; protected function GetVisible: Boolean; override; function CalculateControlBounds: TRect; virtual; function GetBorderWidth(ASide: TdxLayoutSide): Integer; virtual; function GetControlAreaHeight(AControlHeight: Integer): Integer; virtual; function GetControlAreaWidth(AControlWidth: Integer): Integer; virtual; function HasBorder: Boolean; property BorderWidths[ASide: TdxLayoutSide]: Integer read GetBorderWidth; property Item: TdxLayoutItem read GetItem; property ItemViewInfo: TdxLayoutItemViewInfo read GetItemViewInfo; public procedure Calculate(const ABounds: TRect); override; procedure CalculateTabOrder(var AAvailTabOrder: Integer); virtual; function CalculateMinHeight: Integer; override; function CalculateMinWidth: Integer; override; function CalculateHeight: Integer; override; function CalculateWidth: Integer; override; property BorderColor: TColor read GetBorderColor; property BorderStyle: TdxLayoutBorderStyle read GetBorderStyle; property Control: TControl read GetControl; property ControlBounds: TRect read FControlBounds; property OpaqueControl: Boolean read GetOpaqueControl; end; TdxLayoutItemViewInfo = class(TdxCustomLayoutItemViewInfo) private FControlViewInfo: TdxLayoutItemControlViewInfo; function GetCaptionViewInfo: TdxLayoutItemCaptionViewInfo; function GetItem: TdxLayoutItem; function GetOptionsEx: TdxLayoutLookAndFeelItemOptions; function GetDesignSelectorRect: TRect; protected procedure DoCreateViewInfos; override; function GetCaptionViewInfoClass: TdxCustomLayoutItemCaptionViewInfoClass; override; function GetControlViewInfoClass: TdxLayoutItemControlViewInfoClass; virtual; function GetHitTestClass: TdxCustomLayoutItemHitTestClass; override; function GetPainterClass: TdxCustomLayoutItemPainterClass; override; procedure CalculateViewInfosBounds(var ACaptionBounds, AControlBounds: TRect); virtual; function DoCalculateHeight(AIsMinHeight: Boolean): Integer; override; function DoCalculateWidth(AIsMinWidth: Boolean): Integer; override; function GetAutoControlAlignment: Boolean; virtual; function GetCaptionLayout: TdxCaptionLayout; virtual; function GetColor: TColor; override; function GetContentBounds: TRect; virtual; function GetControlOffsetHorz: Integer; virtual; function GetControlOffsetVert: Integer; virtual; function GetIsDefaultColor: Boolean; override; function GetOptions: TdxCustomLayoutLookAndFeelOptions; override; function HasControl: Boolean; virtual; // selections procedure PaintSelectionLayer; override; function PtInDesignSelectorRect(const P: TPoint): Boolean; property ControlOffsetHorz: Integer read GetControlOffsetHorz; property ControlOffsetVert: Integer read GetControlOffsetVert; property Item: TdxLayoutItem read GetItem; property Options: TdxLayoutLookAndFeelItemOptions read GetOptionsEx; public procedure Calculate(const ABounds: TRect); override; procedure CalculateTabOrders(var AAvailTabOrder: Integer); override; property AutoControlAlignment: Boolean read GetAutoControlAlignment; property CaptionLayout: TdxCaptionLayout read GetCaptionLayout; property CaptionViewInfo: TdxLayoutItemCaptionViewInfo read GetCaptionViewInfo; property ContentBounds: TRect read GetContentBounds; property ControlViewInfo: TdxLayoutItemControlViewInfo read FControlViewInfo; property DesignSelectorRect: TRect read GetDesignSelectorRect; end; { GroupViewInfos } { TdxLayoutGroupCaptionViewInfo } TdxLayoutGroupCaptionViewInfo = class(TdxCustomLayoutItemCaptionViewInfo) protected function GetAlignVert: TdxAlignmentVert; override; function GetMultiLine: Boolean; override; public function CalculateMinWidth: Integer; override; end; TItemInfo = record ViewInfo: TdxCustomLayoutItemViewInfo; AlignHorz: TdxLayoutAlignHorz; CalculatedWidth, MinWidth, Width, Height: Integer; Bounds: TRect; Calculated: Boolean; end; TItemInfos = array of TItemInfo; TdxLayoutGroupViewInfoSpecific = class private FGroupViewInfo: TdxLayoutGroupViewInfo; FItemInfos: TItemInfos; procedure PrepareItemInfos; procedure CalculateItemViewInfos; function GetContainer: TdxCustomLayoutControl; function GetItemOffset: Integer; function GetItemViewInfo(Index: Integer): TdxCustomLayoutItemViewInfo; function GetItemViewInfoCount: Integer; function GetLayoutDirection: TdxLayoutDirection; protected // Drawing procedure DrawSpecificPart(ACanvas: TcxCanvas); virtual; // !!! procedure DrawSpecificBackground(ACanvas: TcxCanvas); virtual; // !!! // Calculating procedure CalculateItemsHorizontalBounds(const AItemsAreaBounds: TRect); virtual; procedure CalculateItemsVerticalBounds(const AItemsAreaBounds: TRect); virtual; procedure CalculateTabOrders(var ATabOrder: Integer); virtual; // Dragging function GetAreaPart(const P: TPoint): TdxLayoutAreaPart; virtual; function GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; virtual; // Sizes procedure ConvertCoords(var R: TRect); virtual; function GetCustomHeight(AIsMinHeight: Boolean): Integer; virtual; function GetCustomWidth(AIsMinWidth: Boolean): Integer; virtual; function GetItemAlignHorz(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignHorz; virtual; abstract; function GetItemAlignVert(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignVert; virtual; abstract; function GetItemHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; virtual; abstract; function GetItemWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; virtual; abstract; function GetItemMinHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; virtual; abstract; function GetItemMinWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; virtual; abstract; function GetItemsAreaOffset(ASide: TdxLayoutSide): Integer; virtual; // Selection procedure AddSelectionControls; virtual; procedure RemoveSelectionControls; virtual; // Specific Objects procedure CreateSpecificControls; virtual; procedure DestroySpecificControls; virtual; procedure CreateViewInfos; virtual; procedure SetControlVisibility; virtual; property Container: TdxCustomLayoutControl read GetContainer; property GroupViewInfo: TdxLayoutGroupViewInfo read FGroupViewInfo; property ItemOffset: Integer read GetItemOffset; property ItemViewInfoCount: Integer read GetItemViewInfoCount; property ItemViewInfos[Index: Integer]: TdxCustomLayoutItemViewInfo read GetItemViewInfo; property LayoutDirection: TdxLayoutDirection read GetLayoutDirection; public constructor Create(AGroupViewInfo: TdxLayoutGroupViewInfo); virtual; destructor Destroy; override; procedure Calculate(const AItemsAreaBounds: TRect); virtual; procedure CalculateItemsBounds(AItemsAreaBounds: TRect); function CanDrawBackground: Boolean; virtual; function GetItemsAreaHeight(AIsMinHeight: Boolean): Integer; virtual; function GetItemsAreaWidth(AIsMinWidth: Boolean): Integer; virtual; function IsAtInsertionPos(const R: TRect; const P: TPoint): Boolean; virtual; abstract; function AllowDrawChild(AChild: TdxCustomLayoutItem): Boolean; virtual; function AllowChildHasBorder: Boolean; virtual; end; TdxLayoutGroupViewInfoHorizontalSpecific = class(TdxLayoutGroupViewInfoSpecific) protected function GetItemAlignHorz(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignHorz; override; function GetItemAlignVert(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignVert; override; function GetItemHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; override; function GetItemWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; override; function GetItemMinHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; override; function GetItemMinWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; override; public function IsAtInsertionPos(const R: TRect; const P: TPoint): Boolean; override; end; TdxLayoutGroupViewInfoVerticalSpecific = class(TdxLayoutGroupViewInfoSpecific) protected procedure ConvertCoords(var R: TRect); override; function GetItemAlignHorz(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignHorz; override; function GetItemAlignVert(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignVert; override; function GetItemHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; override; function GetItemWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; override; function GetItemMinHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; override; function GetItemMinWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; override; public function GetItemsAreaHeight(AIsMinHeight: Boolean): Integer; override; function GetItemsAreaWidth(AIsMinWidth: Boolean): Integer; override; function IsAtInsertionPos(const R: TRect; const P: TPoint): Boolean; override; end; TdxLayoutTabbedGroupTabControl = class(TcxTabControl) private procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; protected procedure BoundsChanged; override; function GetDesignHitTest(X, Y: Integer; Shift: TShiftState): Boolean; override; end; TdxTabControlElementViewInfo = class(TdxCustomLayoutItemElementViewInfo) private FTabControl: TdxLayoutTabbedGroupTabControl; protected function GetVisible: Boolean; override; procedure MouseEnter; override; procedure MouseLeave; override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; end; TdxLayoutGroupViewInfoTabbedSpecific = class(TdxLayoutGroupViewInfoHorizontalSpecific) private FTabControl: TdxLayoutTabbedGroupTabControl; FTabControlElementViewInfo: TdxTabControlElementViewInfo; procedure ActiveTabChanged(ASender: TObject); protected // Drawing procedure DrawSpecificPart(ACanvas: TcxCanvas); override; procedure DrawSpecificBackground(ACanvas: TcxCanvas); override; // Calculating procedure CalculateItemsHorizontalBounds(const AItemsAreaBounds: TRect); override; procedure CalculateItemsVerticalBounds(const AItemsAreaBounds: TRect); override; procedure CalculateTabOrders(var ATabOrder: Integer); override; // Dragging function GetAreaPart(const P: TPoint): TdxLayoutAreaPart; override; function GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; override; // Sizes function GetCustomHeight(AIsMinHeight: Boolean): Integer; override; function GetCustomWidth(AIsMinWidth: Boolean): Integer; override; function GetItemsAreaOffset(ASide: TdxLayoutSide): Integer; override; // Specific Objects procedure CreateSpecificControls; override; procedure DestroySpecificControls; override; procedure CreateViewInfos; override; procedure SetControlVisibility; override; procedure CreateTabControl; procedure DestroyTabControl; function HasTabControl: Boolean; public procedure Calculate(const AItemsAreaBounds: TRect); override; function AllowDrawChild(AChild: TdxCustomLayoutItem): Boolean; override; function AllowChildHasBorder: Boolean; override; function CanDrawBackground: Boolean; override; end; TdxLayoutGroupViewInfo = class(TdxCustomLayoutItemViewInfo) private FOffsetsCalculated: Boolean; FItemOffset: Integer; FItemsAreaOffsetHorz: Integer; FItemsAreaOffsetVert: Integer; FItemViewInfos: TObjectList; FSpecific: TdxLayoutGroupViewInfoSpecific; function GetBorderBounds(ASide: TdxLayoutSide): TRect; function GetBorderRestSpaceBounds(ASide: TdxLayoutSide): TRect; function GetBordersHeight: Integer; function GetBordersWidth: Integer; function GetCaptionViewInfo: TdxLayoutGroupCaptionViewInfo; function GetGroup: TdxLayoutGroup; function GetIsLocked: Boolean; function GetItemViewInfo(Index: Integer): TdxCustomLayoutItemViewInfo; function GetItemViewInfoCount: Integer; function GetLayoutDirection: TdxLayoutDirection; function GetOptionsEx: TdxLayoutLookAndFeelGroupOptions; function GetOffset(Index: Integer): Integer; procedure CreateItemViewInfos; procedure CreateSpecific; procedure DestroyItemViewInfos; procedure DestroySpecific; protected FCaptionAreaBounds: TRect; FClientAreaBounds: TRect; FItemsAreaBounds: TRect; procedure DoCreateViewInfos; override; procedure DestroyViewInfos; override; procedure FreeNotification(AComponent: TComponent); override; // Classes function GetCaptionViewInfoClass: TdxCustomLayoutItemCaptionViewInfoClass; override; function GetHitTestClass: TdxCustomLayoutItemHitTestClass; override; function GetPainterClass: TdxCustomLayoutItemPainterClass; override; // Drawing attributes function GetBackgroundColor: TColor; override; function GetColor: TColor; override; function GetIsDefaultColor: Boolean; override; function GetOptions: TdxCustomLayoutLookAndFeelOptions; override; // Calculating function DoCalculateHeight(AIsMinHeight: Boolean = False): Integer; override; function DoCalculateWidth(AIsMinWidth: Boolean = False): Integer; override; // Dragging function GetAreaPart(const P: TPoint): TdxLayoutAreaPart; override; // Conditions function HasCaption: Boolean; override; function HasBorder: Boolean; override; // TdxLayoutGroupViewInfo methods // Calculating procedure CalculateCaptionViewInfoBounds; virtual; procedure CalculateClientBounds; virtual; procedure CalculateItemsAreaBounds; virtual; procedure CalculateOffsets; // Sizes function GetClientAreaBounds(const ABounds: TRect): TRect; function GetItemAreaBounds(const AClientRect: TRect): TRect; function GetBorderWidth(ASide: TdxLayoutSide): Integer; virtual; function GetHeight(AItemsAreaHeight: Integer): Integer; virtual; function GetWidth(AItemsAreaWidth: Integer): Integer; virtual; function GetMinVisibleHeight: Integer; virtual; function GetMinVisibleWidth: Integer; virtual; function GetRestSpaceBounds: TRect; virtual; // Conditions function AllowChildHasBorder: Boolean; function HasBoundsFrame: Boolean; virtual; function UseItemOffset: Boolean; virtual; function UseItemsAreaOffsets: Boolean; virtual; // Classes function GetItemViewInfoClass(AItem: TdxCustomLayoutItem): TdxCustomLayoutItemViewInfoClass; virtual; function GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; virtual; // Selections procedure PaintSelectionLayer; override; property ItemOffset: Integer index 0 read GetOffset write FItemOffset; property ItemsAreaOffsetHorz: Integer index 1 read GetOffset write FItemsAreaOffsetHorz; property ItemsAreaOffsetVert: Integer index 2 read GetOffset write FItemsAreaOffsetVert; property MinVisibleHeight: Integer read GetMinVisibleHeight; property MinVisibleWidth: Integer read GetMinVisibleWidth; property RestSpaceBounds: TRect read GetRestSpaceBounds; property Group: TdxLayoutGroup read GetGroup; property LayoutDirection: TdxLayoutDirection read GetLayoutDirection; property Options: TdxLayoutLookAndFeelGroupOptions read GetOptionsEx; property Specific: TdxLayoutGroupViewInfoSpecific read FSpecific; public procedure Calculate(const ABounds: TRect); override; procedure CalculateTabOrders(var AAvailTabOrder: Integer); override; function GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; override; function GetItemWithMouse(const P: TPoint): TdxCustomLayoutItem; override; function GetInsertionPos(const P: TPoint): Integer; virtual; property BorderBounds[ASide: TdxLayoutSide]: TRect read GetBorderBounds; property BorderRestSpaceBounds[ASide: TdxLayoutSide]: TRect read GetBorderRestSpaceBounds; property BorderWidths[ASide: TdxLayoutSide]: Integer read GetBorderWidth; property BordersHeight: Integer read GetBordersHeight; property BordersWidth: Integer read GetBordersWidth; property CaptionViewInfo: TdxLayoutGroupCaptionViewInfo read GetCaptionViewInfo; property ClientBounds: TRect read FClientAreaBounds; property IsLocked: Boolean read GetIsLocked; property ItemsAreaBounds: TRect read FItemsAreaBounds; property ItemViewInfoCount: Integer read GetItemViewInfoCount; property ItemViewInfos[Index: Integer]: TdxCustomLayoutItemViewInfo read GetItemViewInfo; end; // control TdxLayoutControlViewInfo = class(TdxCustomLayoutControlHandler) private FCanvas: TcxCanvas; FContentBounds: TRect; FItemsViewInfo: TdxLayoutGroupViewInfo; FSelectionLayer: TdxSelectionLayer; FIsDragImagePainted: Boolean; procedure CreateSelectionLayer; procedure BuildSelectionLayer; function GetClientHeight: Integer; function GetClientWidth: Integer; function GetContentHeight: Integer; function GetContentWidth: Integer; function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; function GetSelectionLayer: TdxSelectionLayer; protected procedure CreateViewInfos; virtual; procedure DestroyViewInfos; virtual; function GetItemsViewInfoClass: TdxLayoutGroupViewInfoClass; virtual; procedure RecreateViewInfos; procedure AlignItems; virtual; procedure AutoAlignControls; virtual; procedure CalculateItemsViewInfo; virtual; procedure CalculateTabOrders; virtual; function GetIsTransparent: Boolean; virtual; function HasBackground: Boolean; function NeedHighlightRoot: Boolean; procedure PrepareData; virtual; procedure ResetContentBounds; function GetCanvas: TcxCanvas; virtual; function GetClientBounds: TRect; virtual; function GetContentBounds: TRect; virtual; property Canvas: TcxCanvas read GetCanvas; property IsDragImagePainted: Boolean read FIsDragImagePainted write FIsDragImagePainted; property IsTransparent: Boolean read GetIsTransparent; property SelectionLayer: TdxSelectionLayer read GetSelectionLayer; public constructor Create(AControl: TdxCustomLayoutControl); override; destructor Destroy; override; procedure Calculate; virtual; procedure DoCalculateTabOrders; virtual; function GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; overload; virtual; function GetHitTest(X, Y: Integer): TdxCustomLayoutHitTest; overload; function GetItemWithMouse(const P: TPoint): TdxCustomLayoutItem; property ClientBounds: TRect read GetClientBounds; property ClientHeight: Integer read GetClientHeight; property ClientWidth: Integer read GetClientWidth; property ContentBounds: TRect read GetContentBounds; property ContentHeight: Integer read GetContentHeight; property ContentWidth: Integer read GetContentWidth; property ItemsViewInfo: TdxLayoutGroupViewInfo read FItemsViewInfo; property LayoutLookAndFeel: TdxCustomLayoutLookAndFeel read GetLayoutLookAndFeel; end; { other } TdxLayoutCustomizeListBox = class(TcxCustomizeListBox) private FControl: TdxCustomLayoutControl; function GetDragAndDropItemObject: TdxCustomLayoutItem; protected procedure BeginDragAndDrop; override; property DragAndDropItemObject: TdxCustomLayoutItem read GetDragAndDropItemObject; public property Control: TdxCustomLayoutControl read FControl write FControl; end; { TdxLayoutRunTimeSelectionHelper } TdxLayoutRunTimeSelectionHelper = class(TPersistent, IdxLayoutSelectionHelper) private FListeners: TList; FOwner: TPersistent; FRefCount: Integer; FSelectionList: TcxComponentList; function GetComponent: TComponent; procedure SelectionListNotifyHandler(Sender: TObject; AComponent: TComponent; AAction: TListNotification); procedure SelectionListChangedHandler(Sender: TObject; AComponent: TComponent; AAction: TcxComponentCollectionNotification); protected function GetComponentClass(AComponent: TComponent): TComponentClass; procedure NotifyListeners(AList: TList; AAction: TdxLayoutSelectionAction); procedure SelectionListNotify(AComponent: TComponent; AAction: TListNotification); //IUnknown function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; property Component: TComponent read GetComponent; property Listeners: TList read FListeners; public constructor Create(AOwner: TPersistent); virtual; destructor Destroy; override; // IdxLayoutControlSelectionController procedure AddSelectionChangedListener(AListener: TPersistent); virtual; procedure RemoveSelectionChangedListener(AListener: TPersistent); virtual; //IcxLayoutControlDesignerHelper function CanDeleteComponent(AComponent: TComponent): Boolean; virtual; procedure ClearSelection; virtual; procedure GetSelection(AList: TList); virtual; function IsComponentSelected(AComponent: TPersistent): Boolean; virtual; procedure SelectComponent(AComponent: TPersistent; AShift: TShiftState = []); virtual; procedure SetSelection(AList: TList); virtual; function UniqueName(const BaseName: string): string; virtual; property Owner: TPersistent read FOwner; end; TdxLayoutRunTimeSelectionHelperClass = class of TdxLayoutRunTimeSelectionHelper; var dxLayoutSelectionHelperClass: TdxLayoutRunTimeSelectionHelperClass; implementation {$R *.res} uses Types, TypInfo, Menus, Registry, Math, Variants, {$IFDEF DELPHI7} UxTheme, Themes, {$ENDIF} cxContainer, dxOffice11, dxLayoutControlAdapters, dxLayoutCustomizeForm, dxLayoutStrs; type TControlAccess = class(TControl); TdxCustomLayoutLookAndFeelAccess = class(TdxCustomLayoutLookAndFeel); TcxPCCustomPainterAccess = class(TcxPCCustomPainter); const ScrollStep = 10; dxLayoutSelectionDefaultColor: TColor = $EDC8A3; dxLayoutControlSelectionDefaultColor: TColor = $582801; dxLayoutSelectionBorderDefaultColor: TColor = $BD8753; dxLayoutSelectionDefaultAlphaChannel: Byte = 80; dxLayoutSelectionBorderMarkerInnerDefaultColor: TColor = clWhite; dxLayoutHiddenGroupBackgroundDefaultColor: TColor = $F0E3D1; dxLayoutHiddenGroupBorderDefaultColor: TColor = $C8BCB5; dxLayoutSelectionOffset: Cardinal = 2; dxSelectionMarkerWidth: Cardinal = 5; dxLayoutDestinationColor = $D0D0EE; dxLayoutDestinationBorderColor = $000059; procedure dxDrawSelectionMarkers(ACanvas: TcxCanvas; const ABorderBounds: TRect; ABorderColor, ABorderMarkerInnerColor: TColor; AMarkerWidth: Integer); procedure DrawSelectionBorderMarker(const P: TPoint); var R: TRect; begin R.TopLeft := P; R.BottomRight := P; InflateRect(R, (AMarkerWidth - 1) div 2, (AMarkerWidth - 1) div 2); Inc(R.Bottom); Inc(R.Right); ACanvas.Brush.Color := ABorderMarkerInnerColor; ACanvas.Pen.Color := ABorderColor; ACanvas.Canvas.Rectangle(R); ACanvas.ExcludeClipRect(R); end; var AMiddleX: Integer; AMiddleY: Integer; begin with ABorderBounds do begin DrawSelectionBorderMarker(TopLeft); DrawSelectionBorderMarker(Point(Right - 1, Bottom - 1)); DrawSelectionBorderMarker(Point(Left, Bottom - 1)); DrawSelectionBorderMarker(Point(Right - 1, Top)); AMiddleX := (Left + Right - 1) div 2; AMiddleY := (Top + Bottom - 1) div 2; DrawSelectionBorderMarker(Point(AMiddleX, Top)); DrawSelectionBorderMarker(Point(AMiddleX, Bottom - 1)); DrawSelectionBorderMarker(Point(Left, AMiddleY)); DrawSelectionBorderMarker(Point(Right - 1, AMiddleY)); end; end; type { TdxCustomizationCanvas } TdxCustomizationCanvasState = record PrevCanvas: TCanvas; PrevDC: THandle; NewDC: THandle; NewDCIndex: Integer; end; TdxCustomizationCanvasStates = array of TdxCustomizationCanvasState; TdxCustomizationCanvas = class(TcxCanvas) private FCounter: Integer; FSavedDCs: TdxCustomizationCanvasStates; function HandleValid: Boolean; public constructor Create; reintroduce; destructor Destroy; override; procedure BeginPaint(ADC: THandle); overload; procedure BeginPaint(ACanvas: TCanvas); overload; procedure EndPaint; end; { TdxCustomSatelliteControlItem } TdxSatelliteControls = class; TdxCustomSatelliteControlItem = class(TComponent) private FControl: TControl; FOwner: TdxSatelliteControls; protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; public constructor Create(AOwner: TdxSatelliteControls; AControl: TControl); reintroduce; virtual; destructor Destroy; override; property Control: TControl read FControl; property Owner: TdxSatelliteControls read FOwner; end; TdxCustomSatelliteControlItemClass = class of TdxCustomSatelliteControlItem; { TdxControlDesignSelectorItem } TdxControlDesignSelectorItem = class(TdxCustomSatelliteControlItem) private FChildren: TcxComponentList; FDefaultControlWndProc: TWndMethod; FLayoutItem: TdxLayoutItem; FParent: TdxControlDesignSelectorItem; FSelectorBounds: TRect; function GetSelectorBoundsForChild(AChild: TdxControlDesignSelectorItem): TRect; procedure SetLayoutItem(AValue: TdxLayoutItem); procedure SetSelectorBounds(const AValue: TRect); protected procedure ControlWndProc(var Message: TMessage); procedure CheckChildren; procedure ParentCheckChildren; function IsActive: Boolean; function IsValid: Boolean; // Draw function CanDrawDesignSelector: Boolean; procedure DoDrawDesignSelector(DC: HDC); procedure DrawDesignSelector(DC: HDC); property Parent: TdxControlDesignSelectorItem read FParent write FParent; public constructor Create(AOwner: TdxSatelliteControls; AControl: TControl); reintroduce; override; destructor Destroy; override; property SelectorBounds: TRect read FSelectorBounds write SetSelectorBounds; property LayoutItem: TdxLayoutItem read FLayoutItem write SetLayoutItem; end; { TdxCustomizationControlItem } TdxCustomizationControlItem = class(TdxCustomSatelliteControlItem) private FPrevEnabled: Boolean; function GetControl: TWinControl; public constructor Create(AOwner: TdxSatelliteControls; AControl: TControl); reintroduce; override; destructor Destroy; override; property Control: TWinControl read GetControl; end; { TdxSatelliteControls } TdxSatelliteControls = class(TcxComponentList) private function GetItem(Index: Integer): TdxCustomSatelliteControlItem; public function AddControl(AControl: TControl; AItemClass: TdxCustomSatelliteControlItemClass): TdxCustomSatelliteControlItem; function FindByControl(AControl: TControl): Integer; procedure RemoveControl(AControl: TControl); property Items[Index: Integer]: TdxCustomSatelliteControlItem read GetItem; default; end; { TdxLayoutControlAdapterDefs } PControlAdapterRecord = ^TControlAdapterRecord; TControlAdapterRecord = record ControlClass: TControlClass; AdapterClass: TdxCustomLayoutControlAdapterClass; end; TdxLayoutControlAdapterDefs = class private FItems: TList; function GetCount: Integer; function GetItem(Index: Integer): TControlAdapterRecord; procedure ClearItems; protected procedure Delete(AIndex: Integer); property Count: Integer read GetCount; property Items[Index: Integer]: TControlAdapterRecord read GetItem; public constructor Create; destructor Destroy; override; function GetAdapterClass(AControl: TControl): TdxCustomLayoutControlAdapterClass; procedure Register(AControlClass: TControlClass; AAdapterClass: TdxCustomLayoutControlAdapterClass); procedure Unregister(AControlClass: TControlClass; AAdapterClass: TdxCustomLayoutControlAdapterClass); end; var FdxLayoutControlAdapterDefs: TdxLayoutControlAdapterDefs; FGlobalCanvas: TdxCustomizationCanvas; function dxLayoutControlAdapterDefs: TdxLayoutControlAdapterDefs; begin if FdxLayoutControlAdapterDefs = nil then FdxLayoutControlAdapterDefs := TdxLayoutControlAdapterDefs.Create; Result := FdxLayoutControlAdapterDefs; end; function dxGetCenterAreaBounds(const AItemBounds: TRect): TRect; begin Result := AItemBounds; with Result do InflateRect(Result, -(Right - Left) div 4, -(Bottom - Top) div 4); end; function dxGlobalCanvas: TdxCustomizationCanvas; begin if FGlobalCanvas = nil then FGlobalCanvas := TdxCustomizationCanvas.Create; Result := FGlobalCanvas; end; { TdxLayoutOffsets } function TdxLayoutOffsets.GetValue(Index: Integer): Integer; begin case Index of 1: Result := FBottom; 2: Result := FLeft; 3: Result := FRight; 4: Result := FTop; else Result := 0; end; end; procedure TdxLayoutOffsets.SetValue(Index: Integer; Value: Integer); begin if Value < 0 then Value := 0; if GetValue(Index) <> Value then begin case Index of 1: FBottom := Value; 2: FLeft := Value; 3: FRight := Value; 4: FTop := Value; end; Changed; end; end; { TdxCustomLayoutControlHandler } constructor TdxCustomLayoutControlHandler.Create(AControl: TdxCustomLayoutControl); begin inherited Create; FControl := AControl; end; function TdxCustomLayoutControlHandler.GetViewInfo: TdxLayoutControlViewInfo; begin Result := FControl.ViewInfo; end; { TdxCustomLayoutControl } constructor TdxCustomLayoutControl.Create(AOwner: TComponent); begin inherited; ControlStyle := ControlStyle + [csAcceptsControls, csOpaque]; {$IFDEF DELPHI7} ParentBackground := False; {$ENDIF} { with cxLookAndFeel do begin Kind := lfStandard; NativeStyle := True; end; } TabStop := False; Width := 300; Height := 250; FAbsoluteItems := TcxComponentList.Create; FAvailableItems := TcxComponentList.Create; FAvailableItems.OnComponentListChanged := AvailableItemListChanged; FCustomizationControls := TdxSatelliteControls.Create(True); FOptionsStoring := TdxStoringOptions.Create; FStoredStream := TMemoryStream.Create; FAutoControlAlignment := True; FAutoControlTabOrders := True; FHighlightRoot := True; FShowDesignSelectors := True; FBoldFont := TFont.Create; RefreshBoldFont; FCustomizeFormClass := TdxLayoutControlCustomizeForm; GetLayoutLookAndFeel.AddUser(Self); InitializeSubControlsCxLookAndFeel; CreateRootGroup; //FGroups.UseIndent := False; CreateConstraints; FSelectionHelper := dxLayoutSelectionHelperClass.Create(Self); FSelectionHelper.AddSelectionChangedListener(Self); FCustomizeAvailableItemsViewKind := oivkTree; end; destructor TdxCustomLayoutControl.Destroy; begin FSelectionHelper.RemoveSelectionChangedListener(Self); Customization := False; FSelectionHelper := nil; if not IsDesigning then Store; SetRootGroup(nil); LayoutLookAndFeel := nil; GetLayoutLookAndFeel.RemoveUser(Self); DestroyConstraints; dxLayoutTextMetrics.Unregister(FBoldFont); dxLayoutTextMetrics.Unregister(Font); FreeAndNil(FBoldFont); FreeAndNil(FStoredStream); FreeAndNil(FOptionsStoring); FreeAndNil(FCustomizationControls); FAvailableItems.OwnsObjects := True; FreeAndNil(FAvailableItems); FreeAndNil(FAbsoluteItems); inherited; end; procedure TdxCustomLayoutControl.BeginDragAndDrop; begin DragAndDropState := ddsInProcess; inherited; end; function TdxCustomLayoutControl.GetAbsoluteItem(Index: Integer): TdxCustomLayoutItem; begin Result := TdxCustomLayoutItem(FAbsoluteItems[Index]); end; function TdxCustomLayoutControl.GetAbsoluteItemCount: Integer; begin Result := FAbsoluteItems.Count; end; function TdxCustomLayoutControl.GetAlignmentConstraint(Index: Integer): TdxLayoutAlignmentConstraint; begin Result := FAlignmentConstraints[Index]; end; function TdxCustomLayoutControl.GetAlignmentConstraintCount: Integer; begin Result := FAlignmentConstraints.Count; end; function TdxCustomLayoutControl.GetAllowDrop: Boolean; begin Result := IsDesigning; end; function TdxCustomLayoutControl.GetAvailableItem(Index: Integer): TdxCustomLayoutItem; begin Result := TdxCustomLayoutItem(FAvailableItems[Index]); end; function TdxCustomLayoutControl.GetAvailableItemCount: Integer; begin Result := FAvailableItems.Count; end; function TdxCustomLayoutControl.GetContentBounds: TRect; begin Result := ViewInfo.ContentBounds; end; function TdxCustomLayoutControl.GetOccupiedClientWidth: Integer; begin Result := ViewInfo.ItemsViewInfo.CalculateWidth; end; function TdxCustomLayoutControl.GetOccupiedClientHeight: Integer; begin Result := ViewInfo.ItemsViewInfo.CalculateHeight; end; function TdxCustomLayoutControl.GetSelectedControlCount: Integer; var AList: TList; begin AList := TList.Create; try GetSelection(AList); Result := AList.Count; finally AList.Free; end; end; function TdxCustomLayoutControl.GetLayoutDirection: TdxLayoutDirection; begin Result := FRootGroup.LayoutDirection; end; function TdxCustomLayoutControl.GetAutoContentSizes: TdxLayoutAutoContentSizes; begin Result := TdxLayoutAutoContentSizes(FRootGroup.AutoAligns); end; procedure TdxCustomLayoutControl.SetAutoContentSizes(Value: TdxLayoutAutoContentSizes); begin FRootGroup.AutoAligns := TdxLayoutAutoAligns(Value); end; procedure TdxCustomLayoutControl.SetAutoControlAlignment(Value: Boolean); begin if FAutoControlAlignment <> Value then begin FAutoControlAlignment := Value; LayoutChanged; end; end; procedure TdxCustomLayoutControl.SetAutoControlTabOrders(Value: Boolean); begin if FAutoControlTabOrders <> Value then begin FAutoControlTabOrders := Value; LayoutChanged; end; end; procedure TdxCustomLayoutControl.SetCustomization(Value: Boolean); begin if (FCustomization <> Value) and (not Value or HandleAllocated) then begin if Value then begin FCustomizeForm := TdxLayoutControlCustomizeFormClass(CustomizeFormClass).Create(nil); TdxLayoutControlCustomizeForm(FCustomizeForm).Control := Self; FCustomizeForm.Show; FCustomization := True; UpdateCustomizationControls; end else begin FCustomization := False; with FCustomizeForm do if not (csDestroying in ComponentState) then Free; if not IsDesigning then FSelectionHelper.ClearSelection; if not IsDesigning then FSelectionHelper.ClearSelection; FCustomizationControls.Clear; end; LayoutChanged; DoCustomization; end else if FCustomization and HandleAllocated then FCustomizeForm.BringToFront; end; procedure TdxCustomLayoutControl.SetCustomizeAvailableItemsViewKind(Value: TdxLayoutAvailableItemsViewKind); begin if FCustomizeAvailableItemsViewKind <> Value then begin FCustomizeAvailableItemsViewKind := Value; CustomizeFormUpdate([cfutContent, cfutSelection]); end; end; procedure TdxCustomLayoutControl.SetCustomizeFormTabbedView(Value: Boolean); begin if FCustomizeFormTabbedView <> Value then begin FCustomizeFormTabbedView := Value; CustomizeFormUpdate([cfutContent, cfutSelection]); end; end; procedure TdxCustomLayoutControl.SetShowDesignSelectors(Value: Boolean); begin if FShowDesignSelectors <> Value then begin FShowDesignSelectors := Value; InvalidateWithChildren; CustomizeFormUpdate([cfutContent, cfutSelection]); end; end; procedure TdxCustomLayoutControl.SetHighlightRoot(Value: Boolean); begin if FHighlightRoot <> Value then begin FHighlightRoot := Value; LayoutChanged(False); end; end; procedure TdxCustomLayoutControl.SetIsPlaceControlsNeeded(Value: Boolean); begin if FIsPlaceControlsNeeded <> Value then begin FIsPlaceControlsNeeded := Value; if Value then PlaceControls(nil); end; end; procedure TdxCustomLayoutControl.SetRootGroup(Value: TdxLayoutGroup); begin ItemWithMouse := nil; DestroyHandlers; if Value <> nil then begin if FRootGroup <> nil then begin Value.FAlignHorz := FRootGroup.AlignHorz; Value.FAlignVert := FRootGroup.AlignVert; end else begin Value.FAlignHorz := ahLeft; Value.FAlignVert := avTop; end; end; if IsDestroying or ((FRootGroup <> nil) and not FRootGroup.IsDestroying) then FRootGroup.Free; FRootGroup := Value; if Value = nil then Exit; FRootGroup.Container := Self; CreateHandlers; FRootGroup.Hidden := True; end; procedure TdxCustomLayoutControl.SetItemWithMouse(Value: TdxCustomLayoutItem); begin if FItemWithMouse <> Value then begin if FItemWithMouse <> nil then FItemWithMouse.MouseLeave; FItemWithMouse := Value; if FItemWithMouse <> nil then FItemWithMouse.MouseEnter; end; end; procedure TdxCustomLayoutControl.SetLayoutDirection(Value: TdxLayoutDirection); begin FRootGroup.LayoutDirection := Value; end; procedure TdxCustomLayoutControl.SetLeftPos(Value: Integer); var APrevLeftPos: Integer; begin CheckLeftPos(Value); if FLeftPos <> Value then begin Update; APrevLeftPos := FLeftPos; FLeftPos := Value; LayoutChanged; ScrollContent(APrevLeftPos, FLeftPos, True); end; end; procedure TdxCustomLayoutControl.SetLayoutLookAndFeel(Value: TdxCustomLayoutLookAndFeel); begin if FLayoutLookAndFeel <> Value then begin GetLayoutLookAndFeel.RemoveUser(Self); FLayoutLookAndFeel := Value; GetLayoutLookAndFeel.AddUser(Self); LayoutLookAndFeelUserChanged; end; end; procedure TdxCustomLayoutControl.SetShowHiddenGroupsBounds(Value: Boolean); begin if FShowHiddenGroupsBounds <> Value then begin FShowHiddenGroupsBounds := Value; LayoutChanged; end; end; procedure TdxCustomLayoutControl.SetTopPos(Value: Integer); var APrevTopPos: Integer; begin CheckTopPos(Value); if FTopPos <> Value then begin Update; APrevTopPos := FTopPos; FTopPos := Value; LayoutChanged; ScrollContent(APrevTopPos, FTopPos, False); end; end; function TdxCustomLayoutControl.GetIniFileName: string; begin Result := OptionsStoring.IniFileName; end; function TdxCustomLayoutControl.GetRegistryPath: string; begin Result := OptionsStoring.RegistryPath; end; function TdxCustomLayoutControl.GetStoreInIniFile: Boolean; begin Result := OptionsStoring.StoreToIniFile; end; function TdxCustomLayoutControl.GetStoreInRegistry: Boolean; begin Result := OptionsStoring.StoreToRegistry; end; procedure TdxCustomLayoutControl.SetIniFileName(const Value: string); begin OptionsStoring.IniFileName := Value; end; procedure TdxCustomLayoutControl.SetRegistryPath(const Value: string); begin OptionsStoring.RegistryPath := Value; end; procedure TdxCustomLayoutControl.SetStoreInIniFile(const Value: Boolean); begin OptionsStoring.StoreToIniFile := Value; end; procedure TdxCustomLayoutControl.SetStoreInRegistry(const Value: Boolean); begin OptionsStoring.StoreToRegistry := Value; end; procedure TdxCustomLayoutControl.SetOptionsStoring(Value: TdxStoringOptions); begin FOptionsStoring.Assign(Value); end; procedure TdxCustomLayoutControl.CreateHandlers; begin FPainter := GetPainterClass.Create(Self); FViewInfo := GetViewInfoClass.Create(Self); end; procedure TdxCustomLayoutControl.DestroyHandlers; begin FreeAndNil(FViewInfo); FreeAndNil(FPainter); end; procedure TdxCustomLayoutControl.CreateConstraints; begin FAlignmentConstraints := TList.Create; end; procedure TdxCustomLayoutControl.DestroyConstraints; var I: Integer; begin for I := AlignmentConstraintCount - 1 downto 0 do AlignmentConstraints[I].Free; FreeAndNil(FAlignmentConstraints); end; procedure TdxCustomLayoutControl.AddAlignmentConstraint(AConstraint: TdxLayoutAlignmentConstraint); begin FAlignmentConstraints.Add(AConstraint); AConstraint.FControl := Self; SetComponentName(AConstraint, Name + 'AlignmentConstraint', IsDesigning, IsLoading); end; procedure TdxCustomLayoutControl.RemoveAlignmentConstraint(AConstraint: TdxLayoutAlignmentConstraint); begin FAlignmentConstraints.Remove(AConstraint); AConstraint.FControl := nil; end; procedure TdxCustomLayoutControl.RefreshBoldFont; begin FBoldFont.Assign(Font); with FBoldFont do Style := Style + [fsBold]; dxLayoutTextMetrics.Unregister(FBoldFont); end; procedure TdxCustomLayoutControl.InitializeSubControlsCxLookAndFeel; begin GetLayoutLookAndFeel.InitializeSubControlCxLookAndFeel(HScrollBar.LookAndFeel); GetLayoutLookAndFeel.InitializeSubControlCxLookAndFeel(VScrollBar.LookAndFeel); GetLayoutLookAndFeel.InitializeSubControlCxLookAndFeel(SizeGrip.LookAndFeel); end; procedure TdxCustomLayoutControl.PlaceControls(AItemViewInfo: TdxCustomLayoutItemViewInfo); begin if AItemViewInfo <> nil then begin IsPlaceControlsNeeded := False; Painter.PlaceControls(AItemViewInfo); end else if TdxCustomLayoutLookAndFeelAccess(GetLayoutLookAndFeel).ForceControlArrangement then SendMessage(Handle, DXM_PLACECONTROLS, 0, 0) else PostMessage(Handle, DXM_PLACECONTROLS, 0, 0); end; procedure TdxCustomLayoutControl.AddAbsoluteItem(AItem: TdxCustomLayoutItem); begin FAbsoluteItems.Add(AItem); end; procedure TdxCustomLayoutControl.ExtractAbsoluteItem(AItem: TdxCustomLayoutItem); begin FAbsoluteItems.Extract(AItem); end; procedure TdxCustomLayoutControl.AddAvailableItem(AItem: TdxCustomLayoutItem); begin FAvailableItems.Add(AItem); AItem.Container := Self; end; procedure TdxCustomLayoutControl.ExtractAvailableItem(AItem: TdxCustomLayoutItem); begin FAvailableItems.Extract(AItem); end; procedure TdxCustomLayoutControl.WMNCDestroy(var Message: TWMNCDestroy); begin IsPlaceControlsNeeded := False; inherited; end; {$IFNDEF DELPHI7} procedure TdxCustomLayoutControl.WMPrintClient(var Message: TWMPrintClient); begin with Message do if Result <> 1 then if ((Flags and PRF_CHECKVISIBLE) = 0) or Visible then PaintHandler(TWMPaint(Message)) else inherited else inherited; end; {$ENDIF} procedure TdxCustomLayoutControl.CMControlChange(var Message: TCMControlChange); var AControl: TControl; P: TPoint; AGroup: TdxLayoutGroup; AIndex: Integer; begin inherited; if not (IsLoading or IsDestroying) then begin AControl := Message.Control; if Message.Inserting then begin if (csAncestor in AControl.ComponentState) or IsInternalControl(AControl) or (FindItem(AControl) <> nil) then Exit; P := AControl.BoundsRect.TopLeft; AGroup := ViewInfo.GetHitTest(P).GetGroupForInsert; if AGroup = nil then AGroup := Items; CustomizeFormBeginUpdate; try AIndex := AGroup.ViewInfo.GetInsertionPos(P); AGroup.CreateItemForControl(AControl).VisibleIndex := AIndex; finally CustomizeFormEndUpdate; end; end // #DG else // #DG FindItem(AControl).Free; end; end; procedure TdxCustomLayoutControl.CMDialogChar(var Message: TCMDialogChar); begin if FRootGroup.ProcessDialogChar(Message.CharCode) then Message.Result := 1 else inherited; end; { procedure TdxCustomLayoutControl.CMFreeItem(var Message: TMessage); begin TObject(Message.WParam).Free; end; } procedure TdxCustomLayoutControl.DXMPlaceControls(var Message: TMessage); begin IsPlaceControlsNeeded := False; Painter.PlaceControls(ViewInfo.ItemsViewInfo); end; procedure TdxCustomLayoutControl.DXMBuildSelectionLayer(var Message: TMessage); begin if not IsUpdateLocked and (ViewInfo <> nil) then ViewInfo.BuildSelectionLayer; end; function TdxCustomLayoutControl.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; begin if IsDesigning then Result := False else begin Result := True; if (ViewInfo.ItemsViewInfo.AlignHorz <> ahClient) and (Align in [alNone, alLeft, alRight]) then NewWidth := cxRectWidth(ContentBounds); if (ViewInfo.ItemsViewInfo.AlignVert <> avClient) and (Align in [alNone, alTop, alBottom]) then NewHeight := cxRectHeight(ContentBounds); end; end; procedure TdxCustomLayoutControl.AlignControls(AControl: TControl; var Rect: TRect); begin end; function TdxCustomLayoutControl.AllowAutoDragAndDropAtDesignTime(X, Y: Integer; Shift: TShiftState): Boolean; begin Result := not GetDesignHitTest(X, Y, Shift); end; function TdxCustomLayoutControl.AllowDragAndDropWithoutFocus: Boolean; begin Result := FCustomization; end; procedure TdxCustomLayoutControl.BoundsChanged; begin LayoutChanged; inherited; end; function TdxCustomLayoutControl.CanDrag(X, Y: Integer): Boolean; begin Result := inherited CanDrag(X, Y) and not IsDesigning; end; function TdxCustomLayoutControl.CanFocusOnClick(X, Y: Integer): Boolean; begin Result := inherited CanFocusOnClick(X, Y) and not IsCustomization; if ItemWithMouse <> nil then Result := Result and not ItemWithMouse.CanFocusOnClick(X, Y); end; procedure TdxCustomLayoutControl.CreateParams(var Params: TCreateParams); begin inherited; with Params do WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW); end; procedure TdxCustomLayoutControl.DblClick; begin inherited; if IsDesigning then Customization := True; end; procedure TdxCustomLayoutControl.FontChanged; begin inherited; dxLayoutTextMetrics.Unregister(Font); RefreshBoldFont; LayoutLookAndFeelUserChanged; end; procedure TdxCustomLayoutControl.GetChildren(Proc: TGetChildProc; Root: TComponent); var I: Integer; begin inherited; if Owner = Root then begin Proc(FRootGroup); for I := 0 to AvailableItemCount - 1 do Proc(AvailableItems[I]); for I := 0 to AlignmentConstraintCount - 1 do Proc(AlignmentConstraints[I]); end; end; function TdxCustomLayoutControl.GetCursor(X, Y: Integer): TCursor; var AHitTest: TdxCustomLayoutHitTest; begin AHitTest := ViewInfo.GetHitTest(X, Y); if AHitTest is TdxCustomLayoutItemHitTest then Result := TdxCustomLayoutItemHitTest(AHitTest).Item.GetCursor(X, Y) else Result := crDefault; if Result = crDefault then Result := inherited GetCursor(X, Y); end; function TdxCustomLayoutControl.GetDesignHitTest(X, Y: Integer; Shift: TShiftState): Boolean; function IsGrabHandle(AHandle: THandle): Boolean; const GrabHandleClassName = 'TGrabHandle'; begin Result := cxGetClassName(AHandle) = GrabHandleClassName; end; var AHitTest: TdxCustomLayoutHitTest; begin Result := inherited GetDesignHitTest(X, Y, Shift); if not Result then begin AHitTest := ViewInfo.GetHitTest(X, Y); Result := not (ssRight in Shift) and not FRightButtonPressed and (AHitTest is TdxCustomLayoutItemHitTest) and not IsToolSelected and not IsGrabHandle(cxWindowFromPoint(ClientToScreen(Point(X, Y)))); end; FRightButtonPressed := ssRight in Shift; end; function TdxCustomLayoutControl.HasBackground: Boolean; begin Result := {$IFDEF DELPHI7}ThemeServices.ThemesEnabled and ParentBackground{$ELSE}inherited HasBackground{$ENDIF}; end; function TdxCustomLayoutControl.IsInternalControl(AControl: TControl): Boolean; begin Result := inherited IsInternalControl(AControl) or (AControl is TdxLayoutTabbedGroupTabControl); end; procedure TdxCustomLayoutControl.Loaded; begin inherited; if not IsDesigning then Restore; LayoutChanged; end; procedure TdxCustomLayoutControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin AssignItemWithMouse(X, Y); inherited; if ItemWithMouse <> nil then ItemWithMouse.MouseDown(Button, Shift, X, Y); end; procedure TdxCustomLayoutControl.MouseLeave(AControl: TControl); begin inherited; ItemWithMouse := nil; end; procedure TdxCustomLayoutControl.MouseMove(Shift: TShiftState; X, Y: Integer); begin AssignItemWithMouse(X, Y); if ItemWithMouse <> nil then ItemWithMouse.MouseMove(Shift, X, Y); inherited; end; procedure TdxCustomLayoutControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited; AssignItemWithMouse(X, Y); if ItemWithMouse <> nil then ItemWithMouse.MouseUp(Button, Shift, X, Y); end; procedure TdxCustomLayoutControl.Paint; begin if not IsUpdateLocked then begin inherited; Painter.Paint; end; end; procedure TdxCustomLayoutControl.SetName(const Value: TComponentName); function GetItem(ACaller: TComponent; Index: Integer): TComponent; begin if Index = 0 then Result := TdxCustomLayoutControl(ACaller).Items else Result := TdxCustomLayoutControl(ACaller).AbsoluteItems[Index - 1]; end; function GetAlignmentConstraint(ACaller: TComponent; Index: Integer): TComponent; begin Result := TdxCustomLayoutControl(ACaller).AlignmentConstraints[Index]; end; var AOldName: string; begin AOldName := Name; inherited; RenameComponents(Self, Owner, Name, AOldName, 1 + AbsoluteItemCount, @GetItem); RenameComponents(Self, Owner, Name, AOldName, AlignmentConstraintCount, @GetAlignmentConstraint); CustomizeFormUpdate([cfutCaption, cfutContent]); end; {$IFDEF DELPHI7} procedure TdxCustomLayoutControl.SetParentBackground(Value: Boolean); begin if Value then ControlStyle := ControlStyle - [csOpaque] else ControlStyle := ControlStyle + [csOpaque]; inherited; end; {$ENDIF} procedure TdxCustomLayoutControl.WriteState(Writer: TWriter); begin if HandleAllocated then SendMessage(Handle, WM_SETREDRAW, 0, 0); try Items.RestoreItemControlSize; inherited; finally if HandleAllocated then SendMessage(Handle, WM_SETREDRAW, 1, 0); LayoutChanged; end; end; procedure TdxCustomLayoutControl.WndProc(var Message: TMessage); var AControl: TControl; P: TPoint; AHitTest: TdxCustomLayoutHitTest; begin if (IsDesigning or Customization) and HandleAllocated then case Message.Msg of WM_LBUTTONDOWN: if GetCapture <> Handle then begin P := SmallPointToPoint(TWMMouse(Message).Pos); AControl := ControlAtPos(P, True); if (AControl <> nil) and not (AControl is TWinControl) then begin AHitTest := ViewInfo.GetHitTest(P); if Customization or ((AHitTest <> nil) and (AHitTest is TdxLayoutItemHitTest) and (AHitTest as TdxLayoutItemHitTest).Item.ViewInfo.PtInDesignSelectorRect(P)) then SetCaptureControl(Self); end; end; end; inherited WndProc(Message); end; procedure TdxCustomLayoutControl.InitScrollBarsParameters; begin inherited; SetScrollBarInfo(sbHorizontal, 0, ViewInfo.ContentWidth - 1, ScrollStep, ViewInfo.ClientWidth, LeftPos, True, True); SetScrollBarInfo(sbVertical, 0, ViewInfo.ContentHeight - 1, ScrollStep, ViewInfo.ClientHeight, TopPos, True, True); end; function TdxCustomLayoutControl.NeedsToBringInternalControlsToFront: Boolean; begin Result := True; end; procedure TdxCustomLayoutControl.Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); function GetContentPos: Integer; begin if AScrollBarKind = sbHorizontal then Result := LeftPos else Result := TopPos; end; procedure SetContentPos(Value: Integer); begin if AScrollBarKind = sbHorizontal then LeftPos := Value else TopPos := Value; end; function GetPageScrollStep: Integer; begin if AScrollBarKind = sbHorizontal then Result := ClientWidth else Result := ClientHeight; end; begin inherited; case AScrollCode of scLineUp: SetContentPos(GetContentPos - ScrollStep); scLineDown: SetContentPos(GetContentPos + ScrollStep); scPageUp: SetContentPos(GetContentPos - GetPageScrollStep); scPageDown: SetContentPos(GetContentPos + GetPageScrollStep); scTrack: SetContentPos(AScrollPos); end; AScrollPos := GetContentPos; end; function TdxCustomLayoutControl.CanDragAndDrop: Boolean; begin Result := not IsDesigning or not (csInline in Owner.ComponentState); end; function TdxCustomLayoutControl.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; begin Result := TdxLayoutControlDragAndDropObject; end; function TdxCustomLayoutControl.StartDragAndDrop(const P: TPoint): Boolean; var AHitTest: TdxCustomLayoutHitTest; AItem: TdxCustomLayoutItem; begin Result := False; if IsCustomization and CanDragAndDrop then begin AHitTest := ViewInfo.GetHitTest(P); if AHitTest is TdxCustomLayoutItemHitTest then begin AItem := TdxCustomLayoutItemHitTest(AHitTest).Item; if not AItem.IsRoot then begin (DragAndDropObject as TdxLayoutControlDragAndDropObject).Init(dsControl, AItem); Result := True; end end; end; end; function TdxCustomLayoutControl.GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin Result := FLayoutLookAndFeel; if Result = nil then Result := dxLayoutDefaultLookAndFeel; end; function TdxCustomLayoutControl.GetCxLookAndFeel: TcxLookAndFeel; begin Result := inherited LookAndFeel; end; procedure TdxCustomLayoutControl.BeginLayoutLookAndFeelUserDestroying; begin BeginUpdate; end; procedure TdxCustomLayoutControl.EndLayoutLookAndFeelUserDestroying; begin EndUpdate; end; procedure TdxCustomLayoutControl.LayoutLookAndFeelUserChanged; begin if (LayoutLookAndFeel <> nil) and not DoubleBuffered then DoubleBuffered := LayoutLookAndFeel.NeedDoubleBuffered; if (FRootGroup <> nil) and (GetLayoutLookAndFeel <> nil) then FRootGroup.LayoutLookAndFeelUserChanged; InitializeSubControlsCxLookAndFeel; end; procedure TdxCustomLayoutControl.LayoutLookAndFeelUserDestroyed; begin LayoutLookAndFeel := nil; end; procedure TdxCustomLayoutControl.SelectionChanged; begin Items.SelectionChanged; end; function TdxCustomLayoutControl.GetPainterClass: TdxLayoutControlPainterClass; begin Result := TdxLayoutControlPainter; end; function TdxCustomLayoutControl.GetViewInfoClass: TdxLayoutControlViewInfoClass; begin Result := TdxLayoutControlViewInfo; end; procedure TdxCustomLayoutControl.AssignItemWithMouse(X, Y: Integer); begin ItemWithMouse := ViewInfo.GetItemWithMouse(Point(X, Y)); end; procedure TdxCustomLayoutControl.AvailableItemListChanged(Sender: TObject; AComponent: TComponent; AAction: TcxComponentCollectionNotification); begin CustomizeFormUpdate([cfutContent, cfutSelection]); end; procedure TdxCustomLayoutControl.UpdateCustomizationControls; var I: Integer; AItem: TdxLayoutItem; begin FCustomizationControls.Clear; for I := 0 to AbsoluteItemCount - 1 do begin if AbsoluteItems[I] is TdxLayoutItem then begin AItem := TdxLayoutItem(AbsoluteItems[I]); if AItem.HasWinControl then TdxSatelliteControls(FCustomizationControls).AddControl(TWinControl(AItem.Control), TdxCustomizationControlItem); end; end; end; function TdxCustomLayoutControl.CalculateCustomizeFormBounds(const AFormBounds: TRect): TRect; var AControlBounds, ADesktopBounds: TRect; begin AControlBounds := BoundsRect; MapWindowPoints(Parent.Handle, 0, AControlBounds, 2); ADesktopBounds := GetDesktopWorkArea(AControlBounds.TopLeft); Result := AFormBounds; with AControlBounds do begin if (ADesktopBounds.Right - Right >= Result.Right - Result.Left) or (ADesktopBounds.Right - Right >= Left - ADesktopBounds.Left) then OffsetRect(Result, Right - Result.Left, 0) else OffsetRect(Result, Left - Result.Right, 0); OffsetRect(Result, 0, (Top + Bottom - (Result.Bottom - Result.Top)) div 2 - Result.Top); end; with ADesktopBounds do begin if Result.Left < Left then OffsetRect(Result, Left - Result.Left, 0); if Result.Right > Right then OffsetRect(Result, Right - Result.Right, 0); if Result.Top < Top then OffsetRect(Result, 0, Top - Result.Top); end; end; function TdxCustomLayoutControl.CanMultiSelect: Boolean; begin Result := True; end; function TdxCustomLayoutControl.CanShowSelection: Boolean; begin Result := {$IFDEF DELPHI6}True{$ELSE}CanMultiSelect{$ENDIF}; end; procedure TdxCustomLayoutControl.PostBuildSelectionLayer; begin if HandleAllocated then PostMessage(Handle, DXM_BUILDSELECTIONLAYER, 0, 0); end; procedure TdxCustomLayoutControl.CheckLeftPos(var Value: Integer); begin Value := Max(Min(Value, ViewInfo.ContentWidth - ViewInfo.ClientWidth), 0); end; procedure TdxCustomLayoutControl.CheckPositions; begin LeftPos := LeftPos; TopPos := TopPos; end; procedure TdxCustomLayoutControl.CheckTopPos(var Value: Integer); begin Value := Max(Min(Value, ViewInfo.ContentHeight - ViewInfo.ClientHeight), 0); end; procedure TdxCustomLayoutControl.CustomizeFormBeginUpdate; begin Inc(FCustomizeFormUpdateLockCount); end; procedure TdxCustomLayoutControl.CustomizeFormCancelUpdate; begin Dec(FCustomizeFormUpdateLockCount); end; procedure TdxCustomLayoutControl.CustomizeFormEndUpdate; begin Dec(FCustomizeFormUpdateLockCount); CustomizeFormUpdate([cfutCaption, cfutContent, cfutSelection]); end; procedure TdxCustomLayoutControl.CustomizeFormUpdate( AUpdateTypes: TdxLayoutCustomizeFormUpdateTypes); begin if not Customization or IsUpdateLocked or (FCustomizeFormUpdateLockCount <> 0) or (csDestroying in FCustomizeForm.ComponentState) then Exit; if cfutCaption in AUpdateTypes then TdxLayoutControlCustomizeForm(CustomizeForm).UpdateCaption; if cfutContent in AUpdateTypes then TdxLayoutControlCustomizeForm(CustomizeForm).UpdateContent; if cfutSelection in AUpdateTypes then TdxLayoutControlCustomizeForm(CustomizeForm).UpdateSelection; end; procedure TdxCustomLayoutControl.DoCustomization; begin CallNotify(FOnCustomization, Self); end; procedure TdxCustomLayoutControl.DragAndDropBegan; begin // todo: remove end; function TdxCustomLayoutControl.GetAlignmentConstraintClass: TdxLayoutAlignmentConstraintClass; begin Result := TdxLayoutAlignmentConstraint; end; function TdxCustomLayoutControl.GetDefaultGroupClass: TdxLayoutGroupClass; begin Result := TdxLayoutGroup; end; function TdxCustomLayoutControl.GetDefaultItemClass: TdxLayoutItemClass; begin Result := TdxLayoutItem; end; function TdxCustomLayoutControl.GetDesignSelectorRect: TRect; const Offset = 3; Width = 16; begin with ClientBounds do Result := Rect(Right - Width - Offset, Bottom - Width - Offset, Right - Offset, Bottom - Offset); end; function TdxCustomLayoutControl.IsCustomization: Boolean; begin Result := Customization or IsDesigning; end; function TdxCustomLayoutControl.IsToolSelected: Boolean; begin Result := IsDesigning and (dxLayoutDesignTimeHelper <> nil) and dxLayoutDesignTimeHelper.IsToolSelected; end; function TdxCustomLayoutControl.IsUpdateLocked: Boolean; begin Result := FUpdateLockCount <> 0; end; procedure TdxCustomLayoutControl.LayoutChanged(ANeedPack: Boolean = True); procedure BeforeCalculateViewInfo; var I: Integer; begin Items.BeforeCalculateViewInfo; for I := 0 to AvailableItemCount - 1 do AvailableItems[I].BeforeCalculateViewInfo; end; procedure AfterCalculateViewInfo; var I: Integer; begin Items.AfterCalculateViewInfo; for I := 0 to AvailableItemCount - 1 do AvailableItems[I].AfterCalculateViewInfo; end; begin if not IsDestroying and not IsLoading and not IsUpdateLocked then begin BeginUpdate; try if ANeedPack then Items.Pack; BeforeCalculateViewInfo; ViewInfo.Calculate; AfterCalculateViewInfo; finally CancelUpdate; end; CustomizeFormUpdate([cfutContent, cfutSelection]); AdjustSize; {$IFDEF DELPHI12} TControlAccess(Parent).AdjustSize; // bug in D12 {$ENDIF} UpdateScrollBars; Invalidate; PostBuildSelectionLayer; end; end; procedure TdxCustomLayoutControl.CreateRootGroup; begin SetRootGroup(GetDefaultGroupClass.Create(Owner{nil})); end; {procedure TdxCustomLayoutControl.PostFree(AObject: TObject); begin if HandleAllocated then PostMessage(Handle, CM_FREEITEM, WParam(AObject), 0); end;} procedure TdxCustomLayoutControl.ScrollContent(APrevPos, ACurPos: Integer; AHorzScrolling: Boolean); var ADelta: Integer; AScrollBounds: TRect; begin if not HandleAllocated then Exit; ADelta := -(ACurPos - APrevPos); AScrollBounds := ViewInfo.ClientBounds; //ValidateRect(Handle, @AScrollBounds); ScrollWindowEx(Handle, Ord(AHorzScrolling) * ADelta, Ord(not AHorzScrolling) * ADelta, @AScrollBounds, nil, 0, nil, SW_INVALIDATE or SW_ERASE{ or SW_SCROLLCHILDREN bug in WinAPI}); UpdateWindow(Handle); end; type PdxLayoutItemPosition = ^TdxLayoutItemPosition; TdxLayoutItemPosition = record Item: TdxCustomLayoutItem; ParentName: string; Index: Integer; end; function ComparePositions(Item1, Item2: Pointer): Integer; begin Result := PdxLayoutItemPosition(Item1).Index - PdxLayoutItemPosition(Item2).Index; end; procedure TdxCustomLayoutControl.LoadFromCustomIniFile(AIniFile: TCustomIniFile; const ARootSection: string); var AItems: TList; APositions: TList; AItemCount, I: Integer; function CreateItemsList: TList; begin Result := TList.Create; Result.Count := AbsoluteItemCount; Move(FAbsoluteItems.List^, Result.List^, Result.Count * SizeOf(Pointer)); end; procedure PrepareItems; var I: Integer; begin for I := 0 to AbsoluteItemCount - 1 do AbsoluteItems[I].Parent := nil; end; function GetItemSection(AIndex: Integer): string; begin Result := 'Item' + IntToStr(AIndex); if ARootSection <> '' then Result := ARootSection + '\' + Result; end; procedure AddPosition(AItem: TdxCustomLayoutItem; const AParentName: string; AIndex: Integer); var APosition: PdxLayoutItemPosition; begin New(APosition); with APosition^ do begin Item := AItem; ParentName := AParentName; Index := AIndex; end; APositions.Add(APosition); end; procedure LoadItem(const ASection: string); var AName, AParentName: string; AItem: TdxCustomLayoutItem; AIndex: Integer; AGroup: TdxLayoutGroup; begin AName := AIniFile.ReadString(ASection, 'Name', ''); if AName = '' then Exit; AItem := FindItem(AName); AItems.Remove(AItem); if AItem = nil then begin AItem := CreateGroup; AItem.Name := AName; end; AParentName := AIniFile.ReadString(ASection, 'ParentName', ''); AIndex := AIniFile.ReadInteger(ASection, 'Index', -1); AddPosition(AItem, AParentName, AIndex); if AItem is TdxLayoutGroup then begin AGroup := TdxLayoutGroup(AItem); AGroup.Hidden := AIniFile.ReadBool(ASection, 'Hidden', False); AGroup.LayoutDirection := TdxLayoutDirection(AIniFile.ReadInteger(ASection, 'LayoutDirection', 0)); if AGroup.IsUserDefined and not AGroup.Hidden then AGroup.Caption := AIniFile.ReadString(ASection, 'Caption', ''); end; end; procedure DestroyNonLoadedItems; var I: Integer; function CanDestroy(AItem: TdxCustomLayoutItem): Boolean; function ItemExists(AItem: Pointer): Boolean; var I: Integer; begin for I := 0 to AbsoluteItemCount - 1 do begin Result := AbsoluteItems[I] = AItem; if Result then Exit; end; Result := False; end; begin Result := ItemExists(AItem) and (AItem is TdxLayoutGroup) and TdxLayoutGroup(AItem).CanDestroy; end; begin for I := 0 to AItems.Count - 1 do if CanDestroy(AItems[I]) then TObject(AItems[I]).Free; end; procedure UpdatePositions; var I: Integer; APosition: PdxLayoutItemPosition; begin APositions.Sort(ComparePositions); for I := 0 to APositions.Count - 1 do begin APosition := PdxLayoutItemPosition(APositions[I]); with APosition^ do begin Item.Parent := FindItem(ParentName) as TdxLayoutGroup; Item.Index := Index; end; end; end; begin AItems := CreateItemsList; APositions := TList.Create; try AItemCount := AIniFile.ReadInteger(ARootSection, 'ItemCount', -1); if AItemCount = -1 then Exit; BeginUpdate; try PrepareItems; for I := 0 to AItemCount - 1 do LoadItem(GetItemSection(I)); DestroyNonLoadedItems; UpdatePositions; finally EndUpdate; end; finally for I := 0 to APositions.Count - 1 do Dispose(PdxLayoutItemPosition(APositions[I])); APositions.Free; AItems.Free; end; end; function CompareItemsByIsUserDefined(Item1, Item2: Pointer): Integer; var AItem1, AItem2: TdxCustomLayoutItem; begin AItem1 := TdxCustomLayoutItem(Item1); AItem2 := TdxCustomLayoutItem(Item2); if (AItem1 is TdxLayoutGroup) and (AItem2 is TdxLayoutGroup) then Result := Ord(TdxLayoutGroup(AItem2).IsUserDefined) - Ord(TdxLayoutGroup(AItem1).IsUserDefined) else Result := Ord(AItem2 is TdxLayoutGroup) - Ord(AItem1 is TdxLayoutGroup); if Result = 0 then Result := Integer(Item1) - Integer(Item2); end; procedure TdxCustomLayoutControl.SaveToCustomIniFile(AIniFile: TCustomIniFile; const ARootSection: string); var AItems: TList; I: Integer; function CreateItemsList: TList; begin Result := TList.Create; Result.Count := AbsoluteItemCount; Move(FAbsoluteItems.List^, Result.List^, Result.Count * SizeOf(Pointer)); Result.Sort(CompareItemsByIsUserDefined); Result.Insert(0, Items); end; function GetItemSection(AIndex: Integer): string; begin Result := 'Item' + IntToStr(AIndex); if ARootSection <> '' then Result := ARootSection + '\' + Result; end; procedure DeletePrevSettings; var ABaseSectionName: string; ASections: TStringList; I: Integer; begin ABaseSectionName := ARootSection; if ABaseSectionName <> '' then ABaseSectionName := ABaseSectionName + '\'; ASections := TStringList.Create; try AIniFile.ReadSections(ASections); for I := 0 to ASections.Count - 1 do if Copy(ASections[I], 1, Length(ABaseSectionName)) = ABaseSectionName then AIniFile.EraseSection(ASections[I]); finally ASections.Free; end; end; procedure SaveItem(const ASection: string; AItem: TdxCustomLayoutItem); var AGroup: TdxLayoutGroup; function GetParentName: string; begin if AItem.Parent <> nil then Result := AItem.Parent.Name else Result := ''; end; begin AIniFile.WriteString(ASection, 'Name', AItem.Name); AIniFile.WriteString(ASection, 'ParentName', GetParentName); AIniFile.WriteInteger(ASection, 'Index', AItem.Index); if AItem is TdxLayoutGroup then begin AGroup := TdxLayoutGroup(AItem); AIniFile.WriteBool(ASection, 'Hidden', AGroup.Hidden); AIniFile.WriteInteger(ASection, 'LayoutDirection', Integer(AGroup.LayoutDirection)); if AGroup.IsUserDefined and not AGroup.Hidden then AIniFile.WriteString(ASection, 'Caption', AItem.Caption); end; end; begin DeletePrevSettings; AItems := CreateItemsList; try AIniFile.WriteInteger(ARootSection, 'ItemCount', AItems.Count); for I := 0 to AItems.Count - 1 do SaveItem(GetItemSection(I), AItems[I]); finally AItems.Free; end; end; function TdxCustomLayoutControl.CanDeleteComponent(AComponent: TComponent): Boolean; begin Result := (FSelectionHelper <> nil) and FSelectionHelper.CanDeleteComponent(AComponent); end; procedure TdxCustomLayoutControl.ClearSelection; begin if (FSelectionHelper <> nil) then FSelectionHelper.ClearSelection; end; procedure TdxCustomLayoutControl.GetSelection(AList: TList); begin if (FSelectionHelper <> nil) then FSelectionHelper.GetSelection(AList); end; function TdxCustomLayoutControl.IsComponentSelected(AComponent: TPersistent): Boolean; begin Result := (FSelectionHelper <> nil) and FSelectionHelper.IsComponentSelected(AComponent); end; procedure TdxCustomLayoutControl.SelectComponent(AComponent: TPersistent; AShift: TShiftState = []); begin if FSelectionHelper <> nil then FSelectionHelper.SelectComponent(AComponent, AShift); end; procedure TdxCustomLayoutControl.SetSelection(AList: TList); begin if FSelectionHelper <> nil then FSelectionHelper.SetSelection(AList); end; function TdxCustomLayoutControl.UniqueName(const BaseName: string): string; begin if FSelectionHelper <> nil then Result := FSelectionHelper.UniqueName(BaseName); end; //IdxLayoutSelectionChanged procedure TdxCustomLayoutControl.LayoutSelectionChanged(ASelection: TList; AAction: TdxLayoutSelectionAction); begin if not IsDestroying and (AAction in [lsaAdded, lsaChanged]) and not IsUpdateLocked then begin CustomizeFormUpdate([cfutSelection]); if IsDesigning then InvalidateRect(GetDesignSelectorRect, True); ViewInfo.BuildSelectionLayer; end; end; procedure TdxCustomLayoutControl.Clear; var I: Integer; AItem: TdxCustomLayoutItem; begin BeginUpdate; try for I := AbsoluteItemCount - 1 downto 0 do begin AItem := AbsoluteItems[I]; if (AItem is TdxLayoutItem) and (TdxLayoutItem(AItem).Control <> nil) then TdxLayoutItem(AItem).Control.Free; end; while AbsoluteItemCount <> 0 do AbsoluteItems[0].Free; finally EndUpdate; end; end; function TdxCustomLayoutControl.CreateAlignmentConstraint: TdxLayoutAlignmentConstraint; begin Result := GetAlignmentConstraintClass.Create(Owner); AddAlignmentConstraint(Result); end; function TdxCustomLayoutControl.FindItem(AControl: TControl): TdxLayoutItem; var I: Integer; AItem: TdxCustomLayoutItem; begin for I := 0 to AbsoluteItemCount - 1 do begin AItem := AbsoluteItems[I]; if AItem is TdxLayoutItem then begin Result := TdxLayoutItem(AItem); if Result.Control = AControl then Exit; end; end; Result := nil; end; function TdxCustomLayoutControl.FindItem(const AName: string): TdxCustomLayoutItem; var I: Integer; begin if AName <> '' then begin Result := Items; if SameText(Result.Name, AName) then Exit; for I := 0 to AbsoluteItemCount - 1 do begin Result := AbsoluteItems[I]; if SameText(Result.Name, AName) then Exit; end; end; Result := nil; end; function TdxCustomLayoutControl.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; begin Result := ViewInfo.GetHitTest(P); end; function TdxCustomLayoutControl.GetHitTest(X, Y: Integer): TdxCustomLayoutHitTest; begin Result := ViewInfo.GetHitTest(X, Y); end; procedure TdxCustomLayoutControl.BeginUpdate; begin Inc(FUpdateLockCount); end; procedure TdxCustomLayoutControl.CancelUpdate; begin Dec(FUpdateLockCount); end; procedure TdxCustomLayoutControl.EndUpdate(ANeedPack: Boolean = True); begin Dec(FUpdateLockCount); LayoutChanged(ANeedPack); end; function TdxCustomLayoutControl.CreateGroup(AGroupClass: TdxLayoutGroupClass = nil; AParent: TdxLayoutGroup = nil): TdxLayoutGroup; begin if AGroupClass = nil then AGroupClass := GetDefaultGroupClass; Result := TdxLayoutGroup(CreateItem(AGroupClass, AParent)); end; function TdxCustomLayoutControl.CreateItem(AItemClass: TdxCustomLayoutItemClass = nil; AParent: TdxLayoutGroup = nil): TdxCustomLayoutItem; begin if AItemClass = nil then AItemClass := GetDefaultItemClass; Result := AItemClass.Create(Owner); AddAvailableItem(Result); Result.Parent := AParent; Modified; end; function TdxCustomLayoutControl.CreateItemForControl(AControl: TControl; AParent: TdxLayoutGroup = nil): TdxLayoutItem; begin Result := TdxLayoutItem(CreateItem(GetDefaultItemClass, AParent)); Result.Control := AControl; end; function TdxCustomLayoutControl.CanRestore: Boolean; begin Result := OptionsStoring.CanRestoreFromIniFile or OptionsStoring.CanRestoreFromRegistry or (FStoredStream.Size > 0); end; procedure TdxCustomLayoutControl.Restore; begin if not CanRestore then Exit; if OptionsStoring.CanRestoreFromRegistry then LoadFromRegistry(OptionsStoring.RegistryPath) else if OptionsStoring.CanRestoreFromIniFile then LoadFromIniFile(OptionsStoring.IniFileName) else begin FStoredStream.Position := 0; LoadFromStream(FStoredStream); end; end; procedure TdxCustomLayoutControl.Store; begin if OptionsStoring.CanStoreToIniFile then SaveToIniFile(OptionsStoring.IniFileName); if OptionsStoring.CanStoreToRegistry then SaveToRegistry(OptionsStoring.RegistryPath); if not IsDestroying then begin FStoredStream.Clear; SaveToStream(FStoredStream); end; end; procedure TdxCustomLayoutControl.LoadFromIniFile(const AFileName: string); var AIniFile: TMemIniFile; begin if AFileName = '' then Exit; AIniFile := TMemIniFile.Create(AFileName); try LoadFromCustomIniFile(AIniFile, Name); finally AIniFile.Free; end; end; procedure TdxCustomLayoutControl.LoadFromRegistry(const ARegistryPath: string); var AIniFile: TRegistryIniFile; begin if ARegistryPath = '' then Exit; AIniFile := TRegistryIniFile.Create(ARegistryPath); try LoadFromCustomIniFile(AIniFile, ''); finally AIniFile.Free; end; end; procedure TdxCustomLayoutControl.LoadFromStream(AStream: TStream); var AIniFile: TMemIniFile; AStrings: TStringList; begin AIniFile := TMemIniFile.Create(''); AStrings := TStringList.Create; try AStrings.LoadFromStream(AStream); AIniFile.SetStrings(AStrings); LoadFromCustomIniFile(AIniFile, ''); finally AStrings.Free; AIniFile.Free; end; end; procedure TdxCustomLayoutControl.SaveToIniFile(const AFileName: string); var AIniFile: TMemIniFile; begin if AFileName = '' then Exit; AIniFile := TMemIniFile.Create(AFileName); try SaveToCustomIniFile(AIniFile, Name); AIniFile.UpdateFile; finally AIniFile.Free; end; end; procedure TdxCustomLayoutControl.SaveToRegistry(const ARegistryPath: string); var AIniFile: TRegistryIniFile; begin if ARegistryPath = '' then Exit; AIniFile := TRegistryIniFile.Create(ARegistryPath); try SaveToCustomIniFile(AIniFile, ''); finally AIniFile.Free; end; end; procedure TdxCustomLayoutControl.SaveToStream(AStream: TStream); var AIniFile: TMemIniFile; AStrings: TStringList; begin AIniFile := TMemIniFile.Create(''); AStrings := TStringList.Create; try SaveToCustomIniFile(AIniFile, ''); AIniFile.GetStrings(AStrings); AStrings.SaveToStream(AStream); finally AStrings.Free; AIniFile.Free; end; end; { TdxLayoutControlPersistent } constructor TdxLayoutControlPersistent.Create(AControl: TdxCustomLayoutControl); begin inherited Create; FControl := AControl; end; procedure TdxLayoutControlPersistent.Changed; begin end; function TdxLayoutControlPersistent.GetOwner: TPersistent; begin Result := FControl; end; { TdxCustomLayoutItemOptions } constructor TdxCustomLayoutItemOptions.Create(AItem: TdxCustomLayoutItem); begin inherited Create; FItem := AItem; end; procedure TdxCustomLayoutItemOptions.Changed; begin FItem.Changed; end; { TdxCustomLayoutItemCaptionOptions } constructor TdxCustomLayoutItemCaptionOptions.Create(AItem: TdxCustomLayoutItem); begin inherited; FShowAccelChar := True; end; procedure TdxCustomLayoutItemCaptionOptions.SetAlignHorz(Value: TAlignment); begin if FAlignHorz <> Value then begin FAlignHorz := Value; Changed; end; end; procedure TdxCustomLayoutItemCaptionOptions.SetShowAccelChar(Value: Boolean); begin if FShowAccelChar <> Value then begin FShowAccelChar := Value; Changed; end; end; { TdxLayoutGroupHelper } class function TdxLayoutGroupHelper.GetChildItemsAlignHorz: TdxLayoutAlignHorz; begin Result := ahClient; end; class function TdxLayoutGroupHelper.GetChildItemsAlignVert: TdxLayoutAlignVert; begin Result := avClient; end; { TdxLayoutHorizontalGroupHelper } class function TdxLayoutHorizontalGroupHelper.GetChildItemsAlignHorz: TdxLayoutAlignHorz; begin Result := ahLeft; end; class function TdxLayoutHorizontalGroupHelper.GetChildItemsAlignVert: TdxLayoutAlignVert; begin Result := avClient; end; class function TdxLayoutHorizontalGroupHelper.GetOrthogonalDirection: TdxLayoutDirection; begin Result := ldVertical; end; class function TdxLayoutHorizontalGroupHelper.GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; begin Result := TdxLayoutGroupViewInfoHorizontalSpecific; end; { TdxLayoutVerticalGroupHelper } class function TdxLayoutVerticalGroupHelper.GetChildItemsAlignHorz: TdxLayoutAlignHorz; begin Result := ahClient; end; class function TdxLayoutVerticalGroupHelper.GetChildItemsAlignVert: TdxLayoutAlignVert; begin Result := avTop; end; class function TdxLayoutVerticalGroupHelper.GetOrthogonalDirection: TdxLayoutDirection; begin Result := ldHorizontal; end; class function TdxLayoutVerticalGroupHelper.GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; begin Result := TdxLayoutGroupViewInfoVerticalSpecific; end; { TdxLayoutTabbedGroupHelper } class function TdxLayoutTabbedGroupHelper.GetChildItemsAlignHorz: TdxLayoutAlignHorz; begin Result := ahClient; end; class function TdxLayoutTabbedGroupHelper.GetChildItemsAlignVert: TdxLayoutAlignVert; begin Result := avClient; end; class function TdxLayoutTabbedGroupHelper.GetOrthogonalDirection: TdxLayoutDirection; begin Result := ldTabbed; end; class function TdxLayoutTabbedGroupHelper.GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; begin Result := TdxLayoutGroupViewInfoTabbedSpecific; end; { TdxCustomLayoutItem } constructor TdxCustomLayoutItem.Create(AOwner: TComponent); begin inherited; FAllowRemove := True; FAlignHorz := ahParentManaged; FAlignVert := avParentManaged; FCaptionOptions := GetCaptionOptionsClass.Create(Self); FEnabled := True; FOffsets := TdxLayoutOffsets.Create(Self); FShowCaption := True; FVisible := True; end; procedure TdxCustomLayoutItem.BeforeDestruction; begin Container.BeginUpdate; inherited; Container.FinishDragAndDrop(False); AlignmentConstraint := nil; end; destructor TdxCustomLayoutItem.Destroy; var AContainer: TdxCustomLayoutControl; begin HasMouse := False; LayoutLookAndFeel := nil; FreeAndNil(FOffsets); FreeAndNil(FCaptionOptions); AContainer := Container; inherited; AContainer.EndUpdate; end; function TdxCustomLayoutItem.GetRealAlignHorz: TdxLayoutAlignHorz; begin if AlignHorz = ahParentManaged then Result := GetParentManagedAlignHorz else Result := AlignHorz; end; function TdxCustomLayoutItem.GetRealAlignVert: TdxLayoutAlignVert; begin if AlignVert = avParentManaged then Result := GetParentManagedAlignVert else Result := AlignVert; end; function TdxCustomLayoutItem.GetActuallyVisible: Boolean; begin Result := GetVisible and (IsRoot or (FParent <> nil) and FParent.IsChildActuallyVisible(Self)); end; function TdxCustomLayoutItem.GetAlignHorz: TdxLayoutAlignHorz; begin Result := FAlignHorz; end; function TdxCustomLayoutItem.GetAlignVert: TdxLayoutAlignVert; begin Result := FAlignVert; end; function TdxCustomLayoutItem.GetAutoAligns: TdxLayoutAutoAligns; begin Result := []; if AlignHorz = ahParentManaged then Include(Result, aaHorizontal); if AlignVert = avParentManaged then Include(Result, aaVertical); end; function TdxCustomLayoutItem.GetCaptionForCustomizeForm: string; begin if (csDesigning in ComponentState) or (FCaption = '') then Result := Name else Result := StripHotKey(FCaption); end; function TdxCustomLayoutItem.GetHasMouse: Boolean; begin Result := FContainer.ItemWithMouse = Self; end; function TdxCustomLayoutItem.GetIndex: Integer; begin if FParent = nil then Result := -1 else Result := FParent.IndexOf(Self); end; function TdxCustomLayoutItem.GetIsAvailable: Boolean; begin Result := not IsRoot and ((Parent = nil) or Parent.IsAvailable); end; function TdxCustomLayoutItem.GetIsDesigning: Boolean; begin Result := csDesigning in ComponentState; end; function TdxCustomLayoutItem.GetIsDestroying: Boolean; begin Result := csDestroying in ComponentState; end; function TdxCustomLayoutItem.GetIsDragged: Boolean; var ADragObject: TdxLayoutControlDragAndDropObject; begin Result := Container.DragAndDropState <> ddsNone; if Result then begin ADragObject := Container.DragAndDropObject as TdxLayoutControlDragAndDropObject; Result := ADragObject.SourceItem = Self; end; end; function TdxCustomLayoutItem.GetIsLoading: Boolean; begin Result := csLoading in ComponentState; end; function TdxCustomLayoutItem.GetIsSelected: Boolean; begin Result := Container.IsComponentSelected(Self); end; function TdxCustomLayoutItem.GetIsRoot: Boolean; begin Result := (FContainer <> nil) and (FContainer.FRootGroup = Self); end; function TdxCustomLayoutItem.GetVisibleIndex: Integer; begin if FParent = nil then Result := -1 else Result := FParent.VisibleIndexOf(Self); end; procedure TdxCustomLayoutItem.SetAlignHorz(Value: TdxLayoutAlignHorz); begin if AlignHorz <> Value then begin FAlignHorz := Value; Changed; end; end; procedure TdxCustomLayoutItem.SetAlignmentConstraint(Value: TdxLayoutAlignmentConstraint); begin if FAlignmentConstraint <> Value then begin Container.BeginUpdate; try if FAlignmentConstraint <> nil then FAlignmentConstraint.InternalRemoveItem(Self); FAlignmentConstraint := Value; if FAlignmentConstraint <> nil then FAlignmentConstraint.InternalAddItem(Self); finally Container.EndUpdate; end; end; end; procedure TdxCustomLayoutItem.SetAlignVert(Value: TdxLayoutAlignVert); begin if AlignVert <> Value then begin FAlignVert := Value; Changed; end; end; procedure TdxCustomLayoutItem.SetAutoAligns(Value: TdxLayoutAutoAligns); function GetLoadedAlignHorz: TdxLayoutAlignHorz; begin if AlignHorz = ahParentManaged then Result := ahLeft else Result := AlignHorz; end; function GetLoadedAlignVert: TdxLayoutAlignVert; begin if AlignVert = avParentManaged then Result := avTop else Result := AlignVert; end; begin if AutoAligns <> Value then begin Container.BeginUpdate; try if aaHorizontal in Value then AlignHorz := ahParentManaged else AlignHorz := GetLoadedAlignHorz; if aaVertical in Value then AlignVert := avParentManaged else AlignVert := GetLoadedAlignVert; finally Container.EndUpdate; end; end; end; procedure TdxCustomLayoutItem.SetCaption(const Value: string); begin if FCaption <> Value then begin FCaption := Value; ResetCachedTextHeight; Changed; end; end; procedure TdxCustomLayoutItem.SetContainer(Value: TdxCustomLayoutControl); begin if FContainer <> Value then begin if not IsRoot and (FContainer <> nil) then FContainer.ExtractAbsoluteItem(Self); FContainer := Value; if not IsRoot then begin if FContainer <> nil then FContainer.AddAbsoluteItem(Self); if Self.Name = '' then SetComponentName(Self, GetBaseName, IsDesigning, IsLoading); end else Name := GetValidName(Self, GetBaseName + '_Root'); ContainerChanged; end; end; procedure TdxCustomLayoutItem.SetEnabled(Value: Boolean); begin if FEnabled <> Value then begin FEnabled := Value; EnabledChanged; end; end; procedure TdxCustomLayoutItem.SetLayoutLookAndFeel(Value: TdxCustomLayoutLookAndFeel); begin if FLayoutLookAndFeel <> Value then begin if FLayoutLookAndFeel <> nil then FLayoutLookAndFeel.RemoveUser(Self); FLayoutLookAndFeel := Value; if FLayoutLookAndFeel <> nil then FLayoutLookAndFeel.AddUser(Self); LayoutLookAndFeelUserChanged; end; end; procedure TdxCustomLayoutItem.SetHasMouse(Value: Boolean); begin if HasMouse <> Value then if Value then FContainer.ItemWithMouse := Self else FContainer.ItemWithMouse := nil; end; procedure TdxCustomLayoutItem.SetIndex(Value: Integer); begin if FParent <> nil then FParent.ChangeItemIndex(Self, Value); end; procedure TdxCustomLayoutItem.SetParent(Value: TdxLayoutGroup); var APrevParent: TdxLayoutGroup; begin if (FParent <> Value) and CanMoveTo(Value) then begin APrevParent := FParent; if FParent <> nil then FParent.ExtractItem(Self) else if FContainer <> nil then FContainer.ExtractAvailableItem(Self); if Value <> nil then Value.AddItem(Self) else if (APrevParent <> nil) and not APrevParent.IsDestroying then FContainer.AddAvailableItem(Self); Changed; end; end; procedure TdxCustomLayoutItem.SetShowCaption(Value: Boolean); begin if FShowCaption <> Value then begin FShowCaption := Value; Changed; end; end; procedure TdxCustomLayoutItem.SetVisible(Value: Boolean); begin if FVisible <> Value then begin FVisible := Value; Changed; end; end; procedure TdxCustomLayoutItem.SetVisibleIndex(Value: Integer); begin if FParent <> nil then FParent.ChangeItemVisibleIndex(Self, Value); end; function TdxCustomLayoutItem.IsAlignHorzStored: Boolean; begin Result := IsRoot or (AlignHorz <> ahParentManaged); end; function TdxCustomLayoutItem.IsAlignVertStored: Boolean; begin Result := IsRoot or (AlignVert <> avParentManaged); end; procedure TdxCustomLayoutItem.SetName(const Value: TComponentName); begin inherited; if Container.IsDesigning then Container.CustomizeFormUpdate([cfutContent]); end; procedure TdxCustomLayoutItem.SetParentComponent(Value: TComponent); begin inherited; if Value is TdxLayoutGroup then Parent := TdxLayoutGroup(Value) else if Value is TdxCustomLayoutControl then TdxCustomLayoutControl(Value).AddAvailableItem(Self); end; procedure TdxCustomLayoutItem.LayoutLookAndFeelChanged; begin end; procedure TdxCustomLayoutItem.LayoutLookAndFeelChanging; begin ResetCachedTextHeight; end; procedure TdxCustomLayoutItem.BeginLayoutLookAndFeelUserDestroying; begin FContainer.BeginUpdate; end; procedure TdxCustomLayoutItem.EndLayoutLookAndFeelUserDestroying; begin FContainer.EndUpdate; end; procedure TdxCustomLayoutItem.LayoutLookAndFeelUserChanged; begin if IsDestroying or IsLoading or not ActuallyVisible then Exit; LayoutLookAndFeelChanging; Changed; LayoutLookAndFeelChanged; end; procedure TdxCustomLayoutItem.LayoutLookAndFeelUserDestroyed; begin LayoutLookAndFeel := nil; end; function TdxCustomLayoutItem.CanFocusOnClick(X, Y: Integer): Boolean; begin Result := False; end; function TdxCustomLayoutItem.CanRemove: Boolean; begin Result := FAllowRemove; end; procedure TdxCustomLayoutItem.ContainerChanged; begin // do nothing end; procedure TdxCustomLayoutItem.DoCaptionDown; begin // do nothing end; procedure TdxCustomLayoutItem.DoCaptionClick; begin CallNotify(FOnCaptionClick, Self); end; procedure TdxCustomLayoutItem.DoPack; begin // do nothing end; function TdxCustomLayoutItem.DoProcessAccel: Boolean; var AItem: TdxCustomLayoutItem; begin Result := CanProcessAccel(AItem); if Result then AItem.ProcessAccel; end; procedure TdxCustomLayoutItem.EnabledChanged; begin Changed(ictLight); end; function TdxCustomLayoutItem.GetParentManagedAlignHorz: TdxLayoutAlignHorz; begin Result := GetParentHelperClass.GetChildItemsAlignHorz; end; function TdxCustomLayoutItem.GetParentManagedAlignVert: TdxLayoutAlignVert; begin Result := GetParentHelperClass.GetChildItemsAlignVert; end; function TdxCustomLayoutItem.GetBaseName: string; begin Result := FContainer.Name; end; function TdxCustomLayoutItem.GetCursor(X, Y: Integer): TCursor; begin Result := ViewInfo.GetCursor(X, Y); end; function TdxCustomLayoutItem.GetEnabledForWork: Boolean; begin Result := FEnabled and ((FParent = nil) or FParent.EnabledForWork); end; function TdxCustomLayoutItem.GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin Result := FLayoutLookAndFeel; if Result = nil then if FParent <> nil then Result := FParent.GetChildLayoutLookAndFeel else Result := FContainer.GetLayoutLookAndFeel; end; function TdxCustomLayoutItem.GetParentHelperClass: TdxLayoutGroupHelperClass; begin if Parent <> nil then Result := Parent.GetHelperClass else Result := TdxLayoutGroupHelper; end; function TdxCustomLayoutItem.GetShowCaption: Boolean; begin Result := FShowCaption; end; function TdxCustomLayoutItem.GetVisible: Boolean; begin Result := FVisible or IsDesigning; end; function TdxCustomLayoutItem.HasControl: Boolean; begin Result := False; end; procedure TdxCustomLayoutItem.BeforeCalculateViewInfo; begin // do nothing end; procedure TdxCustomLayoutItem.AfterCalculateViewInfo; begin // do nothing end; function TdxCustomLayoutItem.IsParentGroup(AParentGroup: TdxLayoutGroup): Boolean; begin Result := AParentGroup.IsChildItem(Self); end; function TdxCustomLayoutItem.IsChildItem(AChildItem: TdxCustomLayoutItem): Boolean; begin while (AChildItem <> nil) and (AChildItem <> Self) do AChildItem := AChildItem.Parent; Result := AChildItem = Self; end; function TdxCustomLayoutItem.HasCaption: Boolean; begin Result := ShowCaption and (Caption <> ''); end; procedure TdxCustomLayoutItem.Init; begin if GetLayoutLookAndFeel <> nil then LayoutLookAndFeelChanged; end; procedure TdxCustomLayoutItem.MouseEnter; begin ViewInfo.MouseEnter; end; procedure TdxCustomLayoutItem.MouseLeave; begin if FViewInfo <> nil then FViewInfo.MouseLeave; end; procedure TdxCustomLayoutItem.CustomizationMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var AHitTest: TdxCustomLayoutHitTest; begin AHitTest := ViewInfo.GetHitTest(Point(X, Y)); if AHitTest is TdxCustomLayoutItemHitTest then TdxCustomLayoutItemHitTest(AHitTest).Item.SelectComponent(Shift); end; procedure TdxCustomLayoutItem.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin ViewInfo.MouseDown(Button, Shift, X, Y); if Container.Customization or Container.IsDesigning then CustomizationMouseDown(Button, Shift, X, Y); end; procedure TdxCustomLayoutItem.MouseMove(Shift: TShiftState; X, Y: Integer); begin ViewInfo.MouseMove(Shift, X, Y); end; procedure TdxCustomLayoutItem.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin ViewInfo.MouseUp(Button, Shift, X, Y); end; procedure TdxCustomLayoutItem.ProcessAccel; begin end; function TdxCustomLayoutItem.ProcessDialogChar(ACharCode: Word): Boolean; begin Result := HasCaption and FCaptionOptions.ShowAccelChar and IsAccel(ACharCode, Caption) and DoProcessAccel; end; function TdxCustomLayoutItem.GetCaptionOptionsClass: TdxCustomLayoutItemCaptionOptionsClass; begin Result := TdxCustomLayoutItemCaptionOptions; end; procedure TdxCustomLayoutItem.ResetCachedTextHeight; begin FCachedTextHeight := 0; end; //IdxLayoutSelectableItem function TdxCustomLayoutItem.CanDelete: Boolean; begin Result := IsDesigning or CanRemove; end; function TdxCustomLayoutItem.IsChild(AOwner: TdxCustomLayoutControl): Boolean; begin Result := Container = AOwner; end; procedure TdxCustomLayoutItem.SelectComponent(AShift: TShiftState = []); begin Container.SelectComponent(Self, AShift); end; procedure TdxCustomLayoutItem.SelectParent; begin if Parent = nil then Container.SelectComponent(Container) else Container.SelectComponent(Parent); end; procedure TdxCustomLayoutItem.SelectionChanged; begin // do nothing end; function TdxCustomLayoutItem.IsSelectableItemVisible: Boolean; begin Result := ActuallyVisible; end; function TdxCustomLayoutItem.GetParentComponent: TComponent; begin if FParent = nil then Result := FContainer else Result := FParent; end; function TdxCustomLayoutItem.HasParent: Boolean; begin Result := True; end; procedure TdxCustomLayoutItem.Changed(AType: TdxLayoutItemChangeType); begin if IsDestroying or Container.IsLoading or Container.IsDestroying or Container.IsUpdateLocked then Exit; case AType of ictHard: Container.LayoutChanged(False); ictMedium: if ViewInfo <> nil then begin Container.BeginUpdate; try BeforeCalculateViewInfo; ViewInfo.Calculate(ViewInfo.Bounds); AfterCalculateViewInfo; if Container.HandleAllocated then Container.PlaceControls(ViewInfo); Container.InvalidateRect(ViewInfo.Bounds, False); finally Container.CancelUpdate; end; Container.PostBuildSelectionLayer; end; ictLight: if ViewInfo <> nil then Container.InvalidateRect(ViewInfo.Bounds, False); end; end; function TdxCustomLayoutItem.CanMoveTo(AParent: TdxCustomLayoutItem): Boolean; begin Result := AParent <> Self; end; procedure TdxCustomLayoutItem.MakeVisible; var R, AClientR: TRect; procedure MakeVisibleInOneDirection(AItemMin, AItemMax, AClientMin, AClientMax: Integer; AIsHorizontal: Boolean); var AOffset: Integer; procedure ChangeOffset(ADelta: Integer); begin Inc(AOffset, ADelta); Dec(AItemMin, ADelta); Dec(AItemMax, ADelta); end; procedure ApplyOffset; begin with FContainer do if AIsHorizontal then LeftPos := LeftPos + AOffset else TopPos := TopPos + AOffset; end; begin AOffset := 0; if AItemMax > AClientMax then ChangeOffset(AItemMax - AClientMax); if AItemMin < AClientMin then ChangeOffset(-(AClientMin - AItemMin)); ApplyOffset; end; begin if not ActuallyVisible then Exit; R := ViewInfo.Bounds; AClientR := FContainer.ClientBounds; MakeVisibleInOneDirection(R.Left, R.Right, AClientR.Left, AClientR.Right, True); MakeVisibleInOneDirection(R.Top, R.Bottom, AClientR.Top, AClientR.Bottom, False); end; function TdxCustomLayoutItem.Move(AParent: TdxLayoutGroup; AIndex: Integer; APack: Boolean = False): Boolean; var ASourceContainer, ADestinationContainer: TdxCustomLayoutControl; begin Result := CanMoveTo(AParent); if not Result then Exit; ASourceContainer := Container; ADestinationContainer := AParent.Container; ASourceContainer.BeginUpdate; ADestinationContainer.BeginUpdate; try Parent := AParent; Index := AIndex; finally ASourceContainer.EndUpdate(APack); ADestinationContainer.EndUpdate(APack); end; end; function TdxCustomLayoutItem.MoveTo(AParent: TdxLayoutGroup; AVisibleIndex: Integer; APack: Boolean = False): Boolean; var AIndex: Integer; begin if AParent = nil then AIndex := -1 else AIndex := AParent.GetItemIndex(AVisibleIndex); Result := Move(AParent, AIndex, APack); end; procedure TdxCustomLayoutItem.Pack; begin DoPack; end; function TdxCustomLayoutItem.PutIntoHiddenGroup(ALayoutDirection: TdxLayoutDirection): TdxLayoutGroup; var AIndex: Integer; begin if FParent = nil then Result := nil else begin AIndex := Index; Result := FParent.CreateGroup; with Result do begin Hidden := True; LayoutDirection := ALayoutDirection; Index := AIndex; end; Move(Result, 0); end; 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 := Control.CanDragAndDrop and (Control.DragAndDropState = ddsNone) and not cxPointIsEqual(FMouseDownPos, cxInvalidPoint) and not IsPointInDragDetectArea(FMouseDownPos, X, Y) and (DragItem <> nil) and not DragItem.IsRoot; end; procedure TdxLayoutDragAndDropHelper.BeginDragAndDrop(ASource: TdxLayoutDragSource); begin DragAndDropObject.Init(ASource, DragItem); Control.BeginDragAndDrop; end; function TdxLayoutDragAndDropHelper.GetDragAndDropObject: TdxLayoutControlDragAndDropObject; begin Result := TdxLayoutControlDragAndDropObject(Control.DragAndDropObject); end; { TdxLayoutCustomizeListBox } function TdxLayoutCustomizeListBox.GetDragAndDropItemObject: TdxCustomLayoutItem; begin Result := TdxCustomLayoutItem(inherited DragAndDropItemObject); end; procedure TdxLayoutCustomizeListBox.BeginDragAndDrop; begin inherited; with Control do if CanDragAndDrop then begin (DragAndDropObject as TdxLayoutControlDragAndDropObject).Init(dsCustomizeFormAvailableItems, Self.DragAndDropItemObject); BeginDragAndDrop; end; end; { TdxLayoutControlRunTimeSelectionHelper } constructor TdxLayoutRunTimeSelectionHelper.Create(AOwner: TPersistent); begin inherited Create; FOwner := AOwner; FSelectionList := TcxComponentList.Create; FListeners := TList.Create; FSelectionList.OnNotify := SelectionListNotifyHandler; FSelectionList.OnComponentListChanged := SelectionListChangedHandler; end; destructor TdxLayoutRunTimeSelectionHelper.Destroy; begin FreeAndNil(FSelectionList); FreeAndNil(FListeners); inherited; end; procedure TdxLayoutRunTimeSelectionHelper.AddSelectionChangedListener(AListener: TPersistent); begin if (AListener <> nil) and Supports(AListener, IdxLayoutSelectionChanged) and (FListeners.IndexOf(AListener) < 0) then FListeners.Add(AListener); end; procedure TdxLayoutRunTimeSelectionHelper.RemoveSelectionChangedListener(AListener: TPersistent); begin FListeners.Remove(AListener); end; function TdxLayoutRunTimeSelectionHelper.CanDeleteComponent( AComponent: TComponent): Boolean; var ASelectableItem: IdxLayoutSelectableItem; begin Result := not (csDestroying in AComponent.ComponentState) and Supports(AComponent, IdxLayoutSelectableItem, ASelectableItem) and ASelectableItem.CanDelete; end; procedure TdxLayoutRunTimeSelectionHelper.ClearSelection; begin FSelectionList.Clear; end; procedure TdxLayoutRunTimeSelectionHelper.GetSelection(AList: TList); var I: Integer; begin for I := 0 to FSelectionList.Count - 1 do AList.Add(FSelectionList[I]); end; function TdxLayoutRunTimeSelectionHelper.IsComponentSelected(AComponent: TPersistent): Boolean; begin Result := FSelectionList.IndexOf(TComponent(AComponent)) <> -1; end; procedure TdxLayoutRunTimeSelectionHelper.SelectComponent( AComponent: TPersistent; AShift: TShiftState); begin FSelectionList.BeginUpdate; try if (ssCtrl in AShift) and IsComponentSelected(AComponent) then FSelectionList.Delete(FSelectionList.IndexOf(TComponent(AComponent))) else begin if not (ssCtrl in AShift) then ClearSelection; if not IsComponentSelected(AComponent) then FSelectionList.Add(TComponent(AComponent)); end; finally FSelectionList.EndUpdate; end; end; procedure TdxLayoutRunTimeSelectionHelper.SetSelection(AList: TList); var I: Integer; begin FSelectionList.BeginUpdate; try ClearSelection; for I := 0 to AList.Count - 1 do if FSelectionList.IndexOf(AList[I]) = -1 then FSelectionList.Add(AList[I]); finally FSelectionList.EndUpdate; end; end; function TdxLayoutRunTimeSelectionHelper.UniqueName(const BaseName: string): string; begin Result := ''; end; function TdxLayoutRunTimeSelectionHelper.GetComponentClass(AComponent: TComponent): TComponentClass; begin Result := TComponentClass(AComponent.ClassType); end; procedure TdxLayoutRunTimeSelectionHelper.NotifyListeners(AList: TList; AAction: TdxLayoutSelectionAction); var I: Integer; AIntf: IdxLayoutSelectionChanged; begin for I := 0 to FListeners.Count - 1 do if Supports(TObject(FListeners[I]), IdxLayoutSelectionChanged, AIntf) then begin AIntf.SelectionChanged(AList, AAction); AIntf := nil; end; end; procedure TdxLayoutRunTimeSelectionHelper.SelectionListNotify(AComponent: TComponent; AAction: TListNotification); var ASelectableItem: IdxLayoutSelectableItem; begin if not (csDestroying in AComponent.ComponentState) and Supports(AComponent, IdxLayoutSelectableItem, ASelectableItem) then ASelectableItem.SelectionChanged; end; function TdxLayoutRunTimeSelectionHelper.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end; function TdxLayoutRunTimeSelectionHelper._AddRef: Integer; begin Result := InterlockedIncrement(FRefCount); end; function TdxLayoutRunTimeSelectionHelper._Release: Integer; begin Result := InterlockedDecrement(FRefCount); if Result = 0 then Destroy; end; function TdxLayoutRunTimeSelectionHelper.GetComponent: TComponent; begin Result := TComponent(Owner); end; procedure TdxLayoutRunTimeSelectionHelper.SelectionListNotifyHandler(Sender: TObject; AComponent: TComponent; AAction: TListNotification); begin SelectionListNotify(AComponent, AAction); end; procedure TdxLayoutRunTimeSelectionHelper.SelectionListChangedHandler(Sender: TObject; AComponent: TComponent; AAction: TcxComponentCollectionNotification); const Action: array[TcxComponentCollectionNotification] of TdxLayoutSelectionAction = (lsaAdded, lsaChanged, lsaExtracted, lsaExtracted, lsaExtracted); var AList: TList; begin if AAction in [ccnAdded, ccnChanged, ccnExtracted] then begin AList := TList.Create; try GetSelection(AList); NotifyListeners(AList, Action[AAction]); finally AList.Free; end; end; end; { TdxLayoutAlignmentConstraint } constructor TdxLayoutAlignmentConstraint.Create(AOwner: TComponent); begin inherited; CreateItems; end; destructor TdxLayoutAlignmentConstraint.Destroy; begin DestroyItems; if FControl <> nil then FControl.RemoveAlignmentConstraint(Self); inherited; end; function TdxLayoutAlignmentConstraint.GetCount: Integer; begin Result := FItems.Count; end; function TdxLayoutAlignmentConstraint.GetItem(Index: Integer): TdxCustomLayoutItem; begin Result := FItems[Index]; end; procedure TdxLayoutAlignmentConstraint.SetKind(Value: TdxLayoutAlignmentConstraintKind); begin if FKind <> Value then begin FKind := Value; Changed; end; end; procedure TdxLayoutAlignmentConstraint.CreateItems; begin FItems := TList.Create; end; procedure TdxLayoutAlignmentConstraint.DestroyItems; var I: Integer; begin BeginUpdate; try for I := Count - 1 downto 0 do RemoveItem(Items[I]); finally EndUpdate; end; FreeAndNil(FItems); end; procedure TdxLayoutAlignmentConstraint.InternalAddItem(AItem: TdxCustomLayoutItem); begin FItems.Add(AItem); end; procedure TdxLayoutAlignmentConstraint.InternalRemoveItem(AItem: TdxCustomLayoutItem); begin FItems.Remove(AItem); if not (csDestroying in ComponentState) and (Count < 2) then Free; end; procedure TdxLayoutAlignmentConstraint.SetParentComponent(Value: TComponent); begin inherited; if Value is TdxCustomLayoutControl then TdxCustomLayoutControl(Value).AddAlignmentConstraint(Self); end; procedure TdxLayoutAlignmentConstraint.BeginUpdate; begin FControl.BeginUpdate; end; function TdxLayoutAlignmentConstraint.CanAddItem(AItem: TdxCustomLayoutItem): Boolean; begin Result := (AItem <> nil) and (AItem.Container = Control); end; procedure TdxLayoutAlignmentConstraint.Changed; begin FControl.LayoutChanged; end; procedure TdxLayoutAlignmentConstraint.EndUpdate; begin FControl.EndUpdate; end; function TdxLayoutAlignmentConstraint.GetParentComponent: TComponent; begin Result := FControl; end; function TdxLayoutAlignmentConstraint.HasParent: Boolean; begin Result := FControl <> nil; end; procedure TdxLayoutAlignmentConstraint.AddItem(AItem: TdxCustomLayoutItem); begin if CanAddItem(AItem) then AItem.AlignmentConstraint := Self; end; procedure TdxLayoutAlignmentConstraint.RemoveItem(AItem: TdxCustomLayoutItem); begin if FItems.IndexOf(AItem) <> -1 then AItem.AlignmentConstraint := nil; end; { TdxCustomisationCanvas } constructor TdxCustomizationCanvas.Create; begin inherited Create(TCanvas.Create); end; destructor TdxCustomizationCanvas.Destroy; begin Canvas.Free; inherited; end; procedure TdxCustomizationCanvas.BeginPaint(ADC: THandle); begin SetLength(FSavedDCs, FCounter + 1); if HandleValid then begin SaveState; FSavedDCs[FCounter].PrevDC := Handle; end else FSavedDCs[FCounter].PrevDC := 0; FSavedDCs[FCounter].PrevCanvas := nil; FSavedDCs[FCounter].NewDC := ADC; FSavedDCs[FCounter].NewDCIndex := Windows.SaveDC(ADC); SynchronizeObjects(ADC); Canvas.Handle := ADC; Inc(FCounter); end; procedure TdxCustomizationCanvas.BeginPaint(ACanvas: TCanvas); begin SetLength(FSavedDCs, FCounter + 1); FSavedDCs[FCounter].PrevCanvas := Canvas; Canvas := ACanvas; SaveClipRegion; SaveState; Inc(FCounter); end; procedure TdxCustomizationCanvas.EndPaint; begin if FCounter > 0 then begin Dec(FCounter); if FSavedDCs[FCounter].PrevCanvas <> nil then begin RestoreState; RestoreClipRegion; Canvas := FSavedDCs[FCounter].PrevCanvas; end else begin Canvas.Handle := FSavedDCs[FCounter].PrevDC; Windows.RestoreDC(FSavedDCs[FCounter].NewDC, FSavedDCs[FCounter].NewDCIndex); if HandleValid then RestoreState; end; SetLength(FSavedDCs, FCounter); end; end; function TdxCustomizationCanvas.HandleValid; begin Result := {$IFDEF DELPHI6}Canvas.HandleAllocated{$ELSE}FCounter > 0{$ENDIF}; end; { TdxCustomSatelliteControlItem } constructor TdxCustomSatelliteControlItem.Create(AOwner: TdxSatelliteControls; AControl: TControl); begin inherited Create(nil); FOwner := AOwner; FControl := AControl; FControl.FreeNotification(Self); end; destructor TdxCustomSatelliteControlItem.Destroy; begin FControl.RemoveFreeNotification(Self); FControl := nil; inherited Destroy; end; procedure TdxCustomSatelliteControlItem.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if (AComponent = FControl) and (Operation = opRemove) then Free; end; { TdxControlDesignSelectorItem } constructor TdxControlDesignSelectorItem.Create(AOwner: TdxSatelliteControls; AControl: TControl); begin inherited Create(AOwner, AControl); FSelectorBounds := cxInvalidRect; FChildren := TcxComponentList.Create; FChildren.OwnsObjects := True; FDefaultControlWndProc := Control.WindowProc; Control.WindowProc := ControlWndProc; end; destructor TdxControlDesignSelectorItem.Destroy; begin Control.WindowProc := FDefaultControlWndProc; FDefaultControlWndProc := nil; FreeAndNil(FChildren); inherited Destroy; end; procedure TdxControlDesignSelectorItem.ControlWndProc(var Message: TMessage); function PtInSelectorBounds(const P: TPoint): Boolean; begin Result := PtInRect(SelectorBounds, P); end; var DC: HDC; ANeedProcessDefaultControlWndProc: Boolean; begin ANeedProcessDefaultControlWndProc := True; if IsActive and not EqualRect(cxInvalidRect, SelectorBounds) then case Message.Msg of WM_NCHITTEST: if PtInSelectorBounds(Control.ScreenToClient(Point(Message.LParamLo, Message.LParamHi))) then begin Message.Result := HTTRANSPARENT; ANeedProcessDefaultControlWndProc := False; end; CM_HITTEST: if PtInSelectorBounds(Point(Message.LParamLo, Message.LParamHi)) then begin Message.Result := HTNOWHERE; ANeedProcessDefaultControlWndProc := False; end; end; if ANeedProcessDefaultControlWndProc then FDefaultControlWndProc(Message); case Message.Msg of CM_CONTROLCHANGE: CheckChildren; WM_WINDOWPOSCHANGED: ParentCheckChildren; WM_PAINT: if IsActive then begin DC := TWMPaint(Message).DC; if DC <> 0 then DrawDesignSelector(DC) else if Control is TWinControl then begin DC := GetWindowDC((Control as TWinControl).Handle); DrawDesignSelector(DC); ReleaseDC((Control as TWinControl).Handle, DC); end; end; end; end; procedure TdxControlDesignSelectorItem.CheckChildren; var I: Integer; AItem: TdxControlDesignSelectorItem; AControl: TControl; begin FChildren.Clear; if Control is TWinControl then for I := 0 to (Control as TWinControl).ControlCount - 1 do begin AControl := (Control as TWinControl).Controls[I]; if csDestroying in AControl.ComponentState then Continue; AItem := TdxControlDesignSelectorItem.Create(nil, AControl); FChildren.Add(AItem); AItem.Parent := Self; AItem.LayoutItem := LayoutItem; AItem.SelectorBounds := GetSelectorBoundsForChild(AItem); end; end; procedure TdxControlDesignSelectorItem.ParentCheckChildren; begin if Parent <> nil then Parent.CheckChildren; end; function TdxControlDesignSelectorItem.IsActive: Boolean; begin Result := IsValid and LayoutItem.Container.ShowDesignSelectors; end; function TdxControlDesignSelectorItem.IsValid: Boolean; begin Result := (LayoutItem <> nil) and (LayoutItem.ViewInfo <> nil); end; function TdxControlDesignSelectorItem.CanDrawDesignSelector: Boolean; begin Result := IsActive and LayoutItem.ActuallyVisible; end; procedure TdxControlDesignSelectorItem.DoDrawDesignSelector(DC: HDC); function IsSelected: Boolean; begin Result := (not LayoutItem.Container.Customization and LayoutItem.ViewInfo.Selected) or (LayoutItem.Container.Customization and LayoutItem.Container.IsComponentSelected(LayoutItem.Control)); end; begin dxGlobalCanvas.BeginPaint(DC); try cxDrawDesignRect(dxGlobalCanvas, SelectorBounds, IsSelected); finally dxGlobalCanvas.EndPaint; end; end; procedure TdxControlDesignSelectorItem.DrawDesignSelector(DC: HDC); begin if CanDrawDesignSelector then DoDrawDesignSelector(DC); end; function TdxControlDesignSelectorItem.GetSelectorBoundsForChild(AChild: TdxControlDesignSelectorItem): TRect; begin Result := SelectorBounds; Result := cxRectOffset(Result, AChild.Control.BoundsRect.TopLeft, False); end; procedure TdxControlDesignSelectorItem.SetLayoutItem(AValue: TdxLayoutItem); begin if AValue <> FLayoutItem then begin FLayoutItem := AValue; CheckChildren; end; end; procedure TdxControlDesignSelectorItem.SetSelectorBounds(const AValue: TRect); begin if not EqualRect(AValue, FSelectorBounds) then begin FSelectorBounds := AValue; CheckChildren; if Control.Visible then Control.Invalidate; end; end; { TdxCustomizationControlItem } constructor TdxCustomizationControlItem.Create(AOwner: TdxSatelliteControls; AControl: TControl); begin inherited Create(AOwner, AControl); FPrevEnabled := not EnableWindow(Control.Handle, False); end; destructor TdxCustomizationControlItem.Destroy; begin if Control.HandleAllocated then EnableWindow(Control.Handle, FPrevEnabled); inherited Destroy; end; function TdxCustomizationControlItem.GetControl: TWinControl; begin Result := inherited Control as TWinControl; end; { TdxSatelliteControls } function TdxSatelliteControls.AddControl(AControl: TControl; AItemClass: TdxCustomSatelliteControlItemClass): TdxCustomSatelliteControlItem; var AIndex: Integer; begin AIndex := FindByControl(AControl); if AIndex = -1 then begin Result := AItemClass.Create(Self, AControl); Add(Result); end else Result := Items[AIndex]; end; function TdxSatelliteControls.FindByControl(AControl: TControl): Integer; var I: Integer; begin Result := -1; for I := 0 to Count - 1 do if Items[I].Control = AControl then begin Result := I; Break; end; end; procedure TdxSatelliteControls.RemoveControl(AControl: TControl); begin Delete(FindByControl(AControl)); end; function TdxSatelliteControls.GetItem(Index: Integer): TdxCustomSatelliteControlItem; begin Result := inherited Items[Index] as TdxCustomSatelliteControlItem; end; { TdxLayoutControlAdapterDefs } constructor TdxLayoutControlAdapterDefs.Create; begin inherited; FItems := TList.Create; end; destructor TdxLayoutControlAdapterDefs.Destroy; begin ClearItems; FItems.Free; inherited; end; function TdxLayoutControlAdapterDefs.GetCount: Integer; begin Result := FItems.Count; end; function TdxLayoutControlAdapterDefs.GetItem(Index: Integer): TControlAdapterRecord; begin Result := PControlAdapterRecord(FItems[Index])^; end; procedure TdxLayoutControlAdapterDefs.ClearItems; var I: Integer; begin for I := Count - 1 downto 0 do Delete(I); end; procedure TdxLayoutControlAdapterDefs.Delete(AIndex: Integer); begin Dispose(PControlAdapterRecord(FItems[AIndex])); FItems.Delete(AIndex); end; function TdxLayoutControlAdapterDefs.GetAdapterClass(AControl: TControl): TdxCustomLayoutControlAdapterClass; var I: Integer; AControlAdapterRecord: TControlAdapterRecord; begin for I := Count - 1 downto 0 do begin AControlAdapterRecord := Items[I]; if AControl.InheritsFrom(AControlAdapterRecord.ControlClass) then begin Result := AControlAdapterRecord.AdapterClass; Exit; end; end; Result := TdxCustomLayoutControlAdapter; end; procedure TdxLayoutControlAdapterDefs.Register(AControlClass: TControlClass; AAdapterClass: TdxCustomLayoutControlAdapterClass); var AControlAdapterRecord: PControlAdapterRecord; begin New(AControlAdapterRecord); with AControlAdapterRecord^ do begin ControlClass := AControlClass; AdapterClass := AAdapterClass; end; FItems.Add(AControlAdapterRecord); end; procedure TdxLayoutControlAdapterDefs.Unregister(AControlClass: TControlClass; AAdapterClass: TdxCustomLayoutControlAdapterClass); var I: Integer; AControlAdapterRecord: TControlAdapterRecord; begin for I := 0 to Count - 1 do begin AControlAdapterRecord := Items[I]; with AControlAdapterRecord do if (ControlClass = AControlClass) and (AdapterClass = AAdapterClass) then begin Delete(I); Break; end; end; if Count = 0 then FreeAndNil(FdxLayoutControlAdapterDefs); end; { TdxLayoutItemCaptionOptions } constructor TdxLayoutItemCaptionOptions.Create(AItem: TdxCustomLayoutItem); begin inherited; FAlignVert := tavCenter; end; procedure TdxLayoutItemCaptionOptions.SetAlignVert(Value: TdxAlignmentVert); begin if FAlignVert <> Value then begin FAlignVert := Value; Changed; end; end; procedure TdxLayoutItemCaptionOptions.SetLayout(Value: TdxCaptionLayout); begin if FLayout <> Value then begin FLayout := Value; Changed; end; end; procedure TdxLayoutItemCaptionOptions.SetWidth(Value: Integer); begin if Value < 0 then Value := 0; if FWidth <> Value then begin FWidth := Value; Item.ResetCachedTextHeight; Changed; end; end; { TdxLayoutItemControlOptions } constructor TdxLayoutItemControlOptions.Create(AItem: TdxCustomLayoutItem); begin inherited; FAutoAlignment := True; FMinHeight := dxLayoutItemControlDefaultMinHeight; FMinWidth := dxLayoutItemControlDefaultMinWidth; FShowBorder := True; end; procedure TdxLayoutItemControlOptions.SetAutoAlignment(Value: Boolean); begin if FAutoAlignment <> Value then begin FAutoAlignment := Value; Changed; end; end; procedure TdxLayoutItemControlOptions.SetAutoColor(Value: Boolean); begin if FAutoColor <> Value then begin FAutoColor := Value; Item.LayoutLookAndFeelUserChanged; end; end; procedure TdxLayoutItemControlOptions.SetFixedSize(Value: Boolean); begin if FFixedSize <> Value then begin FFixedSize := Value; Changed; end; end; procedure TdxLayoutItemControlOptions.SetMinHeight(Value: Integer); begin if Value < 0 then Value := 0; if FMinHeight <> Value then begin FMinHeight := Value; Changed; end; end; procedure TdxLayoutItemControlOptions.SetMinWidth(Value: Integer); begin if Value < 0 then Value := 0; if FMinWidth <> Value then begin FMinWidth := Value; Changed; end; end; procedure TdxLayoutItemControlOptions.SetOpaque(Value: Boolean); begin if FOpaque <> Value then begin FOpaque := Value; Changed; end; end; procedure TdxLayoutItemControlOptions.SetShowBorder(Value: Boolean); begin if FShowBorder <> Value then begin FShowBorder := Value; Changed; end; end; { TdxCustomLayoutElementPainter } constructor TdxCustomLayoutElementPainter.Create(ACanvas: TcxCanvas; AViewInfo: TdxCustomLayoutElementViewInfo); begin inherited Create; FCanvas := ACanvas; FViewInfo := AViewInfo; end; { TdxCustomLayoutItemElementPainter } function TdxCustomLayoutItemElementPainter.GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin Result := ViewInfo.LayoutLookAndFeel; end; function TdxCustomLayoutItemElementPainter.GetViewInfo: TdxCustomLayoutItemElementViewInfo; begin Result := inherited ViewInfo as TdxCustomLayoutItemElementViewInfo; end; { TdxCustomLayoutItemCaptionPainter } function TdxCustomLayoutItemCaptionPainter.GetViewInfo: TdxCustomLayoutItemCaptionViewInfo; begin Result := TdxCustomLayoutItemCaptionViewInfo(inherited ViewInfo); end; procedure TdxCustomLayoutItemCaptionPainter.AfterDrawText; begin with Canvas do Brush.Style := bsSolid; end; procedure TdxCustomLayoutItemCaptionPainter.BeforeDrawText; begin with Canvas do begin Brush.Style := bsClear; Font := ViewInfo.Font; Font.Color := ViewInfo.TextColor; if ViewInfo.IsTextUnderlined then Font.Style := Font.Style + [fsUnderline]; end; end; procedure TdxCustomLayoutItemCaptionPainter.DrawBackground; begin end; procedure TdxCustomLayoutItemCaptionPainter.DrawText; begin if ViewInfo.Text <> '' then begin BeforeDrawText; DoDrawText; AfterDrawText; end; end; procedure TdxCustomLayoutItemCaptionPainter.DoDrawText; begin with ViewInfo do Self.Canvas.DrawText(Text, TextAreaBounds, CalculateTextFlags, EnabledForWork); end; procedure TdxCustomLayoutItemCaptionPainter.Paint; begin if RectVisible(Canvas.Handle, ViewInfo.Bounds) then begin DrawBackground; DrawText; end; end; { TdxCustomLayoutItemPainter } function TdxCustomLayoutItemPainter.GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin Result := ViewInfo.LayoutLookAndFeel; end; function TdxCustomLayoutItemPainter.GetViewInfo: TdxCustomLayoutItemViewInfo; begin Result := inherited ViewInfo as TdxCustomLayoutItemViewInfo; end; procedure TdxCustomLayoutItemPainter.DoDrawBackground; begin if ViewInfo.HasBackground then Canvas.FillRect(ViewInfo.BackgroundBounds, ViewInfo.GetBackgroundColor); end; procedure TdxCustomLayoutItemPainter.DoDrawCaption; begin with GetCaptionPainterClass.Create(Canvas, ViewInfo.CaptionViewInfo) do try Paint; finally Free; end; end; procedure TdxCustomLayoutItemPainter.DoDrawSpecificPart; begin // do nothing end; procedure TdxCustomLayoutItemPainter.DoDrawSelectionFrame; begin FrameRectByColor(Canvas.Handle, ViewInfo.SelectionBorderRect, dxLayoutSelectionBorderDefaultColor); end; procedure TdxCustomLayoutItemPainter.DrawBackground; begin if CanDrawBackground then DoDrawBackground; end; procedure TdxCustomLayoutItemPainter.DrawCaption; begin if CanDrawCaption then DoDrawCaption; end; procedure TdxCustomLayoutItemPainter.DrawItem; begin DrawBackground; DrawContent; end; procedure TdxCustomLayoutItemPainter.DrawContent; begin DrawCaption; end; function TdxCustomLayoutItemPainter.CanDrawBackground: Boolean; begin Result := ViewInfo.CanDrawBackground; end; function TdxCustomLayoutItemPainter.CanDrawCaption: Boolean; begin Result := ViewInfo.HasCaption; end; function TdxCustomLayoutItemPainter.CanPaint: Boolean; begin Result := ViewInfo.CanPaint; end; function TdxCustomLayoutItemPainter.CanPaintSpecificPart: Boolean; begin Result := CanPaint and ViewInfo.IsDragImagePainted; end; procedure TdxCustomLayoutItemPainter.PaintSpecificPart; begin if CanPaintSpecificPart then DoDrawSpecificPart; end; procedure TdxCustomLayoutItemPainter.PaintDesignFeatures; begin // do nothing end; procedure TdxCustomLayoutItemPainter.Paint; begin if CanPaint and RectVisible(Canvas.Handle, ViewInfo.Bounds) then begin DrawItem; //#DG selection breaks Canvas.ExcludeClipRect(ViewInfo.Bounds); end; end; { TdxLayoutItemControlPainter } function TdxLayoutItemControlPainter.GetViewInfo: TdxLayoutItemControlViewInfo; begin Result := TdxLayoutItemControlViewInfo(inherited ViewInfo); end; procedure TdxLayoutItemControlPainter.DrawBorders; begin LayoutLookAndFeel.DrawItemControlBorder(Canvas, ViewInfo.ItemViewInfo.Options, ViewInfo.Bounds); end; procedure TdxLayoutItemControlPainter.Paint; begin if ViewInfo.HasBorder and RectVisible(Canvas.Handle, ViewInfo.Bounds) then DrawBorders; end; { TdxLayoutItemPainter } function TdxLayoutItemPainter.GetViewInfo: TdxLayoutItemViewInfo; begin Result := TdxLayoutItemViewInfo(inherited ViewInfo); end; function TdxLayoutItemPainter.CanDrawBackground: Boolean; begin Result := inherited CanDrawBackground and not ViewInfo.IsTransparent; end; function TdxLayoutItemPainter.CanDrawCaption: Boolean; begin Result := inherited CanDrawCaption or (ViewInfo.IsDragImagePainted and ViewInfo.IsAvailable); end; function TdxLayoutItemPainter.CanPaintSpecificPart: Boolean; begin Result := CanPaint and not ViewInfo.IsAvailable and ViewInfo.HasControl; end; function TdxLayoutItemPainter.GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; begin Result := TdxLayoutItemCaptionPainter; end; function TdxLayoutItemPainter.GetControlPainterClass: TdxLayoutItemControlPainterClass; begin Result := TdxLayoutItemControlPainter; end; procedure TdxLayoutItemPainter.DoDrawControlBorder; begin with GetControlPainterClass.Create(Canvas, ViewInfo.ControlViewInfo) do try Paint; finally Free; end; end; procedure TdxLayoutItemPainter.DoDrawSpecificPart; function GetControlRect(AControl: TControl): TRect; // copy from cxPC begin Result := Rect(0, 0, AControl.Width, AControl.Height); end; var AControl: TWinControl; begin Canvas.SaveState; try if ViewInfo.Item.Control is TWinControl then begin AControl := TWinControl(ViewInfo.Item.Control); with ViewInfo.Item.Control.BoundsRect.TopLeft do AControl.PaintTo(Canvas.Canvas, X, Y); end else begin with ViewInfo.Item.Control.BoundsRect.TopLeft do MoveWindowOrg(Canvas.Handle, X, Y); Canvas.IntersectClipRect(GetControlRect(ViewInfo.Item.Control)); ViewInfo.Item.Control.Perform(WM_ERASEBKGND, Canvas.Handle, Canvas.Handle); ViewInfo.Item.Control.Perform(WM_PAINT, Canvas.Handle, 0); end; finally Canvas.RestoreState; end; end; procedure TdxLayoutItemPainter.DrawContent; begin DrawControlBorder; inherited; end; procedure TdxLayoutItemPainter.DrawControlBorder; begin if ViewInfo.HasControl then DoDrawControlBorder; end; { TdxLayoutGroupPainter } procedure TdxLayoutGroupPainter.PaintSpecificPart; var I: Integer; AViewInfo: TdxCustomLayoutItemViewInfo; begin inherited; for I := 0 to ViewInfo.ItemViewInfoCount - 1 do begin AViewInfo := ViewInfo.ItemViewInfos[I]; with AViewInfo.GetPainterClass.Create(Canvas, AViewInfo) do try PaintSpecificPart; finally Free; end; end; end; procedure TdxLayoutGroupPainter.PaintDesignFeatures; var I: Integer; AViewInfo: TdxCustomLayoutItemViewInfo; begin inherited; for I := 0 to ViewInfo.ItemViewInfoCount - 1 do begin AViewInfo := ViewInfo.ItemViewInfos[I]; with AViewInfo.GetPainterClass.Create(Canvas, AViewInfo) do try PaintDesignFeatures; finally Free; end; end; end; function TdxLayoutGroupPainter.GetViewInfo: TdxLayoutGroupViewInfo; begin Result := TdxLayoutGroupViewInfo(inherited ViewInfo); end; function TdxLayoutGroupPainter.GetCaptionPainterClass: TdxCustomLayoutItemCaptionPainterClass; begin Result := TdxLayoutGroupCaptionPainter; end; procedure TdxLayoutGroupPainter.DoDrawSpecificPart; begin inherited; ViewInfo.Specific.DrawSpecificPart(Canvas); end; procedure TdxLayoutGroupPainter.DoDrawSelectionFrame; begin DrawBoundsFrame; inherited; end; procedure TdxLayoutGroupPainter.DoDrawBackground; begin inherited; ViewInfo.Specific.DrawSpecificBackground(Canvas); end; procedure TdxLayoutGroupPainter.DrawContent; begin DrawBorders; DrawItemsArea; inherited; //DrawBoundsFrame; end; procedure TdxLayoutGroupPainter.DoDrawBorders; //todo: #SC {var ASide: TdxLayoutSide;} begin //todo: #SC {with Canvas do begin Brush.Color := ViewInfo.Color; for ASide := Low(TdxLayoutSide) to High(TdxLayoutSide) do Canvas.FillRect(ViewInfo.BorderRestSpaceBounds[ASide]); end;} end; procedure TdxLayoutGroupPainter.DoDrawRestSpace; begin Canvas.Brush.Color := ViewInfo.Color; Canvas.FillRect(ViewInfo.ClientBounds); end; procedure TdxLayoutGroupPainter.DoDrawBoundsFrame; begin FrameRectByColor(Canvas.Handle, ViewInfo.SelectionBorderRect, dxLayoutHiddenGroupBorderDefaultColor); end; procedure TdxLayoutGroupPainter.DrawBorders; begin if ViewInfo.HasBorder and not ViewInfo.IsTransparent then begin Canvas.SaveClipRegion; try Canvas.ExcludeClipRect(ViewInfo.CaptionViewInfo.Bounds); DoDrawBorders; finally Canvas.RestoreClipRegion; end; end; end; procedure TdxLayoutGroupPainter.DrawBoundsFrame; begin if ViewInfo.HasBoundsFrame then DoDrawBoundsFrame; end; procedure TdxLayoutGroupPainter.DrawItems; var I: Integer; AItemViewInfo: TdxCustomLayoutItemViewInfo; begin for I := 0 to ViewInfo.ItemViewInfoCount - 1 do begin AItemViewInfo := ViewInfo.ItemViewInfos[I]; if AItemViewInfo.CanPaint then with AItemViewInfo.GetPainterClass.Create(Canvas, AItemViewInfo) do try Paint; finally Free; end; end; end; procedure TdxLayoutGroupPainter.DrawRestSpace; begin if not ViewInfo.IsTransparent then DoDrawRestSpace; end; procedure TdxLayoutGroupPainter.DrawItemsArea; begin DrawItems; //todo: #SC DrawRestSpace; end; { TdxLayoutControlPainter } function TdxLayoutControlPainter.GetInternalCanvas: TcxCanvas; begin Result := FControl.Canvas; end; procedure TdxLayoutControlPainter.MakeCanvasClipped(ACanvas: TcxCanvas); begin ACanvas.IntersectClipRect(ViewInfo.ClientBounds); end; procedure TdxLayoutControlPainter.DrawBackground(ACanvas: TcxCanvas); begin if not ViewInfo.IsTransparent then ViewInfo.LayoutLookAndFeel.DrawLayoutControlBackground(ACanvas, ViewInfo.ClientBounds); end; procedure TdxLayoutControlPainter.DrawDesignSelector(ACanvas: TcxCanvas); begin if Control.IsDesigning and Control.ShowDesignSelectors then cxDrawDesignRect(ACanvas, Control.GetDesignSelectorRect, Control.IsComponentSelected(Control)); end; procedure TdxLayoutControlPainter.DrawItems(ACanvas: TcxCanvas); var AItemsViewInfo: TdxLayoutGroupViewInfo; begin AItemsViewInfo := ViewInfo.ItemsViewInfo; with AItemsViewInfo.GetPainterClass.Create(ACanvas, AItemsViewInfo) do try Paint; finally Free; end; end; procedure TdxLayoutControlPainter.DrawDesignFeatures(ACanvas: TcxCanvas); var AItemsViewInfo: TdxLayoutGroupViewInfo; begin AItemsViewInfo := ViewInfo.ItemsViewInfo; with AItemsViewInfo.GetPainterClass.Create(ACanvas, AItemsViewInfo) do try PaintDesignFeatures; finally Free; end; end; procedure TdxLayoutControlPainter.PlaceControls(AItemViewInfo: TdxCustomLayoutItemViewInfo); var AControlViewInfos, AWinControlViewInfos: TList; procedure RetrieveControlViewInfos(AItemViewInfo: TdxCustomLayoutItemViewInfo); var I: Integer; AControlViewInfo: TdxLayoutItemControlViewInfo; begin if AItemViewInfo is TdxLayoutGroupViewInfo then with TdxLayoutGroupViewInfo(AItemViewInfo) do for I := 0 to ItemViewInfoCount - 1 do RetrieveControlViewInfos(ItemViewInfos[I]) else begin AControlViewInfo := TdxLayoutItemViewInfo(AItemViewInfo).ControlViewInfo; if AControlViewInfo.Control <> nil then if AControlViewInfo.Control is TWinControl then AWinControlViewInfos.Add(AControlViewInfo) else AControlViewInfos.Add(AControlViewInfo); end; end; procedure ProcessControls; var I: Integer; begin for I := 0 to AControlViewInfos.Count - 1 do with TdxLayoutItemControlViewInfo(AControlViewInfos[I]) do begin Control.BoundsRect := ControlBounds; //ValidateRect(Self.Control.Handle, @ControlBounds); end; end; procedure ProcessWinControls; var AWindowsStruct: HDWP; I: Integer; AControlViewInfo: TdxLayoutItemControlViewInfo; R: TRect; begin AWindowsStruct := BeginDeferWindowPos(AWinControlViewInfos.Count); try for I := 0 to AWinControlViewInfos.Count - 1 do begin AControlViewInfo := TdxLayoutItemControlViewInfo(AWinControlViewInfos[I]); R := AControlViewInfo.ControlBounds; DeferWindowPos(AWindowsStruct, (AControlViewInfo.Control as TWinControl).Handle, 0, R.Left, R.Top, cxRectWidth(R), cxRectHeight(R), SWP_NOZORDER or SWP_NOACTIVATE); end; finally EndDeferWindowPos(AWindowsStruct); end; end; function CheckControlSizes(AControlViewInfos: TList): Boolean; var I: Integer; begin Result := True; for I := 0 to AControlViewInfos.Count - 1 do with TdxLayoutItemControlViewInfo(AControlViewInfos[I]) do begin Result := ((ItemViewInfo.AlignHorz = ahClient) or (Control.Width = cxRectWidth(ControlBounds))) and ((ItemViewInfo.AlignVert = avClient) or (Control.Height = cxRectHeight(ControlBounds))); if not Result then begin Item.SaveOriginalControlSize; Break; end; end; end; begin AControlViewInfos := TList.Create; AWinControlViewInfos := TList.Create; try Control.FIsPlacingControls := True; try RetrieveControlViewInfos(AItemViewInfo); ProcessControls; ProcessWinControls; finally Control.FIsPlacingControls := False; end; if not CheckControlSizes(AControlViewInfos) or not CheckControlSizes(AWinControlViewInfos) then Control.LayoutChanged; finally AWinControlViewInfos.Free; AControlViewInfos.Free; end; end; function TdxLayoutControlPainter.GetCanvas: TcxCanvas; begin Result := InternalCanvas; MakeCanvasClipped(Result); end; procedure TdxLayoutControlPainter.Paint; var ACanvas: TcxCanvas; begin ACanvas := GetCanvas; ACanvas.SaveState; try { moved to TdxLayoutControlViewInfo.Calculate }//PlaceControls; // because of selection drawing DrawBackground(ACanvas); DrawItems(ACanvas); DrawDesignFeatures(ACanvas); DrawDesignSelector(ACanvas); // PlaceControls; finally ACanvas.RestoreState; end; end; { THitTests } type THitTests = class private FItems: TList; function GetCount: Integer; function GetInstance(AClass: TdxCustomLayoutHitTestClass): TdxCustomLayoutHitTest; function GetItem(Index: Integer): TdxCustomLayoutHitTest; protected function GetObjectByClass(AClass: TdxCustomLayoutHitTestClass): TdxCustomLayoutHitTest; property Count: Integer read GetCount; property Items[Index: Integer]: TdxCustomLayoutHitTest read GetItem; public constructor Create; destructor Destroy; override; property Instances[AClass: TdxCustomLayoutHitTestClass]: TdxCustomLayoutHitTest read GetInstance; default; end; var HitTests: THitTests; constructor THitTests.Create; begin inherited; FItems := TList.Create; end; destructor THitTests.Destroy; var I: Integer; begin for I := 0 to Count - 1 do Items[I].Free; FItems.Free; inherited; end; function THitTests.GetCount: Integer; begin Result := FItems.Count; end; function THitTests.GetInstance(AClass: TdxCustomLayoutHitTestClass): TdxCustomLayoutHitTest; begin Result := GetObjectByClass(AClass); if Result = nil then begin Result := AClass.Create; FItems.Add(Result); end; end; function THitTests.GetItem(Index: Integer): TdxCustomLayoutHitTest; begin Result := FItems[Index]; end; function THitTests.GetObjectByClass(AClass: TdxCustomLayoutHitTestClass): TdxCustomLayoutHitTest; var I: Integer; begin for I := 0 to Count - 1 do begin Result := Items[I]; if Result.ClassType = AClass then Exit; end; Result := nil; end; { TdxCustomLayoutHitTest } function TdxCustomLayoutHitTest.Cursor: TCursor; begin Result := crDefault; end; class function TdxCustomLayoutHitTest.HitTestCode: Integer; begin Result := htError; end; class function TdxCustomLayoutHitTest.Instance: TdxCustomLayoutHitTest; begin Result := HitTests.Instances[Self]; end; function TdxCustomLayoutHitTest.GetGroupForInsert: TdxLayoutGroup; begin Result := nil; end; { TdxLayoutNoneHitTest } class function TdxLayoutNoneHitTest.HitTestCode: Integer; begin Result := htNone; end; { TdxLayoutItemHitTest } function TdxLayoutItemHitTest.GetItem: TdxLayoutItem; begin Result := TdxLayoutItem(inherited Item); end; procedure TdxLayoutItemHitTest.SetItem(Value: TdxLayoutItem); begin inherited Item := Value; end; class function TdxLayoutItemHitTest.HitTestCode: Integer; begin Result := htItem; end; function TdxLayoutItemHitTest.GetGroupForInsert: TdxLayoutGroup; begin Result := Item.Parent; end; { TdxLayoutGroupHitTest } function TdxLayoutGroupHitTest.GetItem: TdxLayoutGroup; begin Result := TdxLayoutGroup(inherited Item); end; procedure TdxLayoutGroupHitTest.SetItem(Value: TdxLayoutGroup); begin inherited Item := Value; end; class function TdxLayoutGroupHitTest.HitTestCode: Integer; begin Result := htGroup; end; function TdxLayoutGroupHitTest.GetGroupForInsert: TdxLayoutGroup; begin Result := Item; end; { TdxLayoutCustomizeFormHitTest } class function TdxLayoutCustomizeFormHitTest.HitTestCode: Integer; begin Result := htCustomizeForm; end; { TdxLayoutCustomizeFormAvailableItemsHitTest } class function TdxLayoutCustomizeFormAvailableItemsHitTest.HitTestCode: Integer; begin Result := htAvailableItems; end; { TdxLayoutCustomizeFormTreeViewItemsHitTest } class function TdxLayoutCustomizeFormTreeViewItemsHitTest.HitTestCode: Integer; begin Result := htTreeViewItems; end; { TdxLayoutClientAreaHitTest } class function TdxLayoutClientAreaHitTest.HitTestCode: Integer; begin Result := htClientArea; end; { TdxLayoutGroup } constructor TdxLayoutGroup.Create(AOwner: TComponent); begin inherited; FIsUserDefined := True; FItems := TcxComponentList.Create(True); FItems.OnComponentListChanged := ItemListChanged; FVisibleItems := TcxComponentList.Create; FLayoutDirection := ldVertical; FShowBorder := True; FUseIndent := True; end; destructor TdxLayoutGroup.Destroy; var ANeedCreateNewRootGroup: Boolean; begin ANeedCreateNewRootGroup := IsRoot and not (csReading in Container.ComponentState) and not Container.IsDestroying; if ANeedCreateNewRootGroup then Container.CreateRootGroup; FreeAndNil(FVisibleItems); FreeAndNil(FItems); if ANeedCreateNewRootGroup then Container.LayoutChanged; inherited; end; function TdxLayoutGroup.GetCount: Integer; begin Result := FItems.Count; end; function TdxLayoutGroup.GetItem(Index: Integer): TdxCustomLayoutItem; begin Result := TdxCustomLayoutItem(FItems[Index]); end; function TdxLayoutGroup.GetShowBorder: Boolean; begin Result := not FHidden and FShowBorder; end; function TdxLayoutGroup.GetViewInfo: TdxLayoutGroupViewInfo; begin Result := TdxLayoutGroupViewInfo(inherited ViewInfo); end; function TdxLayoutGroup.GetVisibleCount: Integer; begin Result := FVisibleItems.Count; end; function TdxLayoutGroup.GetVisibleItem(Index: Integer): TdxCustomLayoutItem; begin Result := TdxCustomLayoutItem(FVisibleItems[Index]); end; procedure TdxLayoutGroup.SetItemIndex(Value: Integer); begin if not IsLoading and (Value > VisibleCount) then Value := -1; if FItemIndex <> Value then begin FItemIndex := Value; Changed(ictMedium); end; end; procedure TdxLayoutGroup.SetHidden(Value: Boolean); begin if FHidden <> Value then begin FHidden := Value; if not IsRoot then Changed; end; end; procedure TdxLayoutGroup.SetLayoutDirection(Value: TdxLayoutDirection); begin if FLayoutDirection <> Value then begin FLayoutDirection := Value; Changed; end; end; procedure TdxLayoutGroup.SetLocked(Value: Boolean); begin if FLocked <> Value then begin FLocked := Value; end; end; procedure TdxLayoutGroup.SetLayoutLookAndFeelException(Value: Boolean); begin if FLayoutLookAndFeelException <> Value then begin FLayoutLookAndFeelException := Value; LayoutLookAndFeelUserChanged; end; end; procedure TdxLayoutGroup.SetShowBorder(Value: Boolean); begin if FShowBorder <> Value then begin FShowBorder := Value; Changed; end; end; procedure TdxLayoutGroup.SetUseIndent(Value: Boolean); begin if FUseIndent <> Value then begin FUseIndent := Value; Changed; end; end; procedure TdxLayoutGroup.AddItem(AItem: TdxCustomLayoutItem); begin FItems.Add(AItem); AItem.FParent := Self; AItem.Container := FContainer; if not IsLoading then AItem.Init; end; procedure TdxLayoutGroup.ExtractItem(AItem: TdxCustomLayoutItem); begin if not (csDestroying in ComponentState) then begin FItems.Extract(AItem); AItem.FParent := nil; Changed; end; end; procedure TdxLayoutGroup.ItemListChanged(Sender: TObject; AComponent: TComponent; AAction: TcxComponentCollectionNotification); begin if IsLoading then Exit; BuildVisibleItemsList; if ItemIndex > VisibleCount - 1 then ItemIndex := VisibleCount - 1 else if (ItemIndex = -1) and (VisibleCount > 0) then ItemIndex := 0; Changed; end; function TdxLayoutGroup.IsChildActuallyVisible(AChild: TdxCustomLayoutItem): Boolean; begin Result := ActuallyVisible and AllowDrawChild(AChild); end; function TdxLayoutGroup.GetChildLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin if LayoutLookAndFeelException and (Parent <> nil) then Result := Parent.GetChildLayoutLookAndFeel else Result := GetLayoutLookAndFeel; end; function TdxLayoutGroup.CanDelete: Boolean; var I: Integer; begin Result := not IsRoot and inherited CanDelete; if Result then for I := 0 to Count - 1 do begin Result := Items[I].CanDelete; if not Result then Break; end; end; function TdxLayoutGroup.CanProcessAccel(out AItem: TdxCustomLayoutItem): Boolean; var I: Integer; begin Result := False; for I := 0 to VisibleCount - 1 do begin AItem := VisibleItems[I]; Result := AItem.CanProcessAccel(AItem); if Result then Break; end; end; function TdxLayoutGroup.CanRemove: Boolean; var I: Integer; begin Result := inherited CanRemove; if Result then for I := 0 to Count - 1 do begin Result := Items[I].CanRemove; if not Result then Break; end; end; procedure TdxLayoutGroup.ContainerChanged; var I: Integer; begin for I := 0 to Count - 1 do Items[I].Container := Container; end; procedure TdxLayoutGroup.DoPack; var I: Integer; ASomethingDone: Boolean; AGroup: TdxLayoutGroup; begin for I := Count - 1 downto 0 do Items[I].Pack; repeat ASomethingDone := False; if (Count = 0) and CanDestroy then begin Free; Exit; end; if Count = 1 then begin if Items[0] is TdxLayoutGroup then begin AGroup := TdxLayoutGroup(Items[0]); if AGroup.CanDestroy then begin LayoutDirection := AGroup.LayoutDirection; AGroup.MoveChildrenToParent; AGroup.Free; ASomethingDone := True; end; end; if not ASomethingDone and CanDestroy then begin Items[0].Move(Parent, Index); ASomethingDone := True; end; end; until not ASomethingDone; end; procedure TdxLayoutGroup.EnabledChanged; var I: Integer; begin for I := 0 to Count - 1 do Items[I].EnabledChanged; inherited; end; function TdxLayoutGroup.GetBaseName: string; begin Result := inherited GetBaseName + 'Group'; end; procedure TdxLayoutGroup.GetChildren(Proc: TGetChildProc; Root: TComponent); var I: Integer; begin inherited; for I := 0 to Count - 1 do if Items[I].Owner = Root then Proc(Items[I]); end; function TdxLayoutGroup.GetShowCaption: Boolean; begin Result := {#DG ShowBorder and }inherited GetShowCaption; end; function TdxLayoutGroup.GetViewInfoClass: TdxCustomLayoutItemViewInfoClass; begin Result := TdxCustomLayoutItemViewInfoClass(GetLayoutLookAndFeel.GetGroupViewInfoClass); end; procedure TdxLayoutGroup.Loaded; begin inherited; FIsUserDefined := False; end; procedure TdxLayoutGroup.LayoutLookAndFeelChanged; var I: Integer; begin inherited; for I := 0 to VisibleCount - 1 do VisibleItems[I].LayoutLookAndFeelChanged; end; procedure TdxLayoutGroup.LayoutLookAndFeelChanging; var I: Integer; begin inherited; for I := 0 to VisibleCount - 1 do VisibleItems[I].LayoutLookAndFeelChanging; end; function TdxLayoutGroup.ProcessDialogChar(ACharCode: Word): Boolean; var I: Integer; begin Result := inherited ProcessDialogChar(ACharCode); if not Result then for I := 0 to VisibleCount - 1 do begin Result := VisibleItems[I].ProcessDialogChar(ACharCode); if Result then Break; end; end; procedure TdxLayoutGroup.RestoreItemControlSize; var I: Integer; begin for I := 0 to Count - 1 do Items[I].RestoreItemControlSize; end; procedure TdxLayoutGroup.SetChildOrder(Child: TComponent; Order: Integer); begin inherited; (Child as TdxCustomLayoutItem).Index := Order; end; procedure TdxLayoutGroup.SetParentComponent(Value: TComponent); begin //#DG if Value is TdxCustomLayoutControl and not TdxCustomLayoutControl(Value).Items.IsLoading and not (csAncestor in ComponentState) then TdxCustomLayoutControl(Value).SetRootGroup(Self) else inherited; end; procedure TdxLayoutGroup.BeforeCalculateViewInfo; var I: Integer; begin BuildVisibleItemsList; for I := 0 to Count - 1 do Items[I].BeforeCalculateViewInfo; end; procedure TdxLayoutGroup.AfterCalculateViewInfo; var I: Integer; begin if ViewInfo <> nil then ViewInfo.Specific.SetControlVisibility; for I := 0 to Count - 1 do Items[I].AfterCalculateViewInfo; inherited; end; function TdxLayoutGroup.CanDestroy: Boolean; begin Result := Hidden and not IsRoot and not Locked; end; procedure TdxLayoutGroup.BuildVisibleItemsList; var I: Integer; begin FVisibleItems.Clear; for I := 0 to Count - 1 do if Items[I].GetVisible then FVisibleItems.Add(Items[I]); end; function TdxLayoutGroup.GetHelperClass: TdxLayoutGroupHelperClass; begin case LayoutDirection of ldHorizontal: Result := TdxLayoutHorizontalGroupHelper; ldVertical: Result := TdxLayoutVerticalGroupHelper; ldTabbed: Result := TdxLayoutTabbedGroupHelper; else raise EdxException.Create('TdxLayoutGroup.GetHelperClass fails'); end; end; function TdxLayoutGroup.AllowDrawChild(AChild: TdxCustomLayoutItem): Boolean; begin Result := (ViewInfo = nil) or ViewInfo.Specific.AllowDrawChild(AChild); end; procedure TdxLayoutGroup.ChangeItemIndex(AItem: TdxCustomLayoutItem; Value: Integer); begin if AItem.Index <> Value then begin FItems.Move(AItem.Index, Value); if AItem.GetVisible then begin BuildVisibleItemsList; Changed; end; end; end; procedure TdxLayoutGroup.ChangeItemVisibleIndex(AItem: TdxCustomLayoutItem; Value: Integer); begin ChangeItemIndex(AItem, GetItemIndex(Value)); end; function TdxLayoutGroup.GetItemIndex(AItemVisibleIndex: Integer): Integer; begin if (0 <= AItemVisibleIndex) and (AItemVisibleIndex < VisibleCount) then Result := VisibleItems[AItemVisibleIndex].Index else Result := Count; end; function TdxLayoutGroup.IndexOf(AItem: TdxCustomLayoutItem): Integer; begin Result := FItems.IndexOf(AItem); end; function TdxLayoutGroup.VisibleIndexOf(AItem: TdxCustomLayoutItem): Integer; begin Result := FVisibleItems.IndexOf(AItem); end; function TdxLayoutGroup.CreateGroup(AGroupClass: TdxLayoutGroupClass = nil): TdxLayoutGroup; begin Result := Container.CreateGroup(AGroupClass, Self); end; function TdxLayoutGroup.CreateItem(AItemClass: TdxCustomLayoutItemClass = nil): TdxCustomLayoutItem; begin Result := Container.CreateItem(AItemClass, Self); end; function TdxLayoutGroup.CreateItemForControl(AControl: TControl): TdxLayoutItem; begin Result := Container.CreateItemForControl(AControl, Self); end; function TdxLayoutGroup.CanMoveTo(AParent: TdxCustomLayoutItem): Boolean; begin Result := (AParent = nil) or inherited CanMoveTo(AParent) and not IsChildItem(AParent); end; procedure TdxLayoutGroup.MoveChildrenToParent; var AInsertionIndex, I: Integer; begin AInsertionIndex := Index; for I := Count - 1 downto 0 do Items[I].Move(Parent, AInsertionIndex); end; function TdxLayoutGroup.PutChildrenIntoHiddenGroup: TdxLayoutGroup; var I: Integer; begin Result := CreateGroup; Result.Hidden := True; Result.LayoutDirection := LayoutDirection; for I := Count - 2 downto 0 do Items[I].Move(Result, 0); end; { TdxLayoutItem } constructor TdxLayoutItem.Create(AOwner: TComponent); begin inherited; FControlOptions := GetControlOptionsClass.Create(Self); end; destructor TdxLayoutItem.Destroy; begin Control := nil; FControlOptions.Free; inherited; end; function TdxLayoutItem.GetCaptionOptions: TdxLayoutItemCaptionOptions; begin Result := TdxLayoutItemCaptionOptions(inherited CaptionOptions); end; function TdxLayoutItem.GetViewInfo: TdxLayoutItemViewInfo; begin Result := TdxLayoutItemViewInfo(inherited ViewInfo); end; procedure TdxLayoutItem.SetCaptionOptions(Value: TdxLayoutItemCaptionOptions); begin inherited CaptionOptions := Value; end; procedure TdxLayoutItem.SetControl(Value: TControl); procedure CheckValue; var AItem: TdxLayoutItem; begin if Value <> nil then begin if Value = Container then raise EdxException.Create(sdxLayoutControlContainerCannotBeControl); AItem := FContainer.FindItem(Value); if AItem <> nil then raise EdxException.Create(Format(sdxLayoutControlControlIsUsed, [Value.Name, AItem.Name])) end; end; procedure UnprepareControl; begin Control.RemoveFreeNotification(Self); if IsDesigning then with Control do ControlStyle := ControlStyle - [csNoDesignVisible]; FreeAndNil(FDesignSelectorControls); Control.WindowProc := FDefaultControlWndProc; FDefaultControlWndProc := nil; FreeAndNil(FControlAdapter); if IsDesigning and not (csDestroying in Control.ComponentState) then begin Control.Left := 0; Control.Top := 0; end; end; procedure PrepareControl; var ASelectorItem: TdxControlDesignSelectorItem; begin FDefaultControlWndProc := Control.WindowProc; Control.WindowProc := ControlWndProc; if IsDesigning then begin FDesignSelectorControls := TdxSatelliteControls.Create(True); ASelectorItem := TdxControlDesignSelectorItem(TdxSatelliteControls(FDesignSelectorControls).AddControl(TWinControl(Control), TdxControlDesignSelectorItem)); ASelectorItem.LayoutItem := Self; end; Control.FreeNotification(Self); if IsDesigning then with FControl do ControlStyle := ControlStyle + [csNoDesignVisible]; Control.Parent := Container; SaveOriginalControlSize; CreateControlAdapter; SaveOriginalControlSize; if HasWinControl and not TWinControl(Control).HandleAllocated then SaveControlSizeBeforeDestruction; end; begin if FControl <> Value then begin CheckValue; FControlLocked := True; try if FControl <> nil then UnprepareControl; FControl := Value; if Value <> nil then PrepareControl; finally FControlLocked := False; end; Changed; if Container.Customization then Container.UpdateCustomizationControls; end; end; function TdxLayoutItem.CanFocusControlOnCaptionClick: Boolean; begin Result := not Container.IsCustomization and Container.FocusControlOnItemCaptionClick and CanFocusControl; end; procedure TdxLayoutItem.CreateControlAdapter; begin FControlAdapter := dxLayoutControlAdapterDefs.GetAdapterClass(FControl).Create(Self); end; {procedure TdxLayoutItem.PostFree; begin Container.PostFree(Self); end;} function TdxLayoutItem.CanDelete: Boolean; begin Result := inherited CanDelete and (IsDesigning or not HasControl); end; function TdxLayoutItem.CanFocusOnClick(X, Y: Integer): Boolean; begin Result := CanFocusControlOnCaptionClick and ViewInfo.CaptionViewInfo.CanDoCaptionClick(X, Y); end; function TdxLayoutItem.CanProcessAccel(out AItem: TdxCustomLayoutItem): Boolean; begin Result := CanFocusControl and CanTabStopControl; if Result then AItem := Self; end; procedure TdxLayoutItem.ContainerChanged; procedure ResetControlParent; var ASavedControl: TControl; begin if Control.Parent <> Container then begin ASavedControl := Control; Control := nil; Control := ASavedControl; end; end; begin if HasControl and (Container <> nil) then ResetControlParent; end; procedure TdxLayoutItem.DoCaptionDown; begin if CanFocusControlOnCaptionClick then SetControlFocus; end; procedure TdxLayoutItem.EnabledChanged; begin inherited; SetControlEnablement; end; function TdxLayoutItem.GetParentManagedAlignVert: TdxLayoutAlignVert; begin Result := avTop; end; function TdxLayoutItem.GetBaseName: string; begin Result := inherited GetBaseName + 'Item'; end; function TdxLayoutItem.GetViewInfoClass: TdxCustomLayoutItemViewInfoClass; begin Result := TdxCustomLayoutItemViewInfoClass(GetLayoutLookAndFeel.GetItemViewInfoClass); end; procedure TdxLayoutItem.Init; var ACommonValue: Variant; function IsCommonValue(AValueIndex: Integer; var ACommonValue: Variant): Boolean; var I: Integer; AValue: Variant; function CheckValue(AItem: TdxCustomLayoutItem): Boolean; begin if AItem <> Self then case AValueIndex of 0..2: Result := AItem is TdxLayoutItem; // 3..4: Result := True; else Result := False; end else Result := False; end; function GetValue(AItem: TdxCustomLayoutItem): Variant; begin case AValueIndex of 0: Result := TdxLayoutItem(AItem).CaptionOptions.Layout; 1: Result := TdxLayoutItem(AItem).CaptionOptions.AlignHorz; 2: Result := TdxLayoutItem(AItem).CaptionOptions.AlignVert; // 3: Result := AItem.AlignHorz; // 4: Result := AItem.AlignVert; else Result := Null; end; end; begin Result := Parent <> nil; if not Result then Exit; Result := False; ACommonValue := Unassigned; for I := 0 to Parent.VisibleCount - 1 do if CheckValue(Parent.VisibleItems[I]) then begin AValue := GetValue(Parent.VisibleItems[I]); if VarIsEmpty(ACommonValue) then ACommonValue := AValue; Result := AValue = ACommonValue; if not Result then Break; end; end; begin inherited; if IsCommonValue(0, ACommonValue) then CaptionOptions.Layout := ACommonValue; if IsCommonValue(1, ACommonValue) then CaptionOptions.AlignHorz := ACommonValue; if IsCommonValue(2, ACommonValue) then CaptionOptions.AlignVert := ACommonValue; {if IsCommonValue(3, ACommonValue) then AlignHorz := ACommonValue; - items lose client alignment} {if IsCommonValue(4, ACommonValue) then AlignVert := ACommonValue; - because some controls cannot be made client aligned } end; procedure TdxLayoutItem.Loaded; begin inherited; if HasControl then SaveOriginalControlSize; end; procedure TdxLayoutItem.LayoutLookAndFeelChanged; begin inherited; if FControlAdapter <> nil then FControlAdapter.LayoutLookAndFeelChanged; end; procedure TdxLayoutItem.UpdateDesignSelectors; var AIndex: Integer; R: TRect; AItem: TdxControlDesignSelectorItem; begin if HasControl and (FDesignSelectorControls <> nil) then begin AIndex := TdxSatelliteControls(FDesignSelectorControls).FindByControl(Control); if AIndex <> -1 then begin AItem := TdxSatelliteControls(FDesignSelectorControls).Items[AIndex] as TdxControlDesignSelectorItem; R := ViewInfo.DesignSelectorRect; R := cxRectOffset(R, ViewInfo.ControlViewInfo.Bounds.TopLeft, False); AItem.SelectorBounds := R; end; end; end; procedure TdxLayoutItem.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if (Operation = opRemove) and (AComponent = FControl) then begin Control := nil; Free; // #DG // #DG PostFree; end; end; procedure TdxLayoutItem.ProcessAccel; begin SetControlFocus; end; procedure TdxLayoutItem.RestoreItemControlSize; begin if HasControl then Control.SetBounds(Control.Left, Control.Top, FOriginalControlSize.X, FOriginalControlSize.Y); end; procedure TdxLayoutItem.CustomizationMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Container.ShowDesignSelectors and IsDesigning and Container.Customization and HasControl and PtInRect(ViewInfo.DesignSelectorRect, Point(X, Y)) then Container.SelectComponent(Control, Shift) else inherited CustomizationMouseDown(Button, Shift, X, Y); end; procedure TdxLayoutItem.AfterCalculateViewInfo; begin SetControlVisibility; SetControlEnablement; inherited; end; function TdxLayoutItem.GetCaptionOptionsClass: TdxCustomLayoutItemCaptionOptionsClass; begin Result := TdxLayoutItemCaptionOptions; end; function TdxLayoutItem.GetControlOptionsClass: TdxLayoutItemControlOptionsClass; begin Result := TdxLayoutItemControlOptions; end; function TdxLayoutItem.CanFocusControl: Boolean; begin Result := HasWinControl and TWinControl(Control).CanFocus; end; function TdxLayoutItem.CanTabStopControl: Boolean; begin Result := HasWinControl and TWinControl(Control).TabStop; end; procedure TdxLayoutItem.ControlWndProc(var Message: TMessage); function IsControlMoved: Boolean; begin Result := (Message.LParam = 0) or (PWindowPos(Message.LParam)^.flags and SWP_NOMOVE = 0); end; function IsControlResized: Boolean; begin Result := (Message.LParam = 0) or (PWindowPos(Message.LParam)^.flags and SWP_NOSIZE = 0); end; function ControlSizeChanged: Boolean; begin Result := not cxPointIsEqual(Point(Control.Width, Control.Height), FOriginalControlSize); end; var ANeedProcessDefaultControlWndProc: Boolean; begin ANeedProcessDefaultControlWndProc := True; case Message.Msg of WM_NCHITTEST: if Container.Customization then begin Message.Result := HTTRANSPARENT; ANeedProcessDefaultControlWndProc := False; end; end; if ANeedProcessDefaultControlWndProc then FDefaultControlWndProc(Message); if not FControlLocked then with Message do case Msg of WM_CREATE: if (Control.Width <> ControlSizeBeforeDestruction.X) or (Control.Height <> ControlSizeBeforeDestruction.Y) then begin SaveOriginalControlSize; Changed; end; WM_DESTROY: SaveControlSizeBeforeDestruction; WM_SETFOCUS: MakeVisible; WM_WINDOWPOSCHANGED: if not Container.IsPlacingControls and (IsControlMoved or IsControlResized) then begin if IsControlResized and FControlAdapter.AllowCheckSize and ControlSizeChanged then SaveOriginalControlSize; Changed; end; CM_TABSTOPCHANGED: Container.ViewInfo.DoCalculateTabOrders; end; end; function TdxLayoutItem.HasControl: Boolean; begin Result := FControl <> nil; end; function TdxLayoutItem.HasWinControl: Boolean; begin Result := HasControl and (FControl is TWinControl); end; procedure TdxLayoutItem.SaveControlSizeBeforeDestruction; begin FControlSizeBeforeDestruction := Point(Control.Width, Control.Height); end; procedure TdxLayoutItem.SaveOriginalControlSize; begin if HasWinControl and CanAllocateHandle(TWinControl(FControl)) then TWinControl(FControl).HandleNeeded; // for cxEditors FOriginalControlSize := Point(FControl.Width, FControl.Height); end; procedure TdxLayoutItem.SetControlEnablement; begin if HasControl then Control.Enabled := EnabledForWork; end; procedure TdxLayoutItem.SetControlFocus; begin TWinControl(FControl).SetFocus; end; procedure TdxLayoutItem.SetControlVisibility; begin if HasControl then begin Control.Visible := ActuallyVisible and ViewInfo.ActuallyVisible; // to make the control invisible on showing if not Control.Visible then Control.SetBounds(10000, 10000, FOriginalControlSize.X, FOriginalControlSize.Y); end; end; { TdxLayoutControlViewInfo } constructor TdxLayoutControlViewInfo.Create(AControl: TdxCustomLayoutControl); begin inherited; CreateViewInfos; end; destructor TdxLayoutControlViewInfo.Destroy; begin DestroyViewInfos; FCanvas.Free; FreeAndNil(FSelectionLayer); inherited; end; procedure TdxLayoutControlViewInfo.CreateSelectionLayer; begin FSelectionLayer := TdxSelectionLayer.Create(Control, Control.Handle); end; procedure TdxLayoutControlViewInfo.BuildSelectionLayer; function CanBuildSelectionLayer: Boolean; var I: Integer; AList: TcxObjectList; AIntf: IdxLayoutSelectableItem; begin Result := (Control.IsDesigning or Control.Customization) and not Control.IsUpdateLocked; if Result then begin Result := False; AList := TcxObjectList.Create(False); try Control.GetSelection(AList); for I := 0 to AList.Count - 1 do begin if Supports(AList[I], IdxLayoutSelectableItem, AIntf) and AIntf.IsChild(Control) and AIntf.IsVisible then begin Result := True; AIntf := nil; Break; end; end; finally AList.Free; end; end; end; begin if CanBuildSelectionLayer then begin SelectionLayer.BoundsRect := ClientBounds; SelectionLayer.SelectionImage.Clear; ItemsViewInfo.PaintSelectionLayer; SelectionLayer.SelectionImage.RecoverAlphaChannel(0); SelectionLayer.Show; end else FreeAndNil(FSelectionLayer); end; function TdxLayoutControlViewInfo.GetClientHeight: Integer; begin Result := cxRectHeight(ClientBounds); end; function TdxLayoutControlViewInfo.GetClientWidth: Integer; begin Result := cxRectWidth(ClientBounds); end; function TdxLayoutControlViewInfo.GetContentHeight: Integer; begin Result := cxRectHeight(ContentBounds); end; function TdxLayoutControlViewInfo.GetContentWidth: Integer; begin Result := cxRectWidth(ContentBounds); end; function TdxLayoutControlViewInfo.GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin Result := FControl.GetLayoutLookAndFeel; end; function TdxLayoutControlViewInfo.GetSelectionLayer: TdxSelectionLayer; begin if FSelectionLayer = nil then CreateSelectionLayer; Result := FSelectionLayer; end; procedure TdxLayoutControlViewInfo.CreateViewInfos; begin if LayoutLookAndFeel <> nil then FItemsViewInfo := GetItemsViewInfoClass.Create(Self, nil, FControl.Items); end; procedure TdxLayoutControlViewInfo.DestroyViewInfos; begin FreeAndNil(FItemsViewInfo); end; function TdxLayoutControlViewInfo.GetItemsViewInfoClass: TdxLayoutGroupViewInfoClass; begin Result := TdxLayoutGroupViewInfoClass(FControl.Items.GetViewInfoClass); end; procedure TdxLayoutControlViewInfo.RecreateViewInfos; begin DestroyViewInfos; CreateViewInfos; end; procedure TdxLayoutControlViewInfo.AlignItems; var I: Integer; procedure ProcessConstraint(AConstraint: TdxLayoutAlignmentConstraint); var AItemViewInfos: TList; procedure RetrieveItemViewInfos; var I: Integer; AViewInfo: TdxCustomLayoutItemViewInfo; begin for I := 0 to AConstraint.Count - 1 do begin AViewInfo := AConstraint.Items[I].ViewInfo; if AViewInfo <> nil then AItemViewInfos.Add(AViewInfo); end; end; function GetSide: TdxLayoutSide; begin if AConstraint.Kind in [ackLeft, ackRight] then Result := sdLeft else Result := sdTop; end; function AlignItemViewInfos: Boolean; var AMaxBorderValue, I: Integer; function GetBorderValue(AItemViewInfoIndex: Integer): Integer; begin with TdxCustomLayoutItemViewInfo(AItemViewInfos[AItemViewInfoIndex]) do case AConstraint.Kind of ackLeft: Result := Bounds.Left - CalculateOffset(sdLeft); ackTop: Result := Bounds.Top - CalculateOffset(sdTop); ackRight: Result := Bounds.Right + CalculateOffset(sdRight); ackBottom: Result := Bounds.Bottom + CalculateOffset(sdBottom); else Result := 0; end; end; function FindMaxBorderValue: Integer; var I: Integer; begin Result := -MaxInt; for I := 0 to AItemViewInfos.Count - 1 do Result := Max(Result, GetBorderValue(I)); end; procedure ChangeOffset(AItemViewInfoIndex, ADelta: Integer); begin with TdxCustomLayoutItemViewInfo(AItemViewInfos[AItemViewInfoIndex]) do Offsets[GetSide] := Offsets[GetSide] + ADelta; end; function AreItemViewInfosAligned: Boolean; var I, ABorderValue: Integer; begin ABorderValue := 0; for I := 0 to AItemViewInfos.Count - 1 do if I = 0 then ABorderValue := GetBorderValue(I) else begin Result := GetBorderValue(I) = ABorderValue; if not Result then Exit; end; Result := True; end; begin AMaxBorderValue := FindMaxBorderValue; for I := 0 to AItemViewInfos.Count - 1 do ChangeOffset(I, AMaxBorderValue - GetBorderValue(I)); CalculateItemsViewInfo; Result := AreItemViewInfosAligned; end; procedure ResetOffsets; var I: Integer; begin for I := 0 to AItemViewInfos.Count - 1 do TdxCustomLayoutItemViewInfo(AItemViewInfos[I]).ResetOffset(GetSide); CalculateItemsViewInfo; end; begin AItemViewInfos := TList.Create; try RetrieveItemViewInfos; while not AlignItemViewInfos do //!!! to think about invisible items if items will be deleted begin ResetOffsets; if AItemViewInfos.Count > 2 then AItemViewInfos.Count := AItemViewInfos.Count - 1 else Break; end; finally AItemViewInfos.Free; end; end; begin for I := 0 to FControl.AlignmentConstraintCount - 1 do ProcessConstraint(FControl.AlignmentConstraints[I]); end; function CompareAllItemViewInfos(Item1, Item2: TdxLayoutItemViewInfo): Integer; begin Result := Ord(Item2.CaptionLayout) - Ord(Item1.CaptionLayout); end; function CompareItemViewInfos(Item1, Item2: TdxLayoutItemViewInfo): Integer; begin case Item1.CaptionLayout of clLeft: Result := Item1.Bounds.Left - Item2.Bounds.Left; clTop: Result := Item1.Bounds.Top - Item2.Bounds.Top; clRight: Result := Item1.Bounds.Right - Item2.Bounds.Right; clBottom: Result := Item1.Bounds.Bottom - Item2.Bounds.Bottom; else Result := 0; end; end; procedure TdxLayoutControlViewInfo.AutoAlignControls; var AAllItemViewInfos: TList; ACaptionLayout: TdxCaptionLayout; procedure FindAllItemViewInfos(ACustomItemViewInfo: TdxCustomLayoutItemViewInfo); var I: Integer; begin if ACustomItemViewInfo is TdxLayoutGroupViewInfo then with TdxLayoutGroupViewInfo(ACustomItemViewInfo) do for I := 0 to ItemViewInfoCount - 1 do FindAllItemViewInfos(ItemViewInfos[I]) else if TdxLayoutItemViewInfo(ACustomItemViewInfo).AutoControlAlignment then AAllItemViewInfos.Add(ACustomItemViewInfo); end; procedure SortAllItemViewInfos; begin AAllItemViewInfos.Sort(@CompareAllItemViewInfos); end; procedure ProcessItemViewInfos(ACaptionLayout: TdxCaptionLayout); var AItemViewInfos: TList; AGroupedCount: Integer; procedure ExtractItemViewInfos; var I, ACount: Integer; begin I := AAllItemViewInfos.Count - 1; while (I <> -1) and (TdxLayoutItemViewInfo(AAllItemViewInfos[I]).CaptionLayout = ACaptionLayout) do Dec(I); ACount := AAllItemViewInfos.Count - 1 - I; AItemViewInfos.Count := ACount; Move(AAllItemViewInfos.List^[I + 1], AItemViewInfos.List^[0], ACount * SizeOf(Pointer)); AAllItemViewInfos.Count := I + 1; end; procedure SortItemViewInfos; begin AItemViewInfos.Sort(@CompareItemViewInfos); end; function FindGroup: Boolean; var AItemViewInfo1, AItemViewInfo2: TdxLayoutItemViewInfo; begin AItemViewInfo1 := AItemViewInfos[0]; AGroupedCount := 1; while AGroupedCount < AItemViewInfos.Count do begin AItemViewInfo2 := AItemViewInfos[AGroupedCount]; if CompareItemViewInfos(AItemViewInfo1, AItemViewInfo2) <> 0 then Break; Inc(AGroupedCount); end; Result := AGroupedCount <> 1; end; procedure AlignControls; function IsCaptionLayoutHorizontal: Boolean; begin Result := ACaptionLayout in [clLeft, clRight]; end; function GetMaxCaptionSize: Integer; var I, ACaptionSize: Integer; begin Result := 0; for I := 0 to AGroupedCount - 1 do begin with TdxLayoutItemViewInfo(AItemViewInfos[I]).CaptionViewInfo do if IsCaptionLayoutHorizontal then ACaptionSize := Width else ACaptionSize := Height; Result := Max(Result, ACaptionSize); end; end; procedure AssignCaptionSizes(AMaxCaptionSize: Integer); var I: Integer; begin for I := 0 to AGroupedCount - 1 do with TdxLayoutItemViewInfo(AItemViewInfos[I]).CaptionViewInfo do if IsCaptionLayoutHorizontal then Width := AMaxCaptionSize else Height := AMaxCaptionSize; end; begin AssignCaptionSizes(GetMaxCaptionSize); CalculateItemsViewInfo; end; procedure RemoveProcessedItemViewInfos; begin Move(AItemViewInfos.List^[AGroupedCount], AItemViewInfos.List^[0], (AItemViewInfos.Count - AGroupedCount) * SizeOf(Pointer)); AItemViewInfos.Count := AItemViewInfos.Count - AGroupedCount; end; begin AItemViewInfos := TList.Create; try ExtractItemViewInfos; while AItemViewInfos.Count <> 0 do begin SortItemViewInfos; if FindGroup then AlignControls; RemoveProcessedItemViewInfos; end; finally AItemViewInfos.Free; end; end; begin AAllItemViewInfos := TList.Create; try FindAllItemViewInfos(ItemsViewInfo); SortAllItemViewInfos; for ACaptionLayout := Low(ACaptionLayout) to High(ACaptionLayout) do ProcessItemViewInfos(ACaptionLayout); finally AAllItemViewInfos.Free; end; end; procedure TdxLayoutControlViewInfo.CalculateItemsViewInfo; begin ResetContentBounds; ItemsViewInfo.Calculate(ContentBounds); end; procedure TdxLayoutControlViewInfo.CalculateTabOrders; var AAvailTabOrder: Integer; begin AAvailTabOrder := 0; ItemsViewInfo.CalculateTabOrders(AAvailTabOrder); end; function TdxLayoutControlViewInfo.GetIsTransparent: Boolean; begin Result := HasBackground; end; function TdxLayoutControlViewInfo.HasBackground: Boolean; begin Result := Control.HasBackground; end; function TdxLayoutControlViewInfo.NeedHighlightRoot: Boolean; begin Result := Control.HighlightRoot and Control.IsDesigning; end; procedure TdxLayoutControlViewInfo.PrepareData; begin RecreateViewInfos; end; procedure TdxLayoutControlViewInfo.ResetContentBounds; begin SetRectEmpty(FContentBounds); end; function TdxLayoutControlViewInfo.GetCanvas: TcxCanvas; begin if Control.HandleAllocated then begin FreeAndNil(FCanvas); Result := Control.Canvas; end else begin if FCanvas = nil then FCanvas := TcxScreenCanvas.Create; Result := FCanvas; end; end; function TdxLayoutControlViewInfo.GetClientBounds: TRect; begin Result := FControl.ClientBounds; end; function TdxLayoutControlViewInfo.GetContentBounds: TRect; function CalculateContentWidth: Integer; begin //#DG if acsWidth in Control.AutoContentSizes then if ItemsViewInfo.AlignHorz = ahClient then Result := Max(cxRectWidth(ClientBounds), ItemsViewInfo.MinWidth) else Result := ItemsViewInfo.CalculateWidth; end; function CalculateContentHeight: Integer; begin //#DG if acsHeight in Control.AutoContentSizes then if ItemsViewInfo.AlignVert = avClient then Result := Max(cxRectHeight(ClientBounds), ItemsViewInfo.MinHeight) else Result := ItemsViewInfo.CalculateHeight; end; begin if IsRectEmpty(FContentBounds) then FContentBounds := cxRectBounds(-Control.LeftPos, -Control.TopPos, CalculateContentWidth, CalculateContentHeight); Result := FContentBounds; end; procedure TdxLayoutControlViewInfo.Calculate; begin PrepareData; CalculateItemsViewInfo; AlignItems; if Control.AutoControlAlignment then begin AutoAlignControls; AlignItems; end; Control.CheckPositions; DoCalculateTabOrders; if Control.HandleAllocated then Control.IsPlaceControlsNeeded := True; end; procedure TdxLayoutControlViewInfo.DoCalculateTabOrders; begin if Control.AutoControlTabOrders then CalculateTabOrders; end; function TdxLayoutControlViewInfo.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; begin //{#MS if Control.Customization and PtInRect(Control.CustomizeForm.BoundsRect, Control.ClientToScreen(P)) then Result := TdxLayoutControlCustomizeForm(Control.CustomizeForm).GetHitTest(Control.CustomizeForm.ScreenToClient(Control.ClientToScreen(P))) else begin if PtInRect(ClientBounds, P) and not (Control.ShowDesignSelectors and PtInRect(Control.GetDesignSelectorRect, P)) then begin Result := ItemsViewInfo.GetHitTest(P); if Result = nil then Result := TdxLayoutClientAreaHitTest.Instance; end else Result := nil; end; if Result = nil then Result := TdxLayoutNoneHitTest.Instance; end; function TdxLayoutControlViewInfo.GetHitTest(X, Y: Integer): TdxCustomLayoutHitTest; begin Result := GetHitTest(Point(X, Y)); end; function TdxLayoutControlViewInfo.GetItemWithMouse(const P: TPoint): TdxCustomLayoutItem; begin Result := ItemsViewInfo.GetItemWithMouse(P); end; { TdxCustomLayoutElementViewInfo } procedure TdxCustomLayoutElementViewInfo.Calculate(const ABounds: TRect); begin FBounds := ABounds; end; { TdxCustomLayoutItemElementViewInfo } constructor TdxCustomLayoutItemElementViewInfo.Create(AItemViewInfo: TdxCustomLayoutItemViewInfo); begin inherited Create; FItemViewInfo := AItemViewInfo; end; function TdxCustomLayoutItemElementViewInfo.CalculateMinHeight: Integer; begin Result := 0; end; function TdxCustomLayoutItemElementViewInfo.CalculateMinWidth: Integer; begin Result := 0; end; function TdxCustomLayoutItemElementViewInfo.CalculateHeight: Integer; begin Result := 0; end; function TdxCustomLayoutItemElementViewInfo.CalculateWidth: Integer; begin Result := 0; end; function TdxCustomLayoutItemElementViewInfo.GetHeight: Integer; begin Result := FHeight; if Result = 0 then begin Result := cxRectHeight(Bounds); if Result = 0 then Result := CalculateHeight; end; end; function TdxCustomLayoutItemElementViewInfo.GetItem: TdxCustomLayoutItem; begin Result := FItemViewInfo.Item; end; function TdxCustomLayoutItemElementViewInfo.GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin Result := FItemViewInfo.LayoutLookAndFeel; end; function TdxCustomLayoutItemElementViewInfo.GetWidth: Integer; begin Result := FWidth; if Result = 0 then begin Result := cxRectWidth(Bounds); if Result = 0 then Result := CalculateWidth; end; end; procedure TdxCustomLayoutItemElementViewInfo.SetHeight(Value: Integer); begin FHeight := Value; end; procedure TdxCustomLayoutItemElementViewInfo.SetWidth(Value: Integer); begin FWidth := Value; end; function TdxCustomLayoutItemElementViewInfo.GetEnabled: Boolean; begin Result := FItemViewInfo.Enabled; end; function TdxCustomLayoutItemElementViewInfo.GetEnabledForWork: Boolean; begin Result := FItemViewInfo.EnabledForWork; end; function TdxCustomLayoutItemElementViewInfo.GetCursor(X, Y: Integer): TCursor; begin Result := crDefault; end; function TdxCustomLayoutItemElementViewInfo.GetVisible: Boolean; begin Result := False; end; procedure TdxCustomLayoutItemElementViewInfo.Invalidate(const ABounds: TRect); begin Item.Container.InvalidateRect(ABounds, False); end; procedure TdxCustomLayoutItemElementViewInfo.MouseEnter; begin end; procedure TdxCustomLayoutItemElementViewInfo.MouseLeave; begin Pressed := False; end; procedure TdxCustomLayoutItemElementViewInfo.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Pressed := True; end; procedure TdxCustomLayoutItemElementViewInfo.MouseMove(Shift: TShiftState; X, Y: Integer); begin end; procedure TdxCustomLayoutItemElementViewInfo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Pressed := False; end; function TdxCustomLayoutItemElementViewInfo.WantsMouse(X, Y: Integer): Boolean; begin Result := Visible and PtInRect(Bounds, Point(X, Y)); end; { TdxCustomLayoutItemCaptionViewInfo } function TdxCustomLayoutItemCaptionViewInfo.GetCanvas: TcxCanvas; begin Result := ItemViewInfo.ContainerViewInfo.Canvas; end; function TdxCustomLayoutItemCaptionViewInfo.GetIsCustomization: Boolean; begin Result := FItemViewInfo.IsCustomization; end; function TdxCustomLayoutItemCaptionViewInfo.GetTextHeight: Integer; var R: TRect; begin if Item.CachedTextHeight = 0 then begin PrepareCanvas; if MultiLine then begin R := Rect(0, 0, CalculateWidth - 1 {for disabling}, 0); Canvas.TextExtent(Text, R, CalculateTextFlags); Result := R.Bottom - R.Top; end else Result := Canvas.TextHeight(Text); Item.CachedTextHeight := Result; end else Result := Item.CachedTextHeight; if Text <> '' then Inc(Result); // for disabling end; function TdxCustomLayoutItemCaptionViewInfo.GetTextWidth: Integer; var AText: string; begin AText := VisibleText; PrepareCanvas; Result := Canvas.TextWidth(AText); if AText <> '' then Inc(Result); // for disabling end; procedure TdxCustomLayoutItemCaptionViewInfo.SetHotTracked(Value: Boolean); begin if FHotTracked <> Value then begin FHotTracked := Value; Invalidate(HotTrackBounds); end; end; function TdxCustomLayoutItemCaptionViewInfo.GetCursor(X, Y: Integer): TCursor; begin if HotTracked and (htsHandPoint in HotTrackStyles) then Result := crcxHandPoint else Result := inherited GetCursor(X, Y); end; function TdxCustomLayoutItemCaptionViewInfo.GetVisible: Boolean; begin Result := ItemViewInfo.HasCaption or (ItemViewInfo.IsDragImagePainted and ItemViewInfo.IsAvailable); end; procedure TdxCustomLayoutItemCaptionViewInfo.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited; if CanDoCaptionClick(X, Y) then Item.DoCaptionDown; end; procedure TdxCustomLayoutItemCaptionViewInfo.MouseLeave; begin inherited; HotTracked := False; end; procedure TdxCustomLayoutItemCaptionViewInfo.MouseMove(Shift: TShiftState; X, Y: Integer); begin inherited; if IsHotTrackable then HotTracked := IsPointInHotTrackBounds(Point(X, Y)); end; procedure TdxCustomLayoutItemCaptionViewInfo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var APressed: Boolean; begin APressed := Pressed; inherited; if CanDoCaptionClick(X, Y) and APressed then Item.DoCaptionClick; end; function TdxCustomLayoutItemCaptionViewInfo.GetColor: TColor; begin Result := ItemViewInfo.Color; end; function TdxCustomLayoutItemCaptionViewInfo.GetFont: TFont; begin Result := Options.GetFont(Item.Container); end; function TdxCustomLayoutItemCaptionViewInfo.GetHotTrackBounds: TRect; begin Result := TextAreaBounds; end; function TdxCustomLayoutItemCaptionViewInfo.GetHotTrackStyles: TdxLayoutHotTrackStyles; begin Result := Options.HotTrackStyles; end; function TdxCustomLayoutItemCaptionViewInfo.GetIsDefaultColor: Boolean; begin Result := ItemViewInfo.IsDefaultColor; end; function TdxCustomLayoutItemCaptionViewInfo.GetIsHotTrackable: Boolean; begin Result := not IsCustomization and EnabledForWork and Options.HotTrack; end; function TdxCustomLayoutItemCaptionViewInfo.CalculateTextFlags: Integer; const MultiLines: array[Boolean] of Integer = (cxSingleLine, cxWordBreak); AlignsVert: array[TdxAlignmentVert] of Integer = (cxAlignTop, cxAlignVCenter, cxAlignBottom); begin Result := MultiLines[MultiLine] or cxAlignmentsHorz[AlignHorz] or AlignsVert[AlignVert]; if Item.CaptionOptions.ShowAccelChar then Inc(Result, cxShowPrefix); end; function TdxCustomLayoutItemCaptionViewInfo.CanDoCaptionClick(X, Y: Integer): Boolean; begin Result := EnabledForWork and IsPointInHotTrackBounds(Point(X, Y)); end; function TdxCustomLayoutItemCaptionViewInfo.GetAlignHorz: TAlignment; begin Result := Item.CaptionOptions.AlignHorz; end; function TdxCustomLayoutItemCaptionViewInfo.GetIsTextUnderlined: Boolean; begin Result := IsHotTrackable and not HotTracked and (htsUnderlineCold in HotTrackStyles) or HotTracked and (htsUnderlineHot in HotTrackStyles); end; function TdxCustomLayoutItemCaptionViewInfo.GetIsTransparent: Boolean; begin Result := ItemViewInfo.ContainerViewInfo.HasBackground and IsDefaultColor; end; function TdxCustomLayoutItemCaptionViewInfo.GetOptions: TdxLayoutLookAndFeelCaptionOptions; begin Result := ItemViewInfo.Options.CaptionOptions; end; function TdxCustomLayoutItemCaptionViewInfo.GetText: string; begin Result := Item.Caption; end; function TdxCustomLayoutItemCaptionViewInfo.GetTextAreaBounds: TRect; begin Result := Bounds; if Enabled and (Text <> '') then with Result do begin Dec(Right); Dec(Bottom); end; end; function TdxCustomLayoutItemCaptionViewInfo.GetTextColor: TColor; begin if HotTracked then Result := GetTextHotColor else Result := GetTextNormalColor; end; function TdxCustomLayoutItemCaptionViewInfo.GetTextHotColor: TColor; begin Result := Options.GetTextHotColor; end; function TdxCustomLayoutItemCaptionViewInfo.GetTextNormalColor: TColor; begin Result := Options.GetTextColor; end; function TdxCustomLayoutItemCaptionViewInfo.GetVisibleText: string; begin Result := Text; if Item.CaptionOptions.ShowAccelChar then Result := StripHotKey(Result); end; function TdxCustomLayoutItemCaptionViewInfo.IsPointInHotTrackBounds(const P: TPoint): Boolean; var ABounds: TRectArray; I: Integer; begin Result := False; PrepareCanvas; Canvas.GetTextStringsBounds(Text, TextAreaBounds, CalculateTextFlags, Enabled, ABounds); try for I := 0 to High(ABounds) do begin Result := PtInRect(ABounds[I], P); if Result then Break; end; finally ABounds := nil; end; end; procedure TdxCustomLayoutItemCaptionViewInfo.PrepareCanvas; begin Canvas.Font := Font; end; function TdxCustomLayoutItemCaptionViewInfo.CalculateHeight: Integer; begin if Visible then Result := TextHeight else Result := 0; end; function TdxCustomLayoutItemCaptionViewInfo.CalculateWidth: Integer; begin if Visible then Result := TextWidth else Result := 0; end; { TdxCustomLayoutItemViewInfo } constructor TdxCustomLayoutItemViewInfo.Create(AContainerViewInfo: TdxLayoutControlViewInfo; AParentViewInfo: TdxLayoutGroupViewInfo; AItem: TdxCustomLayoutItem); begin inherited Create; FContainerViewInfo := AContainerViewInfo; FParentViewInfo := AParentViewInfo; FNotifyComponent := TcxFreeNotificator.Create(nil); FNotifyComponent.OnFreeNotification := FreeNotification; FItem := AItem; FItem.FViewInfo := Self; FItem.FreeNotification(FNotifyComponent); CreateViewInfos; end; destructor TdxCustomLayoutItemViewInfo.Destroy; begin DestroyViewInfos; if FItem <> nil then FItem.FViewInfo := nil; FreeAndNil(FNotifyComponent); inherited; end; function TdxCustomLayoutItemViewInfo.GetAlignHorz: TdxLayoutAlignHorz; begin //#DG Result := Item.AlignHorz; Result := Item.GetRealAlignHorz; end; function TdxCustomLayoutItemViewInfo.GetAlignVert: TdxLayoutAlignVert; begin //#DG Result := Item.AlignVert; Result := Item.GetRealAlignVert; end; function TdxCustomLayoutItemViewInfo.GetBackgroundBounds: TRect; begin if IsDragImagePainted then Result := SelectionBorderRect else Result := Bounds; end; function TdxCustomLayoutItemViewInfo.GetCanPaint: Boolean; begin Result := ActuallyVisible or IsDragImagePainted and (IsDragged or IsDraggedWithParent and ParentViewInfo.CanPaint and ParentViewInfo.Specific.AllowDrawChild(Item)); end; function TdxCustomLayoutItemViewInfo.GetIsAvailable: Boolean; begin Result := Item.IsAvailable; end; function TdxCustomLayoutItemViewInfo.GetIsCustomization: Boolean; begin Result := FItem.Container.IsCustomization; end; function TdxCustomLayoutItemViewInfo.GetIsDragged: Boolean; begin Result := Item.IsDragged; end; function TdxCustomLayoutItemViewInfo.GetIsDraggedWithParent: Boolean; begin Result := (ParentViewInfo <> nil) and (ParentViewInfo.IsDragged or ParentViewInfo.IsDraggedWithParent); end; function TdxCustomLayoutItemViewInfo.GetIsDragImagePainted: Boolean; begin Result := ContainerViewInfo.IsDragImagePainted; end; function TdxCustomLayoutItemViewInfo.GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin Result := Item.GetLayoutLookAndFeel; end; procedure TdxCustomLayoutItemViewInfo.PaintSelectionLayer; var ABitmap, ABackgroundBitmap: TcxAlphaBitmap; begin if Selected and ActuallyVisible then begin ABitmap := ContainerViewInfo.SelectionLayer.SelectionImage; ABackgroundBitmap := TcxAlphaBitmap.CreateSize(SelectionBorderRect); try ABackgroundBitmap.cxCanvas.FillRect(ABackgroundBitmap.ClientRect, dxLayoutControlSelectionDefaultColor); ABackgroundBitmap.SetAlphaChannel(dxLayoutSelectionDefaultAlphaChannel); ABitmap.CopyBitmap(ABackgroundBitmap, SelectionBorderRect, cxNullPoint); finally ABackgroundBitmap.Free; end; dxDrawSelectionMarkers(ABitmap.cxCanvas, SelectionBorderRect, dxLayoutSelectionBorderDefaultColor, dxLayoutSelectionBorderMarkerInnerDefaultColor, dxSelectionMarkerWidth); ABitmap.cxCanvas.FrameRect(SelectionBorderRect, dxLayoutSelectionBorderDefaultColor, 1, cxBordersAll, True); end; end; function TdxCustomLayoutItemViewInfo.IsParentLocked: Boolean; begin Result := (ParentViewInfo <> nil) and ParentViewInfo.IsLocked; end; function TdxCustomLayoutItemViewInfo.IsParentSelected: Boolean; begin Result := (ParentViewInfo <> nil) and (ParentViewInfo.Selected or ParentViewInfo.IsParentSelected); end; function TdxCustomLayoutItemViewInfo.GetMinHeight: Integer; begin if AlignVert = avClient then Result := CalculateMinHeight else Result := CalculateHeight; end; function TdxCustomLayoutItemViewInfo.GetMinWidth: Integer; begin if AlignHorz = ahClient then Result := CalculateMinWidth else Result := CalculateWidth; end; function TdxCustomLayoutItemViewInfo.GetHeight: Integer; begin Result := CalculateHeight; end; function TdxCustomLayoutItemViewInfo.GetWidth: Integer; begin Result := CalculateWidth; end; function TdxCustomLayoutItemViewInfo.GetOffset(ASide: TdxLayoutSide): Integer; begin Result := FOffsets[ASide]; if Result = 0 then Result := CalculateOffset(ASide); end; function TdxCustomLayoutItemViewInfo.GetOffsetsHeight: Integer; begin Result := Offsets[sdTop] + Offsets[sdBottom]; end; function TdxCustomLayoutItemViewInfo.GetOffsetsWidth: Integer; begin Result := Offsets[sdLeft] + Offsets[sdRight]; end; function TdxCustomLayoutItemViewInfo.GetSelected: Boolean; begin Result := Item.Container.IsComponentSelected(Item); end; function TdxCustomLayoutItemViewInfo.GetSelectionBorderRect: TRect; function CanUseSelectionOffset: Boolean; begin Result := (ParentViewInfo = nil) or (ParentViewInfo.UseItemOffset and (ParentViewInfo.ItemOffset > Integer(dxLayoutSelectionOffset) div 2)); end; function GetSelectionBoundsOffset: Integer; begin if CanUseSelectionOffset then Result := dxLayoutSelectionOffset else Result := 0; if Item.IsRoot then Result := -Result; end; var ABoundsOffset: Integer; begin Result := Bounds; ABoundsOffset := GetSelectionBoundsOffset; InflateRect(Result, ABoundsOffset, ABoundsOffset); end; function TdxCustomLayoutItemViewInfo.GetSelectionArea: TRect; begin Result := SelectionBorderRect; InflateRect(Result, dxSelectionMarkerWidth div 2, dxSelectionMarkerWidth div 2); end; procedure TdxCustomLayoutItemViewInfo.SetElementWithMouse(Value: TdxCustomLayoutItemElementViewInfo); begin if FElementWithMouse <> Value then begin if FElementWithMouse <> nil then FElementWithMouse.MouseLeave; FElementWithMouse := Value; if FElementWithMouse <> nil then FElementWithMouse.MouseEnter; end; end; procedure TdxCustomLayoutItemViewInfo.SetOffset(ASide: TdxLayoutSide; Value: Integer); begin FOffsets[ASide] := Value; end; function TdxCustomLayoutItemViewInfo.CreateHitTest: TdxCustomLayoutItemHitTest; begin Result := GetHitTestClass.Instance as TdxCustomLayoutItemHitTest; Result.Item := Item; end; procedure TdxCustomLayoutItemViewInfo.FreeNotification(AComponent: TComponent); begin FItem := nil; end; procedure TdxCustomLayoutItemViewInfo.DoCreateViewInfos; begin FCaptionViewInfo := GetCaptionViewInfoClass.Create(Self); FElements.Add(FCaptionViewInfo); end; procedure TdxCustomLayoutItemViewInfo.CreateViewInfos; begin FElements := TObjectList.Create; DoCreateViewInfos; end; procedure TdxCustomLayoutItemViewInfo.DestroyViewInfos; begin FreeAndNil(FElements); end; function TdxCustomLayoutItemViewInfo.CanDrawBackground: Boolean; begin Result := HasBackground; end; function TdxCustomLayoutItemViewInfo.GetBackgroundColor: TColor; begin if IsDragImagePainted then Result := dxLayoutSelectionDefaultColor else Result := Color; end; function TdxCustomLayoutItemViewInfo.CalculateMinHeight: Integer; begin Result := DoCalculateHeight(True); end; function TdxCustomLayoutItemViewInfo.CalculateMinWidth: Integer; begin Result := DoCalculateWidth(True); end; function TdxCustomLayoutItemViewInfo.CalculateOffset(ASide: TdxLayoutSide): Integer; begin case ASide of sdLeft: Result := Item.Offsets.Left; sdRight: Result := Item.Offsets.Right; sdTop: Result := Item.Offsets.Top; sdBottom: Result := Item.Offsets.Bottom; else Result := 0; end; end; function TdxCustomLayoutItemViewInfo.GetAreaPart(const P: TPoint): TdxLayoutAreaPart; const Parts: array[Boolean, Boolean] of TdxLayoutAreaPart = ((apBottom, apRight), (apLeft, apTop)); function GetSign(const P1, P2, P: TPoint): Integer; begin Result := (P.X - P1.X) * (P2.Y - P1.Y) - (P.Y - P1.Y) * (P2.X - P1.X); end; var ASign1, ASign2: Integer; begin with Bounds do begin ASign1 := GetSign(Point(Left, Bottom), Point(Right, Top), P); ASign2 := GetSign(TopLeft, BottomRight, P); end; Result := Parts[ASign1 >= 0, ASign2 >= 0]; end; function TdxCustomLayoutItemViewInfo.GetActuallyVisible: Boolean; begin Result := Item.ActuallyVisible; end; function TdxCustomLayoutItemViewInfo.DoCalculateHeight(AIsMinHeight: Boolean): Integer; begin Result := OffsetsHeight; end; function TdxCustomLayoutItemViewInfo.DoCalculateWidth(AIsMinWidth: Boolean): Integer; begin Result := OffsetsWidth; end; function TdxCustomLayoutItemViewInfo.GetCursor(X, Y: Integer): TCursor; var I: Integer; begin for I := 0 to ElementCount - 1 do if Elements[I].WantsMouse(X, Y) then begin Result := Elements[I].GetCursor(X, Y); Exit; end; Result := crDefault; end; function TdxCustomLayoutItemViewInfo.GetElement(AIndex: Integer): TdxCustomLayoutItemElementViewInfo; begin if (AIndex >= 0) and (AIndex < GetElementCount) then Result := TdxCustomLayoutItemElementViewInfo(FElements[AIndex]) else Result := nil; end; function TdxCustomLayoutItemViewInfo.GetElementCount: Integer; begin Result := FElements.Count; end; function TdxCustomLayoutItemViewInfo.GetEnabled: Boolean; begin Result := Item.Enabled; end; function TdxCustomLayoutItemViewInfo.GetEnabledForWork: Boolean; begin Result := Item.EnabledForWork; end; function TdxCustomLayoutItemViewInfo.GetIsTransparent: Boolean; begin Result := ContainerViewInfo.HasBackground and IsDefaultColor; end; function TdxCustomLayoutItemViewInfo.HasBackground: Boolean; begin Result := (ParentViewInfo = nil) {IsRoot} or (LayoutLookAndFeel <> ParentViewInfo.LayoutLookAndFeel) or IsDragImagePainted and IsDragged; end; function TdxCustomLayoutItemViewInfo.HasCaption: Boolean; begin Result := Item.HasCaption; end; function TdxCustomLayoutItemViewInfo.HasBorder: Boolean; begin Result := False; end; procedure TdxCustomLayoutItemViewInfo.MouseEnter; begin end; procedure TdxCustomLayoutItemViewInfo.MouseLeave; begin ElementWithMouse := nil; end; procedure TdxCustomLayoutItemViewInfo.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if ElementWithMouse <> nil then ElementWithMouse.MouseDown(Button, Shift, X, Y); end; procedure TdxCustomLayoutItemViewInfo.MouseMove(Shift: TShiftState; X, Y: Integer); var I: Integer; begin for I := 0 to ElementCount - 1 do if Elements[I].WantsMouse(X, Y) then begin ElementWithMouse := Elements[I]; Elements[I].MouseMove(Shift, X, Y); Exit; end; ElementWithMouse := nil; end; procedure TdxCustomLayoutItemViewInfo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if ElementWithMouse <> nil then ElementWithMouse.MouseUp(Button, Shift, X, Y); end; procedure TdxCustomLayoutItemViewInfo.Calculate(const ABounds: TRect); begin inherited; Inc(FBounds.Left, Offsets[sdLeft]); Inc(FBounds.Top, Offsets[sdTop]); Dec(FBounds.Right, Offsets[sdRight]); Dec(FBounds.Bottom, Offsets[sdBottom]); end; function TdxCustomLayoutItemViewInfo.CalculateHeight: Integer; begin Result := DoCalculateHeight(False); end; function TdxCustomLayoutItemViewInfo.CalculateWidth: Integer; begin Result := DoCalculateWidth(False); end; function TdxCustomLayoutItemViewInfo.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; begin if not IsParentLocked and PtInRect(Bounds, P) and ActuallyVisible then Result := CreateHitTest else Result := nil; end; function TdxCustomLayoutItemViewInfo.GetItemWithMouse(const P: TPoint): TdxCustomLayoutItem; begin if not IsParentLocked and PtInRect(Bounds, P) and ActuallyVisible then Result := Item else Result := nil; end; procedure TdxCustomLayoutItemViewInfo.ResetOffset(ASide: TdxLayoutSide); begin FOffsets[ASide] := 0; end; { TdxLayoutItemCaptionViewInfo } function TdxLayoutItemCaptionViewInfo.GetItem: TdxLayoutItem; begin Result := TdxLayoutItem(inherited GetItem); end; function TdxLayoutItemCaptionViewInfo.GetItemViewInfo: TdxLayoutItemViewInfo; begin Result := TdxLayoutItemViewInfo(inherited ItemViewInfo); end; function TdxLayoutItemCaptionViewInfo.GetAlignVert: TdxAlignmentVert; begin Result := Item.CaptionOptions.AlignVert; end; function TdxLayoutItemCaptionViewInfo.GetIsFixedWidth: Boolean; begin Result := Item.CaptionOptions.Width <> 0; end; function TdxLayoutItemCaptionViewInfo.GetMultiLine: Boolean; begin Result := IsFixedWidth; end; function TdxLayoutItemCaptionViewInfo.GetTextAreaBounds: TRect; var ADelta: Integer; begin Result := inherited GetTextAreaBounds; if IsFixedWidth then with Result do begin ADelta := Width - CalculateWidth; case AlignHorz of taLeftJustify: Dec(Right, ADelta); taRightJustify: Inc(Left, ADelta); taCenter: begin Inc(Left, ADelta div 2); Dec(Right, ADelta - ADelta div 2); end; end; end; end; function TdxLayoutItemCaptionViewInfo.CalculateWidth: Integer; begin if Visible and IsFixedWidth then Result := Item.CaptionOptions.Width else Result := inherited CalculateWidth; end; function TdxLayoutItemCaptionViewInfo.CalculateMinWidth: Integer; begin if FWidth = 0 then Result := CalculateWidth else Result := Width; end; { TdxLayoutItemControlViewInfo } function TdxLayoutItemControlViewInfo.GetBorderColor: TColor; begin Result := ItemViewInfo.Options.GetControlBorderColor; end; function TdxLayoutItemControlViewInfo.GetBorderStyle: TdxLayoutBorderStyle; begin Result := ItemViewInfo.Options.ControlBorderStyle; end; function TdxLayoutItemControlViewInfo.GetControl: TControl; begin Result := Item.Control; end; function TdxLayoutItemControlViewInfo.GetItem: TdxLayoutItem; begin Result := TdxLayoutItem(inherited Item); end; function TdxLayoutItemControlViewInfo.GetItemViewInfo: TdxLayoutItemViewInfo; begin Result := TdxLayoutItemViewInfo(inherited ItemViewInfo); end; function TdxLayoutItemControlViewInfo.GetOpaqueControl: Boolean; begin Result := Item.ControlOptions.Opaque; end; function TdxLayoutItemControlViewInfo.GetVisible: Boolean; begin Result := ItemViewInfo.HasControl and not ItemViewInfo.IsAvailable; end; function TdxLayoutItemControlViewInfo.CalculateControlBounds: TRect; begin Result := Bounds; Inc(Result.Left, BorderWidths[sdLeft]); Dec(Result.Right, BorderWidths[sdRight]); Inc(Result.Top, BorderWidths[sdTop]); Dec(Result.Bottom, BorderWidths[sdBottom]); end; function TdxLayoutItemControlViewInfo.GetBorderWidth(ASide: TdxLayoutSide): Integer; begin if HasBorder then Result := LayoutLookAndFeel.ItemControlBorderWidths[ASide] else Result := 0 end; function TdxLayoutItemControlViewInfo.GetControlAreaHeight(AControlHeight: Integer): Integer; begin Result := BorderWidths[sdTop] + AControlHeight + BorderWidths[sdBottom]; end; function TdxLayoutItemControlViewInfo.GetControlAreaWidth(AControlWidth: Integer): Integer; begin Result := BorderWidths[sdLeft] + AControlWidth + BorderWidths[sdRight]; end; function TdxLayoutItemControlViewInfo.HasBorder: Boolean; begin Result := Item.ControlOptions.ShowBorder and not ItemViewInfo.IsAvailable; end; procedure TdxLayoutItemControlViewInfo.Calculate(const ABounds: TRect); begin inherited; FControlBounds := CalculateControlBounds; end; procedure TdxLayoutItemControlViewInfo.CalculateTabOrder(var AAvailTabOrder: Integer); begin if Item.HasWinControl then begin TWinControl(Control).TabOrder := AAvailTabOrder; Inc(AAvailTabOrder); end; end; function TdxLayoutItemControlViewInfo.CalculateMinHeight: Integer; begin if Item.ControlOptions.FixedSize then Result := CalculateHeight else if Visible then Result := GetControlAreaHeight(Item.ControlOptions.MinHeight) else Result := 0; end; function TdxLayoutItemControlViewInfo.CalculateMinWidth: Integer; begin if Item.ControlOptions.FixedSize then Result := CalculateWidth else if Visible then Result := GetControlAreaWidth(Item.ControlOptions.MinWidth) else Result := 0; end; function TdxLayoutItemControlViewInfo.CalculateHeight: Integer; begin if Visible then Result := GetControlAreaHeight(Item.OriginalControlSize.Y) else Result := 0; end; function TdxLayoutItemControlViewInfo.CalculateWidth: Integer; begin if Visible then Result := GetControlAreaWidth(Item.OriginalControlSize.X) else Result := 0; end; { TdxLayoutItemViewInfo } function TdxLayoutItemViewInfo.GetCaptionViewInfo: TdxLayoutItemCaptionViewInfo; begin Result := TdxLayoutItemCaptionViewInfo(inherited CaptionViewInfo); end; function TdxLayoutItemViewInfo.GetItem: TdxLayoutItem; begin Result := TdxLayoutItem(inherited Item); end; function TdxLayoutItemViewInfo.GetOptionsEx: TdxLayoutLookAndFeelItemOptions; begin Result := TdxLayoutLookAndFeelItemOptions(inherited Options); end; function TdxLayoutItemViewInfo.GetDesignSelectorRect: TRect; const Offset = 3; Width = 10; var AControlBounds: TRect; begin AControlBounds := ControlViewInfo.ControlBounds; Result := AControlBounds; Result.Left := Result.Right - Width; if cxRectWidth(AControlBounds) >= 2 * Offset + Width then OffsetRect(Result, -Offset, 0); Result.Top := Result.Bottom - Width; if cxRectHeight(AControlBounds) >= 2 * Offset + Width then OffsetRect(Result, 0, -Offset); end; procedure TdxLayoutItemViewInfo.DoCreateViewInfos; begin inherited; FControlViewInfo := GetControlViewInfoClass.Create(Self); FElements.Add(FControlViewInfo); end; function TdxLayoutItemViewInfo.GetCaptionViewInfoClass: TdxCustomLayoutItemCaptionViewInfoClass; begin Result := TdxLayoutItemCaptionViewInfo; end; function TdxLayoutItemViewInfo.GetControlViewInfoClass: TdxLayoutItemControlViewInfoClass; begin Result := TdxLayoutItemControlViewInfo; end; function TdxLayoutItemViewInfo.GetHitTestClass: TdxCustomLayoutItemHitTestClass; begin Result := TdxLayoutItemHitTest; end; function TdxLayoutItemViewInfo.GetPainterClass: TdxCustomLayoutItemPainterClass; begin Result := TdxCustomLayoutItemPainterClass(LayoutLookAndFeel.GetItemPainterClass); end; procedure TdxLayoutItemViewInfo.CalculateViewInfosBounds(var ACaptionBounds, AControlBounds: TRect); var ACaptionSize, AControlSize: TPoint; ACaptionVisible, AControlVisible: Boolean; procedure CalculateElementViewInfoSize(AElementViewInfo: TdxCustomLayoutItemElementViewInfo; var ASize: TPoint; var AVisible: Boolean); begin AVisible := AElementViewInfo.Visible; if AVisible then ASize := Point(AElementViewInfo.Width, AElementViewInfo.Height) else ASize := cxNullPoint; AVisible := AVisible and not cxPointIsEqual(ASize, cxNullPoint); //AVisible := AVisible and (ASize.X <> 0) and (ASize.Y <> 0); end; procedure CalculateMainBounds; procedure InitBounds(var ABounds: TRect; const ASize: TPoint; AVisible: Boolean); begin if AVisible then ABounds := ContentBounds else SetRectEmpty(ABounds); end; procedure CalculateWithFixedControl; begin case CaptionLayout of clLeft: begin AControlBounds.Left := AControlBounds.Right - AControlSize.X; ACaptionBounds.Right := AControlBounds.Left - ControlOffsetHorz; end; clTop: begin AControlBounds.Top := AControlBounds.Bottom - AControlSize.Y; ACaptionBounds.Bottom := AControlBounds.Top - ControlOffsetVert; end; clRight: begin AControlBounds.Right := AControlBounds.Left + AControlSize.X; ACaptionBounds.Left := AControlBounds.Right + ControlOffsetHorz; end; clBottom: begin AControlBounds.Bottom := AControlBounds.Top + AControlSize.Y; ACaptionBounds.Top := AControlBounds.Bottom + ControlOffsetVert; end; end end; procedure CalculateWithFixedCaption; begin case CaptionLayout of clLeft: begin ACaptionBounds.Right := ACaptionBounds.Left + ACaptionSize.X; AControlBounds.Left := ACaptionBounds.Right + ControlOffsetHorz; end; clTop: begin ACaptionBounds.Bottom := ACaptionBounds.Top + ACaptionSize.Y; AControlBounds.Top := ACaptionBounds.Bottom + ControlOffsetVert; end; clRight: begin ACaptionBounds.Left := ACaptionBounds.Right - ACaptionSize.X; AControlBounds.Right := ACaptionBounds.Left - ControlOffsetHorz; end; clBottom: begin ACaptionBounds.Top := ACaptionBounds.Bottom - ACaptionSize.Y; AControlBounds.Bottom := ACaptionBounds.Top - ControlOffsetVert; end; end; end; begin InitBounds(ACaptionBounds, ACaptionSize, ACaptionVisible); InitBounds(AControlBounds, AControlSize, AControlVisible); if ACaptionVisible and AControlVisible then if Item.ControlOptions.FixedSize then CalculateWithFixedControl else CalculateWithFixedCaption else if AControlVisible and Item.ControlOptions.FixedSize then begin AControlBounds.Right := AControlBounds.Left + AControlSize.X; AControlBounds.Bottom := AControlBounds.Top + AControlSize.Y; end; end; procedure CalculateRestBounds(var ABounds: TRect; const ASize: TPoint; AAlignHorz: TAlignment; AAlignVert: TdxAlignmentVert); begin with ABounds do case CaptionLayout of clLeft, clRight: case AAlignVert of tavTop: Bottom := Top + ASize.Y; tavCenter: begin Top := (Top + Bottom - ASize.Y) div 2; Bottom := Top + ASize.Y; end; tavBottom: Top := Bottom - ASize.Y; end; clTop, clBottom: case AAlignHorz of taLeftJustify: Right := Left + ASize.X; taCenter: begin Left := (Left + Right - ASize.X) div 2; Right := Left + ASize.X; end; taRightJustify: Left := Right - ASize.X; end; end; end; begin CalculateElementViewInfoSize(CaptionViewInfo, ACaptionSize, ACaptionVisible); CalculateElementViewInfoSize(ControlViewInfo, AControlSize, AControlVisible); CalculateMainBounds; if ACaptionVisible then begin CalculateRestBounds(ACaptionBounds, ACaptionSize, Item.CaptionOptions.AlignHorz, Item.CaptionOptions.AlignVert); if AControlVisible and ((AlignHorz <> ahClient) or (CaptionLayout in [clLeft, clRight])) and ((AlignVert <> avClient) or (CaptionLayout in [clTop, clBottom])) then CalculateRestBounds(AControlBounds, AControlSize, taLeftJustify, tavTop); end; end; function TdxLayoutItemViewInfo.DoCalculateHeight(AIsMinHeight: Boolean): Integer; var AHeight: Integer; begin Result := CaptionViewInfo.Height; if AIsMinHeight then AHeight := ControlViewInfo.CalculateMinHeight else AHeight := ControlViewInfo.CalculateHeight; case CaptionLayout of clLeft, clRight: Result := Max(Result, AHeight); clTop, clBottom: begin if (Result <> 0) and ControlViewInfo.Visible{(AHeight <> 0)} then Inc(Result, ControlOffsetVert); Inc(Result, AHeight); end; else Result := 0; end; Inc(Result, inherited DoCalculateHeight(AIsMinHeight)); end; function TdxLayoutItemViewInfo.DoCalculateWidth(AIsMinWidth: Boolean): Integer; var AWidth: Integer; begin if AIsMinWidth then begin Result := CaptionViewInfo.CalculateMinWidth; AWidth := ControlViewInfo.CalculateMinWidth; end else begin Result := CaptionViewInfo.Width; AWidth := ControlViewInfo.CalculateWidth; end; case CaptionLayout of clLeft, clRight: begin if (Result <> 0) and ControlViewInfo.Visible{(AWidth <> 0)} then Inc(Result, ControlOffsetHorz); Inc(Result, AWidth); end; clTop, clBottom: Result := Max(Result, AWidth); else Result := 0; end; Inc(Result, inherited DoCalculateWidth(AIsMinWidth)); end; function TdxLayoutItemViewInfo.GetAutoControlAlignment: Boolean; function AreAlignmentAndCaptionLayoutLinked: Boolean; begin case CaptionLayout of clLeft: Result := AlignHorz in [ahLeft, ahClient]; clTop: Result := AlignVert in [avTop, avClient]; clRight: Result := AlignHorz in [ahRight, ahClient]; clBottom: Result := AlignVert in [avBottom, avClient]; else Result := False; end; end; begin Result := Item.ControlOptions.AutoAlignment and HasCaption and HasControl and AreAlignmentAndCaptionLayoutLinked; end; function TdxLayoutItemViewInfo.GetCaptionLayout: TdxCaptionLayout; begin Result := Item.CaptionOptions.Layout; end; function TdxLayoutItemViewInfo.GetColor: TColor; begin if ParentViewInfo <> nil then // for dragging Result := ParentViewInfo.GetColor else Result := ContainerViewInfo.ItemsViewInfo.GetColor; end; function TdxLayoutItemViewInfo.GetContentBounds: TRect; begin Result := Bounds; end; function TdxLayoutItemViewInfo.GetControlOffsetHorz: Integer; begin Result := LayoutLookAndFeel.GetControlOffsetHorz(Item.Container); end; function TdxLayoutItemViewInfo.GetControlOffsetVert: Integer; begin Result := LayoutLookAndFeel.GetControlOffsetVert(Item.Container); end; function TdxLayoutItemViewInfo.GetIsDefaultColor: Boolean; begin Result := ParentViewInfo.IsDefaultColor; end; function TdxLayoutItemViewInfo.GetOptions: TdxCustomLayoutLookAndFeelOptions; begin Result := LayoutLookAndFeel.ItemOptions; end; function TdxLayoutItemViewInfo.HasControl: Boolean; begin Result := Item.HasControl; end; procedure TdxLayoutItemViewInfo.PaintSelectionLayer; begin inherited; if HasControl and ActuallyVisible and IsParentSelected and not Selected then ContainerViewInfo.SelectionLayer.SelectionImage.cxCanvas.FillRect(ControlViewInfo.Bounds, 0); end; function TdxLayoutItemViewInfo.PtInDesignSelectorRect(const P: TPoint): Boolean; begin Result := PtInRect(DesignSelectorRect, P); end; procedure TdxLayoutItemViewInfo.Calculate(const ABounds: TRect); var ACaptionViewInfoBounds, AControlViewInfoBounds: TRect; begin inherited; CalculateViewInfosBounds(ACaptionViewInfoBounds, AControlViewInfoBounds); CaptionViewInfo.Calculate(ACaptionViewInfoBounds); ControlViewInfo.Calculate(AControlViewInfoBounds); Item.UpdateDesignSelectors; end; procedure TdxLayoutItemViewInfo.CalculateTabOrders(var AAvailTabOrder: Integer); begin ControlViewInfo.CalculateTabOrder(AAvailTabOrder); end; { TdxLayoutGroupCaptionViewInfo } function TdxLayoutGroupCaptionViewInfo.GetAlignVert: TdxAlignmentVert; begin Result := tavTop; end; function TdxLayoutGroupCaptionViewInfo.GetMultiLine: Boolean; begin Result := False; end; function TdxLayoutGroupCaptionViewInfo.CalculateMinWidth: Integer; begin Result := CalculateWidth; end; { TdxLayoutGroupViewInfoSpecific } constructor TdxLayoutGroupViewInfoSpecific.Create(AGroupViewInfo: TdxLayoutGroupViewInfo); begin inherited Create; FGroupViewInfo := AGroupViewInfo; CreateSpecificControls; end; destructor TdxLayoutGroupViewInfoSpecific.Destroy; begin DestroySpecificControls; inherited Destroy; end; procedure TdxLayoutGroupViewInfoSpecific.Calculate(const AItemsAreaBounds: TRect); begin CalculateItemsBounds(AItemsAreaBounds); end; procedure TdxLayoutGroupViewInfoSpecific.PrepareItemInfos; var I: Integer; begin SetLength(FItemInfos, ItemViewInfoCount); for I := 0 to ItemViewInfoCount - 1 do begin FItemInfos[I].ViewInfo := ItemViewInfos[I]; FItemInfos[I].AlignHorz := GetItemAlignHorz(FItemInfos[I].ViewInfo); FItemInfos[I].CalculatedWidth := GetItemWidth(FItemInfos[I].ViewInfo); FItemInfos[I].Height := GetItemHeight(FItemInfos[I].ViewInfo); FItemInfos[I].MinWidth := GetItemMinWidth(FItemInfos[I].ViewInfo); FItemInfos[I].Calculated := False; end; end; procedure TdxLayoutGroupViewInfoSpecific.CalculateItemsHorizontalBounds(const AItemsAreaBounds: TRect); var ASpace, AAvailableSpace: Integer; procedure CalculateSpaces; var AItemOffsets, I: Integer; AIsFirstItem: Boolean; begin AItemOffsets := 0; ASpace := 0; AIsFirstItem := True; for I := 0 to ItemViewInfoCount - 1 do if FItemInfos[I].AlignHorz <> ahCenter then begin if not AIsFirstItem then Inc(AItemOffsets, ItemOffset); Inc(ASpace, FItemInfos[I].CalculatedWidth); AIsFirstItem := False; end; AAvailableSpace := cxRectWidth(AItemsAreaBounds) - AItemOffsets; end; procedure InternalCalculateItemsVisibleSizes; procedure CalculateNonClientAlignedItemsVisibleSizes; var I: Integer; begin for I := 0 to ItemViewInfoCount - 1 do if FItemInfos[I].AlignHorz <> ahClient then begin FItemInfos[I].Width := FItemInfos[I].CalculatedWidth; if FItemInfos[I].AlignHorz <> ahCenter then begin Dec(ASpace, FItemInfos[I].Width); Dec(AAvailableSpace, FItemInfos[I].Width); end; FItemInfos[I].Calculated := True; end; end; procedure CalculateClientAlignedItemsVisibleSizes; var ANeedRecalculating: Boolean; ANextSpace, ANextAvailableSpace, I: Integer; begin repeat ANeedRecalculating := False; ANextSpace := ASpace; ANextAvailableSpace := AAvailableSpace; for I := 0 to ItemViewInfoCount - 1 do if not FItemInfos[I].Calculated then begin FItemInfos[I].Width := MulDiv(AAvailableSpace, FItemInfos[I].CalculatedWidth, ASpace); if FItemInfos[I].Width < FItemInfos[I].MinWidth then begin FItemInfos[I].Width := FItemInfos[I].MinWidth; Dec(ANextSpace, FItemInfos[I].CalculatedWidth); Dec(ANextAvailableSpace, FItemInfos[I].Width); FItemInfos[I].Calculated := True; ANeedRecalculating := True; end; end; ASpace := ANextSpace; AAvailableSpace := ANextAvailableSpace; until not ANeedRecalculating; end; begin CalculateNonClientAlignedItemsVisibleSizes; CalculateClientAlignedItemsVisibleSizes; end; procedure InternalCalculateItemsBounds; procedure CalculateLeftAlignedItemsBounds; var AOffset, I: Integer; begin AOffset := AItemsAreaBounds.Left; for I := 0 to ItemViewInfoCount - 1 do with FItemInfos[I] do case AlignHorz of ahLeft, ahClient: begin Bounds.Left := AOffset; Bounds.Right := AOffset + Width; Inc(AOffset, Width + ItemOffset); end; ahCenter: begin Bounds.Left := (AItemsAreaBounds.Left + AItemsAreaBounds.Right - Width) div 2; Bounds.Right := Bounds.Left + Width; end; end; end; procedure CalculateRightAlignedItemsBounds; var AOffset, I: Integer; begin AOffset := AItemsAreaBounds.Right; for I := ItemViewInfoCount - 1 downto 0 do with FItemInfos[I] do if AlignHorz = ahRight then begin Bounds.Right := AOffset; Bounds.Left := AOffset - Width; Dec(AOffset, Width + ItemOffset); end; end; begin CalculateLeftAlignedItemsBounds; CalculateRightAlignedItemsBounds; end; begin CalculateSpaces; InternalCalculateItemsVisibleSizes; InternalCalculateItemsBounds; end; procedure TdxLayoutGroupViewInfoSpecific.CalculateItemsVerticalBounds(const AItemsAreaBounds: TRect); var I: Integer; begin for I := 0 to ItemViewInfoCount - 1 do with FItemInfos[I] do case GetItemAlignVert(ViewInfo) of avTop: begin Bounds.Top := AItemsAreaBounds.Top; Bounds.Bottom := Bounds.Top + Height; end; avCenter: begin Bounds.Top := (AItemsAreaBounds.Top + AItemsAreaBounds.Bottom - Height) div 2; Bounds.Bottom := Bounds.Top + Height; end; avBottom: begin Bounds.Bottom := AItemsAreaBounds.Bottom; Bounds.Top := Bounds.Bottom - Height; end; avClient: begin Bounds.Top := AItemsAreaBounds.Top; Bounds.Bottom := AItemsAreaBounds.Bottom; end; end; end; procedure TdxLayoutGroupViewInfoSpecific.CalculateTabOrders(var ATabOrder: Integer); begin // do nothing end; procedure TdxLayoutGroupViewInfoSpecific.CalculateItemViewInfos; var I: Integer; begin for I := 0 to ItemViewInfoCount - 1 do begin ConvertCoords(FItemInfos[I].Bounds); FItemInfos[I].ViewInfo.Calculate(FItemInfos[I].Bounds); end; end; function TdxLayoutGroupViewInfoSpecific.GetContainer: TdxCustomLayoutControl; begin Result := GroupViewInfo.ContainerViewInfo.Control; end; function TdxLayoutGroupViewInfoSpecific.GetItemOffset: Integer; begin Result := FGroupViewInfo.ItemOffset; end; function TdxLayoutGroupViewInfoSpecific.GetItemViewInfo(Index: Integer): TdxCustomLayoutItemViewInfo; begin Result := FGroupViewInfo.ItemViewInfos[Index]; end; function TdxLayoutGroupViewInfoSpecific.GetItemViewInfoCount: Integer; begin Result := FGroupViewInfo.ItemViewInfoCount; end; function TdxLayoutGroupViewInfoSpecific.GetLayoutDirection: TdxLayoutDirection; begin Result := FGroupViewInfo.LayoutDirection; end; procedure TdxLayoutGroupViewInfoSpecific.CreateSpecificControls; begin // do nothing end; procedure TdxLayoutGroupViewInfoSpecific.DestroySpecificControls; begin // do nothing end; procedure TdxLayoutGroupViewInfoSpecific.CreateViewInfos; begin // do nothing end; procedure TdxLayoutGroupViewInfoSpecific.SetControlVisibility; begin // do nothing end; procedure TdxLayoutGroupViewInfoSpecific.AddSelectionControls; begin // do nothing end; procedure TdxLayoutGroupViewInfoSpecific.RemoveSelectionControls; begin // do nothing end; procedure TdxLayoutGroupViewInfoSpecific.DrawSpecificPart(ACanvas: TcxCanvas); begin // do nothing end; procedure TdxLayoutGroupViewInfoSpecific.DrawSpecificBackground(ACanvas: TcxCanvas); begin if GroupViewInfo.HasBackground then ACanvas.FillRect(GroupViewInfo.BackgroundBounds, GroupViewInfo.GetBackgroundColor); end; function TdxLayoutGroupViewInfoSpecific.GetCustomHeight(AIsMinHeight: Boolean): Integer; var I: Integer; begin Result := 0; for I := 0 to ItemViewInfoCount - 1 do if AIsMinHeight then Result := Max(Result, GetItemMinHeight(ItemViewInfos[I])) else Result := Max(Result, GetItemHeight(ItemViewInfos[I])) end; function TdxLayoutGroupViewInfoSpecific.GetCustomWidth(AIsMinWidth: Boolean): Integer; var AIsFirstItem: Boolean; I: Integer; AItemViewInfo: TdxCustomLayoutItemViewInfo; begin Result := 0; AIsFirstItem := True; for I := 0 to ItemViewInfoCount - 1 do begin AItemViewInfo := ItemViewInfos[I]; if GetItemAlignHorz(AItemViewInfo) <> ahCenter then begin if not AIsFirstItem then Inc(Result, ItemOffset); if AIsMinWidth then Inc(Result, GetItemMinWidth(AItemViewInfo)) else Inc(Result, GetItemWidth(AItemViewInfo)); AIsFirstItem := False; end; end; for I := 0 to ItemViewInfoCount - 1 do begin AItemViewInfo := ItemViewInfos[I]; if GetItemAlignHorz(AItemViewInfo) = ahCenter then if AIsMinWidth then Result := Max(Result, GetItemMinWidth(AItemViewInfo)) else Result := Max(Result, GetItemWidth(AItemViewInfo)) end; end; function TdxLayoutGroupViewInfoSpecific.GetAreaPart(const P: TPoint): TdxLayoutAreaPart; begin Result := apNone; if (GroupViewInfo.Group.VisibleCount = 0) and PtInRect(dxGetCenterAreaBounds(GroupViewInfo.Bounds), P) then Result := apCenter; end; function TdxLayoutGroupViewInfoSpecific.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; begin Result := nil; end; function TdxLayoutGroupViewInfoSpecific.GetItemsAreaOffset(ASide: TdxLayoutSide): Integer; begin Result := 0; end; procedure TdxLayoutGroupViewInfoSpecific.ConvertCoords(var R: TRect); begin end; procedure TdxLayoutGroupViewInfoSpecific.CalculateItemsBounds(AItemsAreaBounds: TRect); begin ConvertCoords(AItemsAreaBounds); PrepareItemInfos; CalculateItemsHorizontalBounds(AItemsAreaBounds); CalculateItemsVerticalBounds(AItemsAreaBounds); CalculateItemViewInfos; end; function TdxLayoutGroupViewInfoSpecific.CanDrawBackground: Boolean; begin Result := False; end; function TdxLayoutGroupViewInfoSpecific.GetItemsAreaHeight(AIsMinHeight: Boolean): Integer; begin Result := GetCustomHeight(AIsMinHeight); end; function TdxLayoutGroupViewInfoSpecific.GetItemsAreaWidth(AIsMinWidth: Boolean): Integer; begin Result := GetCustomWidth(AIsMinWidth); end; function TdxLayoutGroupViewInfoSpecific.AllowDrawChild(AChild: TdxCustomLayoutItem): Boolean; begin Result := True; end; function TdxLayoutGroupViewInfoSpecific.AllowChildHasBorder: Boolean; begin Result := True; end; { TdxLayoutGroupHorizontalSpecific } function TdxLayoutGroupViewInfoHorizontalSpecific.GetItemAlignHorz(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignHorz; begin Result := AViewInfo.AlignHorz; end; function TdxLayoutGroupViewInfoHorizontalSpecific.GetItemAlignVert(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignVert; begin Result := AViewInfo.AlignVert; end; function TdxLayoutGroupViewInfoHorizontalSpecific.GetItemHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; begin Result := AViewInfo.Height; end; function TdxLayoutGroupViewInfoHorizontalSpecific.GetItemWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; begin Result := AViewInfo.Width; end; function TdxLayoutGroupViewInfoHorizontalSpecific.GetItemMinHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; begin Result := AViewInfo.MinHeight; end; function TdxLayoutGroupViewInfoHorizontalSpecific.GetItemMinWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; begin Result := AViewInfo.MinWidth; end; function TdxLayoutGroupViewInfoHorizontalSpecific.IsAtInsertionPos(const R: TRect; const P: TPoint): Boolean; begin Result := P.X < (R.Left + R.Right) div 2; end; { TdxLayoutGroupViewInfoVerticalSpecific } procedure TdxLayoutGroupViewInfoVerticalSpecific.ConvertCoords(var R: TRect); begin ExchangeLongWords(R.Left, R.Top); ExchangeLongWords(R.Right, R.Bottom); end; function TdxLayoutGroupViewInfoVerticalSpecific.GetItemAlignHorz(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignHorz; begin Result := TdxLayoutAlignHorz(AViewInfo.AlignVert); end; function TdxLayoutGroupViewInfoVerticalSpecific.GetItemAlignVert(AViewInfo: TdxCustomLayoutItemViewInfo): TdxLayoutAlignVert; begin Result := TdxLayoutAlignVert(AViewInfo.AlignHorz); end; function TdxLayoutGroupViewInfoVerticalSpecific.GetItemHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; begin Result := AViewInfo.GetWidth; end; function TdxLayoutGroupViewInfoVerticalSpecific.GetItemWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; begin Result := AViewInfo.GetHeight; end; function TdxLayoutGroupViewInfoVerticalSpecific.GetItemMinHeight(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; begin Result := AViewInfo.MinWidth; end; function TdxLayoutGroupViewInfoVerticalSpecific.GetItemMinWidth(AViewInfo: TdxCustomLayoutItemViewInfo): Integer; begin Result := AViewInfo.MinHeight; end; function TdxLayoutGroupViewInfoVerticalSpecific.GetItemsAreaHeight(AIsMinHeight: Boolean): Integer; begin Result := inherited GetItemsAreaWidth(AIsMinHeight); end; function TdxLayoutGroupViewInfoVerticalSpecific.GetItemsAreaWidth(AIsMinWidth: Boolean): Integer; begin Result := inherited GetItemsAreaHeight(AIsMinWidth); end; function TdxLayoutGroupViewInfoVerticalSpecific.IsAtInsertionPos(const R: TRect; const P: TPoint): Boolean; begin Result := P.Y < (R.Top + R.Bottom) div 2; end; { TdxLayoutTabbedGroupTabControl } procedure TdxLayoutTabbedGroupTabControl.BoundsChanged; var ARegion: TcxRegion; begin inherited; if HandleAllocated then begin ARegion := TcxRegion.Create(Bounds); try ARegion.Combine(TcxRegion.Create(DisplayRect), roSubtract); SetWindowRgn(Handle, ARegion.Handle, False); finally ARegion.Free; end; end; end; function TdxLayoutTabbedGroupTabControl.GetDesignHitTest(X, Y: Integer; Shift: TShiftState): Boolean; begin Result := True; end; procedure TdxLayoutTabbedGroupTabControl.WMNCHitTest(var Message: TWMNCHitTest); begin Message.Result := HTTRANSPARENT; end; { TdxTabControlElementViewInfo } function TdxTabControlElementViewInfo.GetVisible: Boolean; begin Result := not cxRectIsEmpty(Bounds); end; procedure TdxTabControlElementViewInfo.MouseEnter; begin FTabControl.MouseEnter(nil); end; procedure TdxTabControlElementViewInfo.MouseLeave; begin FTabControl.MouseLeave(nil); end; procedure TdxTabControlElementViewInfo.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin FTabControl.MouseDown(Button, Shift, X - FTabControl.Left, Y - FTabControl.Top); end; procedure TdxTabControlElementViewInfo.MouseMove(Shift: TShiftState; X, Y: Integer); var ATabIndex: Integer; AClientPoint: TPoint; begin FTabControl.MouseMove(Shift, X - FTabControl.Left, Y - FTabControl.Top); if ItemViewInfo.ContainerViewInfo.Control.DragAndDropState <> ddsNone then begin AClientPoint := cxPointOffset(Point(X, Y), Point(FTabControl.Left, FTabControl.Top), False); ATabIndex := FTabControl.IndexOfTabAt(AClientPoint.X, AClientPoint.Y); if ATabIndex <> -1 then FTabControl.TabIndex := ATabIndex; end; end; procedure TdxTabControlElementViewInfo.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin FTabControl.MouseUp(Button, Shift, X - FTabControl.Left, Y - FTabControl.Top); end; { TdxLayoutGroupViewInfoTabbedSpecific } procedure TdxLayoutGroupViewInfoTabbedSpecific.Calculate(const AItemsAreaBounds: TRect); var ARect: TRect; begin inherited; if HasTabControl then begin FTabControl.BoundsRect := GroupViewInfo.ClientBounds; FTabControl.Parent := Container; ARect := GroupViewInfo.ClientBounds; ARect.Bottom := GroupViewInfo.ItemsAreaBounds.Top; FTabControlElementViewInfo.Calculate(ARect); FTabControlElementViewInfo.FTabControl := FTabControl; end else FTabControlElementViewInfo.Calculate(cxEmptyRect); end; function TdxLayoutGroupViewInfoTabbedSpecific.AllowDrawChild(AChild: TdxCustomLayoutItem): Boolean; begin Result := inherited AllowDrawChild(AChild) and (AChild.VisibleIndex = GroupViewInfo.Group.ItemIndex); end; function TdxLayoutGroupViewInfoTabbedSpecific.AllowChildHasBorder: Boolean; begin Result := False; end; function TdxLayoutGroupViewInfoTabbedSpecific.CanDrawBackground: Boolean; begin Result := True; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.CalculateItemsHorizontalBounds(const AItemsAreaBounds: TRect); var I: Integer; begin for I := 0 to ItemViewInfoCount - 1 do with FItemInfos[I] do begin Width := CalculatedWidth; case GetItemAlignHorz(ViewInfo) of ahLeft: begin Bounds.Left := AItemsAreaBounds.Left; Bounds.Right := Bounds.Left + Width; end; ahCenter: begin Bounds.Left := (AItemsAreaBounds.Left + AItemsAreaBounds.Right - Width) div 2; Bounds.Right := Bounds.Left + Width; end; ahRight: begin Bounds.Right := AItemsAreaBounds.Right; Bounds.Left := Bounds.Right - Width; end; ahClient: begin Bounds.Left := AItemsAreaBounds.Left; Bounds.Right := AItemsAreaBounds.Right; end; end; end; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.CalculateItemsVerticalBounds(const AItemsAreaBounds: TRect); begin inherited; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.CalculateTabOrders(var ATabOrder: Integer); begin if HasTabControl then begin FTabControl.TabOrder := ATabOrder; Inc(ATabOrder); end; end; function TdxLayoutGroupViewInfoTabbedSpecific.GetAreaPart(const P: TPoint): TdxLayoutAreaPart; begin if HasTabControl and PtInRect(FTabControl.BoundsRect, P) then Result := apCenter else Result := inherited GetAreaPart(P); end; function TdxLayoutGroupViewInfoTabbedSpecific.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; var ATabIndex: Integer; AClientPoint: TPoint; begin Result := nil; if HasTabControl then begin AClientPoint := cxPointOffset(P, Point(FTabControl.Left, FTabControl.Top), False); ATabIndex := FTabControl.IndexOfTabAt(AClientPoint.X, AClientPoint.Y); if ATabIndex <> -1 then Result := GroupViewInfo.ItemViewInfos[ATabIndex].CreateHitTest; end; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.DrawSpecificPart(ACanvas: TcxCanvas); var ARegion: TcxRegion; begin inherited DrawSpecificPart(ACanvas); if HasTabControl then begin ACanvas.SaveState; try with FTabControl.BoundsRect.TopLeft do MoveWindowOrg(ACanvas.Handle, X, Y); ARegion := TcxRegion.Create; try GetWindowRgn(FTabControl.Handle, ARegion.Handle); ACanvas.SetClipRegion(ARegion, roIntersect, False); finally ARegion.Free; end; FTabControl.PaintTo(ACanvas.Handle, 0, 0); finally ACanvas.RestoreState; end; end; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.DrawSpecificBackground(ACanvas: TcxCanvas); begin if not HasTabControl or (csPaintCopy in (FTabControl.ControlState + Container.ControlState)) then inherited else begin ACanvas.SaveState; try with FTabControl.BoundsRect.TopLeft do MoveWindowOrg(ACanvas.Handle, X, Y); ACanvas.IntersectClipRect(FTabControl.DisplayRect); FTabControl.PaintTo(ACanvas.Canvas, 0, 0); finally ACanvas.RestoreState; end; end; end; function TdxLayoutGroupViewInfoTabbedSpecific.GetCustomHeight(AIsMinHeight: Boolean): Integer; begin Result := inherited GetCustomHeight(AIsMinHeight); end; function TdxLayoutGroupViewInfoTabbedSpecific.GetCustomWidth(AIsMinWidth: Boolean): Integer; var I: Integer; begin Result := 0; for I := 0 to ItemViewInfoCount - 1 do if AIsMinWidth then Result := Max(Result, GetItemMinWidth(ItemViewInfos[I])) else Result := Max(Result, GetItemWidth(ItemViewInfos[I])) end; function TdxLayoutGroupViewInfoTabbedSpecific.GetItemsAreaOffset(ASide: TdxLayoutSide): Integer; begin Result := inherited GetItemsAreaOffset(ASide); // #DG !!! if HasTabControl then begin Inc(Result, GroupViewInfo.LayoutLookAndFeel.GetItemsAreaOffset(GroupViewInfo.Group.Container)); case ASide of sdLeft: Inc(Result, TcxPCCustomPainterAccess(FTabControl.Painter).GetClientRectOffset.Left); sdRight: Inc(Result, TcxPCCustomPainterAccess(FTabControl.Painter).GetClientRectOffset.Right); sdTop: Inc(Result, TcxPCCustomPainterAccess(FTabControl.Painter).GetClientRectOffset.Top); sdBottom: Inc(Result, TcxPCCustomPainterAccess(FTabControl.Painter).GetClientRectOffset.Bottom); end; end; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.CreateSpecificControls; begin inherited CreateSpecificControls; CreateTabControl; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.DestroySpecificControls; begin inherited DestroySpecificControls; DestroyTabControl; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.CreateViewInfos; begin FTabControlElementViewInfo := TdxTabControlElementViewInfo.Create(GroupViewInfo); GroupViewInfo.FElements.Add(FTabControlElementViewInfo); end; procedure TdxLayoutGroupViewInfoTabbedSpecific.SetControlVisibility; begin if HasTabControl then FTabControl.Visible := GroupViewInfo.ActuallyVisible; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.CreateTabControl; var I: Integer; begin if GroupViewInfo.Group.VisibleCount = 0 then Exit; FTabControl := TdxLayoutTabbedGroupTabControl.Create(GroupViewInfo.Group); FTabControl.Font := Container.Font; for I := 0 to GroupViewInfo.Group.VisibleCount - 1 do FTabControl.Tabs.Add(GroupViewInfo.Group.VisibleItems[I].Caption); FTabControl.TabIndex := GroupViewInfo.Group.ItemIndex; GroupViewInfo.LayoutLookAndFeel.InitializeSubControlCxLookAndFeel(FTabControl.LookAndFeel); FTabControl.OnChange := ActiveTabChanged; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.DestroyTabControl; begin FreeAndNil(FTabControl); end; function TdxLayoutGroupViewInfoTabbedSpecific.HasTabControl: Boolean; begin Result := FTabControl <> nil; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.ActiveTabChanged(ASender: TObject); var AContainer: TdxCustomLayoutControl; begin AContainer := GroupViewInfo.Group.Container; GroupViewInfo.Group.ItemIndex := FTabControl.TabIndex; AContainer.Modified; end; { TdxLayoutGroupViewInfo } function TdxLayoutGroupViewInfo.GetBorderBounds(ASide: TdxLayoutSide): TRect; begin Result := Bounds; with ClientBounds do case ASide of sdLeft: Result.Right := Left; sdTop: Result.Bottom := Top; sdRight: Result.Left := Right; sdBottom: Result.Top := Bottom; end; end; function TdxLayoutGroupViewInfo.GetBorderRestSpaceBounds(ASide: TdxLayoutSide): TRect; begin Result := RestSpaceBounds; with ClientBounds do case ASide of sdLeft: Result.Right := Left; sdTop: Result.Bottom := Top; sdRight: Result.Left := Right; sdBottom: Result.Top := Bottom; end; end; function TdxLayoutGroupViewInfo.GetBordersHeight: Integer; begin Result := BorderWidths[sdLeft] + BorderWidths[sdRight]; end; function TdxLayoutGroupViewInfo.GetBordersWidth: Integer; begin Result := BorderWidths[sdTop] + BorderWidths[sdBottom]; end; function TdxLayoutGroupViewInfo.GetCaptionViewInfo: TdxLayoutGroupCaptionViewInfo; begin Result := TdxLayoutGroupCaptionViewInfo(inherited CaptionViewInfo); end; function TdxLayoutGroupViewInfo.GetGroup: TdxLayoutGroup; begin Result := TdxLayoutGroup(inherited Item); end; function TdxLayoutGroupViewInfo.GetIsLocked: Boolean; begin Result := Group.Locked and IsCustomization or IsParentLocked; end; function TdxLayoutGroupViewInfo.GetItemViewInfo(Index: Integer): TdxCustomLayoutItemViewInfo; begin Result := TdxCustomLayoutItemViewInfo(FItemViewInfos[Index]); end; function TdxLayoutGroupViewInfo.GetItemViewInfoCount: Integer; begin Result := FItemViewInfos.Count; end; function TdxLayoutGroupViewInfo.GetLayoutDirection: TdxLayoutDirection; begin Result := Group.LayoutDirection; end; function TdxLayoutGroupViewInfo.GetOptionsEx: TdxLayoutLookAndFeelGroupOptions; begin Result := TdxLayoutLookAndFeelGroupOptions(inherited Options); end; function TdxLayoutGroupViewInfo.GetOffset(Index: Integer): Integer; begin if not FOffsetsCalculated then begin CalculateOffsets; FOffsetsCalculated := True; end; case Index of 0: Result := FItemOffset; 1: Result := FItemsAreaOffsetHorz; 2: Result := FItemsAreaOffsetVert; else Result := -1; end; end; procedure TdxLayoutGroupViewInfo.CreateItemViewInfos; var I: Integer; AItem: TdxCustomLayoutItem; AItemViewInfo: TdxCustomLayoutItemViewInfo; begin FItemViewInfos := TObjectList.Create; for I := 0 to Group.Count - 1 do begin AItem := Group.Items[I]; if AItem.GetVisible or (IsDragImagePainted and IsAvailable) then begin AItemViewInfo := GetItemViewInfoClass(AItem).Create(FContainerViewInfo, Self, AItem); FItemViewInfos.Add(AItemViewInfo); end; end; end; procedure TdxLayoutGroupViewInfo.CreateSpecific; begin FSpecific := GetSpecificClass.Create(Self); end; procedure TdxLayoutGroupViewInfo.DestroyItemViewInfos; begin FreeAndNil(FItemViewInfos); end; procedure TdxLayoutGroupViewInfo.DestroySpecific; begin FreeAndNil(FSpecific); end; function TdxLayoutGroupViewInfo.GetClientAreaBounds(const ABounds: TRect): TRect; var AMargins: TRect; begin with LayoutLookAndFeel do AMargins := Rect(GetBorderWidth(sdLeft), GetBorderWidth(sdTop), GetBorderWidth(sdRight), GetBorderWidth(sdBottom)); Result := cxRectContent(ABounds, AMargins); end; function TdxLayoutGroupViewInfo.GetItemAreaBounds(const AClientRect: TRect): TRect; var AMargins: TRect; begin with LayoutLookAndFeel do AMargins := Rect(GetBorderWidth(sdLeft), GetBorderWidth(sdTop), GetBorderWidth(sdRight), GetBorderWidth(sdBottom)); Result := cxRectInflate(AClientRect, AMargins); end; function TdxLayoutGroupViewInfo.GetBackgroundColor: TColor; begin if Group.IsRoot and ContainerViewInfo.NeedHighlightRoot then Result := dxLayoutHiddenGroupBackgroundDefaultColor else Result := inherited GetBackgroundColor; end; procedure TdxLayoutGroupViewInfo.DoCreateViewInfos; begin inherited; CreateSpecific; CreateItemViewInfos; Specific.CreateViewInfos; end; procedure TdxLayoutGroupViewInfo.DestroyViewInfos; begin DestroyItemViewInfos; DestroySpecific; inherited; end; procedure TdxLayoutGroupViewInfo.FreeNotification(AComponent: TComponent); begin inherited; Specific.DestroySpecificControls; end; function TdxLayoutGroupViewInfo.GetCaptionViewInfoClass: TdxCustomLayoutItemCaptionViewInfoClass; begin Result := TdxLayoutGroupCaptionViewInfo; end; function TdxLayoutGroupViewInfo.GetHitTestClass: TdxCustomLayoutItemHitTestClass; begin Result := TdxLayoutGroupHitTest; end; function TdxLayoutGroupViewInfo.GetPainterClass: TdxCustomLayoutItemPainterClass; begin Result := TdxCustomLayoutItemPainterClass(LayoutLookAndFeel.GetGroupPainterClass); end; function TdxLayoutGroupViewInfo.DoCalculateHeight(AIsMinHeight: Boolean = False): Integer; begin Result := inherited DoCalculateHeight(AIsMinHeight) + GetHeight(Specific.GetItemsAreaHeight(AIsMinHeight)); end; function TdxLayoutGroupViewInfo.DoCalculateWidth(AIsMinWidth: Boolean = False): Integer; begin Result := inherited DoCalculateWidth(AIsMinWidth) + GetWidth(Specific.GetItemsAreaWidth(AIsMinWidth)); end; function TdxLayoutGroupViewInfo.GetAreaPart(const P: TPoint): TdxLayoutAreaPart; begin Result := Specific.GetAreaPart(P); if Result = apNone then Result := inherited GetAreaPart(P); end; function TdxLayoutGroupViewInfo.HasCaption: Boolean; begin Result := inherited HasCaption and HasBorder; end; function TdxLayoutGroupViewInfo.HasBorder: Boolean; begin Result := Group.ShowBorder and ((ParentViewInfo = nil) or ParentViewInfo.AllowChildHasBorder or IsDragImagePainted and IsDragged); end; procedure TdxLayoutGroupViewInfo.CalculateCaptionViewInfoBounds; begin FCaptionAreaBounds := cxNullRect; end; procedure TdxLayoutGroupViewInfo.CalculateClientBounds; begin FClientAreaBounds := GetClientAreaBounds(FBounds); end; procedure TdxLayoutGroupViewInfo.CalculateItemsAreaBounds; begin FItemsAreaBounds := cxRectInflate(ClientBounds, -ItemsAreaOffsetHorz, -ItemsAreaOffsetVert); Inc(FItemsAreaBounds.Left, Specific.GetItemsAreaOffset(sdLeft)); Dec(FItemsAreaBounds.Right, Specific.GetItemsAreaOffset(sdRight)); Inc(FItemsAreaBounds.Top, Specific.GetItemsAreaOffset(sdTop)); Dec(FItemsAreaBounds.Bottom, Specific.GetItemsAreaOffset(sdBottom)); end; procedure TdxLayoutGroupViewInfo.CalculateOffsets; begin if UseItemsAreaOffsets then if Group.IsRoot then begin ItemsAreaOffsetHorz := LayoutLookAndFeel.GetRootItemsAreaOffsetHorz(Item.Container); ItemsAreaOffsetVert := LayoutLookAndFeel.GetRootItemsAreaOffsetVert(Item.Container); end else begin ItemsAreaOffsetHorz := LayoutLookAndFeel.GetItemsAreaOffsetHorz(Item.Container); ItemsAreaOffsetVert := LayoutLookAndFeel.GetItemsAreaOffsetVert(Item.Container); end else begin ItemsAreaOffsetHorz := 0; ItemsAreaOffsetVert := 0; end; if UseItemOffset then ItemOffset := LayoutLookAndFeel.GetItemOffset(Item.Container) else ItemOffset := 0; end; function TdxLayoutGroupViewInfo.GetBorderWidth(ASide: TdxLayoutSide): Integer; begin //#DG !!! if HasBorder then Result := LayoutLookAndFeel.GetGroupBorderWidth(Item.Container, ASide, HasCaption) else Result := 0; end; function TdxLayoutGroupViewInfo.GetColor: TColor; begin Result := Options.GetColor; end; function TdxLayoutGroupViewInfo.GetIsDefaultColor: Boolean; begin Result := Options.Color = clDefault; end; function TdxLayoutGroupViewInfo.GetItemViewInfoClass(AItem: TdxCustomLayoutItem): TdxCustomLayoutItemViewInfoClass; begin Result := AItem.GetViewInfoClass; end; function TdxLayoutGroupViewInfo.GetMinVisibleHeight: Integer; begin Result := dxLayoutItemMinSize; end; function TdxLayoutGroupViewInfo.GetMinVisibleWidth: Integer; begin if HasCaption then Result := CaptionViewInfo.CalculateMinWidth else Result := 0; Result := Max(Result, dxLayoutItemMinSize); end; function TdxLayoutGroupViewInfo.GetOptions: TdxCustomLayoutLookAndFeelOptions; begin Result := LayoutLookAndFeel.GroupOptions; end; function TdxLayoutGroupViewInfo.GetRestSpaceBounds: TRect; begin Result := Bounds; end; function TdxLayoutGroupViewInfo.AllowChildHasBorder: Boolean; begin Result := Specific.AllowChildHasBorder; end; function TdxLayoutGroupViewInfo.GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; begin Result := Group.GetHelperClass.GetSpecificClass; end; procedure TdxLayoutGroupViewInfo.PaintSelectionLayer; var I: Integer; begin inherited; for I := 0 to ItemViewInfoCount - 1 do ItemViewInfos[I].PaintSelectionLayer; end; function TdxLayoutGroupViewInfo.GetHeight(AItemsAreaHeight: Integer): Integer; begin Result := Max(MinVisibleHeight, BorderWidths[sdTop] + ItemsAreaOffsetVert + Specific.GetItemsAreaOffset(sdTop) + AItemsAreaHeight + BorderWidths[sdBottom] + ItemsAreaOffsetVert + Specific.GetItemsAreaOffset(sdBottom)); end; function TdxLayoutGroupViewInfo.GetWidth(AItemsAreaWidth: Integer): Integer; begin Result := Max(MinVisibleWidth, BorderWidths[sdLeft] + ItemsAreaOffsetHorz + Specific.GetItemsAreaOffset(sdLeft) + AItemsAreaWidth + BorderWidths[sdRight] + ItemsAreaOffsetHorz + Specific.GetItemsAreaOffset(sdRight)); end; function TdxLayoutGroupViewInfo.HasBoundsFrame: Boolean; begin Result := Group.IsRoot and (Group.Container.ShowHiddenGroupsBounds or Group.Container.IsDesigning); end; function TdxLayoutGroupViewInfo.UseItemOffset: Boolean; begin Result := Group.UseIndent; end; function TdxLayoutGroupViewInfo.UseItemsAreaOffsets: Boolean; begin // #DG !!! Result := Group.ShowBorder or Group.IsRoot; Result := HasBorder or Group.IsRoot; end; procedure TdxLayoutGroupViewInfo.Calculate(const ABounds: TRect); begin inherited; CalculateClientBounds; CalculateItemsAreaBounds; CalculateCaptionViewInfoBounds; CaptionViewInfo.Calculate(FCaptionAreaBounds); Specific.Calculate(ItemsAreaBounds); end; procedure TdxLayoutGroupViewInfo.CalculateTabOrders(var AAvailTabOrder: Integer); var I: Integer; begin Specific.CalculateTabOrders(AAvailTabOrder); for I := 0 to ItemViewInfoCount - 1 do ItemViewInfos[I].CalculateTabOrders(AAvailTabOrder); end; function TdxLayoutGroupViewInfo.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; var I: Integer; begin Result := nil; for I := 0 to ItemViewInfoCount - 1 do begin Result := ItemViewInfos[I].GetHitTest(P); if Result <> nil then Break; end; if Result = nil then Result := Specific.GetHitTest(P); if Result = nil then Result := inherited GetHitTest(P); end; function TdxLayoutGroupViewInfo.GetItemWithMouse(const P: TPoint): TdxCustomLayoutItem; var I: Integer; begin Result := nil; for I := 0 to ItemViewInfoCount - 1 do begin Result := ItemViewInfos[I].GetItemWithMouse(P); if Result <> nil then Break; end; if Result = nil then Result := inherited GetItemWithMouse(P); end; function TdxLayoutGroupViewInfo.GetInsertionPos(const P: TPoint): Integer; var R: TRect; begin if PtInRect(Bounds, P) then for Result := 0 to ItemViewInfoCount - 1 do begin R := ItemViewInfos[Result].Bounds; if Specific.IsAtInsertionPos(R, P) then Exit; end; Result := ItemViewInfoCount; end; { TdxCustomLayoutControlAdapter } constructor TdxCustomLayoutControlAdapter.Create(AItem: TdxLayoutItem); begin inherited Create; FItem := AItem; if not FItem.IsLoading then begin Init; if FItem.ActuallyVisible then LayoutLookAndFeelChanged; end; end; function TdxCustomLayoutControlAdapter.GetControl: TControl; begin Result := FItem.Control; end; function TdxCustomLayoutControlAdapter.GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; begin Result := FItem.GetLayoutLookAndFeel; end; function TdxCustomLayoutControlAdapter.AllowCheckSize: Boolean; begin Result := True; end; procedure TdxCustomLayoutControlAdapter.HideControlBorder; begin SetEnumProp(Control, 'BorderStyle', 'bsNone'); end; procedure TdxCustomLayoutControlAdapter.Init; var AHeight: Integer; begin FItem.ControlOptions.AutoColor := UseItemColor; if FItem.IsDesigning and (FItem.Caption = '') then FItem.Caption := Control.Name;//GetPlainString(TControlAccess(Control).Caption); FItem.SetControlEnablement; if FItem.IsDesigning then FItem.ShowCaption := ShowItemCaption; FItem.ControlOptions.ShowBorder := ShowBorder; if ShowBorder then begin AHeight := Control.ClientHeight; HideControlBorder; Control.Height := AHeight; end; end; function TdxCustomLayoutControlAdapter.ShowBorder: Boolean; begin Result := IsPublishedProp(Control, 'BorderStyle') and (GetPropInfo(Control, 'BorderStyle').PropType^ = TypeInfo(Forms.TBorderStyle)); end; function TdxCustomLayoutControlAdapter.ShowItemCaption: Boolean; begin Result := not IsPublishedProp(Control, 'Caption'); end; function TdxCustomLayoutControlAdapter.UseItemColor: Boolean; begin Result := TControlAccess(Control).ParentColor and IsPublishedProp(Control, 'Color'); end; procedure TdxCustomLayoutControlAdapter.LayoutLookAndFeelChanged; begin if Item.ControlOptions.AutoColor and (Item.ViewInfo <> nil) then TControlAccess(Control).Color := Item.ViewInfo.Color; end; class procedure TdxCustomLayoutControlAdapter.Register(AControlClass: TControlClass); begin dxLayoutControlAdapterDefs.Register(AControlClass, Self); end; class procedure TdxCustomLayoutControlAdapter.Unregister(AControlClass: TControlClass); begin dxLayoutControlAdapterDefs.Unregister(AControlClass, Self); end; procedure TdxStoringOptions.Assign(Source: TPersistent); var ASourceOptions: TdxStoringOptions; begin if Source is TdxStoringOptions then begin ASourceOptions := TdxStoringOptions(Source); IniFileName := ASourceOptions.IniFileName; RegistryPath := ASourceOptions.RegistryPath; StoreToIniFile := ASourceOptions.StoreToIniFile; StoreToRegistry := ASourceOptions.StoreToRegistry; end else inherited; end; function TdxStoringOptions.CanStoreToIniFile: Boolean; begin Result := StoreToIniFile and (IniFileName <> ''); end; function TdxStoringOptions.CanStoreToRegistry: Boolean; begin Result := StoreToRegistry and (RegistryPath <> ''); end; function TdxStoringOptions.CanRestoreFromIniFile: Boolean; begin Result := CanStoreToIniFile and FileExists(IniFileName); end; function TdxStoringOptions.CanRestoreFromRegistry: Boolean; var ARegistry: TRegistry; begin Result := CanStoreToRegistry; if Result then begin ARegistry := TRegistry.Create(KEY_ALL_ACCESS); try Result := ARegistry.OpenKey(RegistryPath, False); ARegistry.CloseKey; finally ARegistry.Free; end; end; end; { TdxLayoutControlDragAndDropObject } destructor TdxLayoutControlDragAndDropObject.Destroy; begin SourceItem := nil; inherited; end; function TdxLayoutControlDragAndDropObject.CanDrop: Boolean; begin Result := (DestinationItem <> nil) or (SourceControl.ViewInfo.GetHitTest(CurMousePos).HitTestCode in [htTreeViewItems, htClientArea, htGroup, htItem]); end; function TdxLayoutControlDragAndDropObject.CanRemove: Boolean; begin Result := (SourceControl.ViewInfo.GetHitTest(CurMousePos).HitTestCode in [htAvailableItems, htNone]) and SourceItem.CanRemove and (Source <> dsCustomizeFormAvailableItems); end; function TdxLayoutControlDragAndDropObject.GetSourceControl: TdxCustomLayoutControl; begin Result := TdxCustomLayoutControl(inherited Control); end; procedure TdxLayoutControlDragAndDropObject.ResetDragAndDrop; begin SourceItem := nil; DestinationItem := nil; DestinationGroup := nil; 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 FDestinationImage := TcxDragDestinationImage.Create; FDestinationImage.ParentControl := 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; const Cursors: array [Boolean, Boolean] of TCursor = ( (crcxNoDrop, crdxLayoutControlDrag), (crcxRemove, crdxLayoutControlDrag)); begin Result := Cursors[CanRemove, CanDrop]; end; procedure TdxLayoutControlDragAndDropObject.PaintDestinationImage; function GetAreaPartBounds: TRect; const Width = 2; var AGroup: TdxLayoutGroup; begin Result := DestinationItem.ViewInfo.SelectionBorderRect; case AreaPart of apLeft: with Result do Right := Left + Width; apTop: with Result do Bottom := Top + Width; apRight: with Result do Left := Right - Width; apBottom: with Result do Top := Bottom - Width; apCenter: begin AGroup := DestinationItem as TdxLayoutGroup; Result := AGroup.ViewInfo.ClientBounds; case AGroup.LayoutDirection of ldHorizontal: with Result do Right := Left + Width; ldVertical: with Result do Bottom := Top + Width; end; InflateRect(Result, Integer(cxRectWidth(Result) = 0), Integer(cxRectHeight(Result) = 0)); end; else Result := cxInvalidRect; end; end; 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 := GetAreaPartBounds; 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 SourceItem.IsAvailable then Result := Rect(-AViewInfo.CalculateMinWidth, -AViewInfo.CalculateMinHeight, 0, 0) else begin Result := AViewInfo.Bounds; if AHasBorderChanged then Result := TdxLayoutGroupViewInfo(AViewInfo).GetItemAreaBounds(Result); end; end; var ANeedDestroyViewInfo: Boolean; APrevHasBorder: Boolean; APrevBounds: TRect; begin if SourceItem.IsAvailable then begin AViewInfo := SourceItem.GetViewInfoClass.Create(SourceControl.ViewInfo, nil, SourceItem); ANeedDestroyViewInfo := True; end else begin AViewInfo := SourceItem.ViewInfo; ANeedDestroyViewInfo := False; APrevBounds := AViewInfo.Bounds; end; try APrevHasBorder := SourceItem.ViewInfo.HasBorder; SourceControl.ViewInfo.IsDragImagePainted := True; try AViewInfo.Calculate(GetViewInfoBounds(SourceItem.ViewInfo.HasBorder <> APrevHasBorder)); FDragImage.SetBounds(0, 0, cxRectWidth(GetItemDragBounds), cxRectHeight(GetItemDragBounds)); FDragImage.Canvas.WindowOrg := GetItemDragBounds.TopLeft; try with AViewInfo.GetPainterClass.Create(FDragImage.Canvas, AViewInfo) do try Paint; DoDrawSelectionFrame; PaintSpecificPart; finally Free; end; finally FDragImage.Canvas.WindowOrg := cxNullPoint; end; CalculateDragImageOffset; finally SourceControl.ViewInfo.IsDragImagePainted := False; end; finally if ANeedDestroyViewInfo then AViewInfo.Destroy else AViewInfo.Calculate(APrevBounds); end; end; procedure TdxLayoutControlDragAndDropObject.RefreshDestinationImage; var P: TPoint; begin if (DestinationItem = nil) or (AreaPart = apNone) 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([]); 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 TdxCustomLayoutControl(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(const P: TPoint); var AHitTest: TdxCustomLayoutHitTest; begin // DetermineDestinationItems(ADestItems); // UpdatedestinationPlaces(AScreenPoint, ADestItems, ADestinationItem); if IsWindowVisible(DestinationControl.Handle) then AHitTest := DestinationControl.ViewInfo.GetHitTest(P) else AHitTest := nil; if AHitTest is TdxCustomLayoutItemHitTest then DestinationItem := TdxCustomLayoutItemHitTest(AHitTest).Item else if (AHitTest <> nil) and (AHitTest.HitTestCode = htClientArea) then DestinationItem := DestinationControl.Items else DestinationItem := nil; if (DestinationItem = SourceItem) or ((DestinationItem is TdxLayoutGroup) and not SourceItem.CanMoveTo(DestinationItem)) then DestinationItem := nil; end; procedure DetermineAreaPart(const P: TPoint); begin if DestinationItem <> nil then AreaPart := DestinationItem.ViewInfo.GetAreaPart(P) else AreaPart := apNone; end; procedure DetermineDestinationGroup; begin if DestinationItem = nil then DestinationGroup := nil else begin if DestinationItem.IsRoot or (AreaPart in [apCenter]) then DestinationGroup := TdxLayoutGroup(DestinationItem) else DestinationGroup := DestinationItem.Parent; end; end; var AScreenPoint, ADestPoint, ADragImagePoint: TPoint; begin AScreenPoint := Control.ClientToScreen(P); DetermineDestinationControl(AScreenPoint); ADestPoint := DestinationControl.ScreenToClient(AScreenPoint); ADragImagePoint := cxPointOffset(AScreenPoint, FDragImageOffset); ShowDragImage(ADragImagePoint); DetermineDestinationItem(ADestPoint); DetermineAreaPart(ADestPoint); DetermineDestinationGroup; Accepted := AreaPart <> apNone; if FNeedRepaintDestinationImage then RefreshDestinationImage; inherited; end; procedure TdxLayoutControlDragAndDropObject.EndDragAndDrop(Accepted: Boolean); type TActionType = (atNone, atInsert, atCreateGroup, atContentInsert); function GetDestPosition: Integer; begin case AreaPart of apRight, apBottom: if DestinationItem.IsRoot then Result := DestinationGroup.VisibleCount + 1 else Result := DestinationItem.VisibleIndex + 1; apLeft, apTop: if DestinationItem.IsRoot then Result := 0 else Result := DestinationItem.VisibleIndex; else Result := 0; end; if (SourceItem.Parent = DestinationItem.Parent) and (SourceItem.VisibleIndex < Result) then Dec(Result); end; function GetLayoutDirection: TdxLayoutDirection; begin Result := DestinationGroup.LayoutDirection; end; function GetOrthogonalDirection: TdxLayoutDirection; begin Result := DestinationGroup.GetHelperClass.GetOrthogonalDirection; end; function IsHorizontalAreaPart: Boolean; begin Result := AreaPart in [apLeft, apRight]; end; function GetActionType: TActionType; begin if AreaPart = apNone then Result := atNone else if (AreaPart = apCenter) or not DestinationItem.IsRoot and ((GetLayoutDirection = ldHorizontal) and IsHorizontalAreaPart or (GetLayoutDirection = ldVertical) and not IsHorizontalAreaPart or (GetLayoutDirection = ldTabbed)) then Result := atInsert else Result := atCreateGroup; 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); end; var ANeedUpdateCustomizeForm: Boolean; begin FreeAndNil(FDragImage); Dirty := True; if CanProcessDrop then begin ANeedUpdateCustomizeForm := False; SourceControl.CustomizeFormBeginUpdate; DestinationControl.CustomizeFormBeginUpdate; try SourceControl.BeginUpdate; DestinationControl.BeginUpdate; try if CanDrop and (DestinationItem <> nil) then begin ANeedUpdateCustomizeForm := True; case GetActionType of atInsert: DoInsert; atCreateGroup: DoCreateGroup; atContentInsert: DoContentInsert; end; end else if CanRemove then begin SourceItem.Parent := nil; ANeedUpdateCustomizeForm := True; end; finally SourceItem := nil; DestinationItem := nil; DestinationGroup := nil; SourceControl.EndUpdate; DestinationControl.EndUpdate; end; finally SourceControl.CustomizeFormCancelUpdate; DestinationControl.CustomizeFormCancelUpdate; if ANeedUpdateCustomizeForm then begin SourceControl.CustomizeFormUpdate([cfutContent, cfutSelection]); if (DestinationControl <> SourceControl) and DestinationControl.IsCustomization then DestinationControl.CustomizeFormUpdate([cfutContent, cfutSelection]); end; end; SourceControl.Update; if DestinationControl <> SourceControl then DestinationControl.Update; SourceControl.Modified; end else ResetDragAndDrop; inherited; end; procedure TdxLayoutControlDragAndDropObject.Init(ASource: TdxLayoutDragSource; ASourceItem: TdxCustomLayoutItem); begin SourceControl.Update; Source := ASource; SourceItem := ASourceItem; FStartDragPoint := GetMouseCursorPos; end; initialization Screen.Cursors[crdxLayoutControlDrag] := LoadCursor(HInstance, 'DXLAYOUTCONTROLDRAGCURSOR'); RegisterClasses([TdxLayoutItem, TdxLayoutGroup, TdxLayoutAlignmentConstraint]); HitTests := THitTests.Create; dxLayoutSelectionHelperClass := TdxLayoutRunTimeSelectionHelper; finalization FreeAndNil(HitTests); FreeAndNil(FGlobalCanvas); end.