{********************************************************************} { } { 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, ImgList, dxCore, cxClasses, cxGeometry, cxGraphics, cxControls, cxLookAndFeels, cxLibraryConsts, dxLayoutLookAndFeels, dxLayoutCommon, cxPC, dxLayoutSelection; 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; DXM_INVALIDATESELECTIONLAYER = WM_DX + 28; 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; TdxLayoutItemCaptionViewInfo = 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; TdxLayoutGroupViewInfoTabbedSpecific = class; // 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, apBefore, apAfter, apBeforeContent, apAfterContent, apFirstChild, apLastChild); TdxLayoutActionType = (atNone, atInsert, atCreateGroup, atContentInsert); { CustomizeForm } TdxLayoutControlCustomCustomizeForm = class(TForm) private FControl: TdxCustomLayoutControl; procedure SetControl(AValue: TdxCustomLayoutControl); protected procedure CreateParams(var Params: TCreateParams); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure InitializeControl; virtual; public destructor Destroy; override; function GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; virtual; procedure UpdateCaption; virtual; procedure UpdateContent; virtual; procedure UpdateSelection; virtual; procedure UpdateView; virtual; property Control: TdxCustomLayoutControl read FControl write SetControl; end; TdxLayoutControlCustomCustomizeFormClass = class of TdxLayoutControlCustomCustomizeForm; TdxCustomLayoutItemOptions = class(TPersistent) private FItem: TdxCustomLayoutItem; protected procedure Changed; virtual; property Item: TdxCustomLayoutItem read FItem; public constructor Create(AItem: TdxCustomLayoutItem); virtual; end; { TdxLayoutItemImageOptions } TdxCustomLayoutItemImageOptions = class(TdxCustomLayoutItemOptions) private FGlyph: TBitmap; FImageIndex: Integer; procedure SetGlyph(AValue: TBitmap); procedure SetImageIndex(AValue: Integer); procedure GlyphChanged(Sender: TObject); protected procedure BeginUpdate; procedure EndUpdate; function GetCurrentImage(out AImage: TBitmap; out AImageList: TCustomImageList; out AImageIndex: Integer): Boolean; function GetImageList(AEnabled: Boolean): TCustomImageList; function GetImageSize: TSize; function IsImageAssigned: Boolean; public constructor Create(AItem: TdxCustomLayoutItem); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; published property Glyph: TBitmap read FGlyph write SetGlyph; property ImageIndex: Integer read FImageIndex write SetImageIndex default -1; end; TdxLayoutItemCaptionVisibleElement = (cveImage, cveText); TdxLayoutItemCaptionVisibleElements = set of TdxLayoutItemCaptionVisibleElement; TdxCustomLayoutItemCaptionOptions = class(TdxCustomLayoutItemOptions) private FAlignHorz: TAlignment; FImageOptions: TdxCustomLayoutItemImageOptions; FShowAccelChar: Boolean; FText: string; FVisibleElements: TdxLayoutItemCaptionVisibleElements; FVisible: Boolean; function GetGlyph: TBitmap; function GetImageIndex: Integer; procedure SetAlignHorz(Value: TAlignment); procedure SetGlyph(AValue: TBitmap); procedure SetImageIndex(AValue: Integer); procedure SetImageOptions(Value: TdxCustomLayoutItemImageOptions); procedure SetShowAccelChar(Value: Boolean); procedure SetText(const Value: string); procedure SetVisibleElements(Value: TdxLayoutItemCaptionVisibleElements); procedure SetVisible(Value: Boolean); protected property Glyph: TBitmap read GetGlyph write SetGlyph; property ImageIndex: Integer read GetImageIndex write SetImageIndex default -1; property ImageOptions: TdxCustomLayoutItemImageOptions read FImageOptions write SetImageOptions; property VisibleElements: TdxLayoutItemCaptionVisibleElements read FVisibleElements write SetVisibleElements default [cveImage, cveText]; public constructor Create(AItem: TdxCustomLayoutItem); override; destructor Destroy; override; published property AlignHorz: TAlignment read FAlignHorz write SetAlignHorz default taLeftJustify; property ShowAccelChar: Boolean read FShowAccelChar write SetShowAccelChar default True; property Text: string read FText write SetText; property Visible: Boolean read FVisible write SetVisible 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; TdxLayoutItemChangeType = (ictHard, ictMedium, ictLight); TdxCustomLayoutItemAssignedValue = (liavEnabled); TdxCustomLayoutItemAssignedValues = set of TdxCustomLayoutItemAssignedValue; TdxCustomLayoutItem = class(TComponent, IdxLayoutLookAndFeelUser, IdxLayoutSelectableItem) private FAlignHorz: TdxLayoutAlignHorz; FAlignmentConstraint: TdxLayoutAlignmentConstraint; FAlignVert: TdxLayoutAlignVert; FAllowRemove: Boolean; FAssignedValues: TdxCustomLayoutItemAssignedValues; FCachedTextHeight: Integer; FCaptionOptions: TdxCustomLayoutItemCaptionOptions; FContainer: TdxCustomLayoutControl; FEnabled: Boolean; FLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; FOffsets: TdxLayoutOffsets; FParent: TdxLayoutGroup; 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 GetCaption: string; function GetCaptionForCustomizeForm: string; function GetEnabled: Boolean; 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; // LayoutLookAndFeel 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 CanDragAndDrop: Boolean; virtual; function CanFocusOnClick(X, Y: Integer): Boolean; virtual; function CanProcessAccel(out AItem: TdxCustomLayoutItem): Boolean; virtual; abstract; function CanRemove: Boolean; virtual; procedure CustomizationChanged; 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 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 CanInit: Boolean; virtual; procedure DoInit; virtual; procedure Init; function HasCaption: Boolean; virtual; // #DG !!! 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: TComponent): Boolean; virtual; procedure SelectComponent(AShift: TShiftState = []); virtual; procedure SelectParent; virtual; procedure SelectionChanged; virtual; function IdxLayoutSelectableItem.IsVisible = IsSelectableItemVisible; function IsSelectableItemVisible: Boolean; virtual; function IdxLayoutSelectableItem.IsDragged = GetIsDragged; property CachedTextHeight: Integer read FCachedTextHeight write FCachedTextHeight; 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 GetCaption write SetCaption stored False; // obsolette property CaptionOptions: TdxCustomLayoutItemCaptionOptions read FCaptionOptions write FCaptionOptions; property Enabled: Boolean read GetEnabled 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 stored False; // obsolette 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; procedure InternalLayoutLookAndFeelChanged; 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 Glyph; property ImageIndex; property Layout: TdxCaptionLayout read FLayout write SetLayout default clLeft; property VisibleElements; 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; FCustomizeControlHelper: TdxControlsDesignSelectorHelper; 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 CanFocusOnClick(X, Y: Integer): Boolean; override; function CanProcessAccel(out AItem: TdxCustomLayoutItem): Boolean; override; procedure ContainerChanged; override; procedure CustomizationChanged; override; procedure DoCaptionDown; override; function GetParentManagedAlignVert: TdxLayoutAlignVert; override; function GetBaseName: string; override; function GetViewInfoClass: TdxCustomLayoutItemViewInfoClass; override; procedure DoInit; 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; class function GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; virtual; 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 CustomizationChanged; override; procedure DoPack; 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; 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 IsSuperfluous: Boolean; 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; { 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; { controls } { TdxLayoutImageOptions } TdxLayoutImageOptions = class(TdxLayoutControlPersistent) private FDisabledImages: TCustomImageList; FDisabledImagesChangeLink: TChangeLink; FImages: TCustomImageList; FImagesChangeLink: TChangeLink; FNotifyComponent: TcxFreeNotificator; procedure SetImages(AValue: TCustomImageList); procedure SetDisabledImages(AValue: TCustomImageList); procedure DisabledImagesChange(Sender: TObject); procedure ImagesChange(Sender: TObject); procedure SetImageList(var ANewValue, AOldValue: TCustomImageList; const AChangeLink: TChangeLink); procedure FreeNotification(AComponent: TComponent); protected procedure Changed; override; procedure BeginUpdate; procedure EndUpdate; public constructor Create(AControl: TdxCustomLayoutControl); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; published property DisabledImages: TCustomImageList read FDisabledImages write SetDisabledImages; property Images: TCustomImageList read FImages write SetImages; end; { TdxUndoRedoManager } TdxUndoRedoManager = class(TdxLayoutControlPersistent) private FUndoList: TcxObjectList; FIndex: Integer; FCurrentLayout: TMemIniFile; FLockCount: Integer; procedure AddUndo(ALayout: TMemIniFile); function GetRedoCount: Integer; function GetUndoCount: Integer; protected procedure SaveLayout; function IsLocked: Boolean; property RedoCount: Integer read GetRedoCount; property UndoCount: Integer read GetUndoCount; public constructor Create(AControl: TdxCustomLayoutControl); override; destructor Destroy; override; function CanRedo: Boolean; function CanUndo: Boolean; procedure Redo; procedure Undo; procedure Clear; end; { TdxStoringOptions } 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, cfutView); TdxLayoutCustomizeFormUpdateTypes = set of TdxLayoutCustomizeFormUpdateType; TdxLayoutAutoContentSizes = set of TdxLayoutAutoContentSize; TdxCustomLayoutControl = class(TcxControl, IdxLayoutLookAndFeelUser, IdxLayoutComponent, IdxSkinSupport, IdxLayoutDesignerHelper, IdxSelectionChanged, IdxCustomizeControlsHelper) private FAlignmentConstraints: TList; FAutoControlAlignment: Boolean; FAutoControlTabOrders: Boolean; FBoldFont: TFont; FFocusControlOnItemCaptionClick: Boolean; FItemWithMouse: TdxCustomLayoutItem; FLeftPos: Integer; FLoadingCount:Integer; FRightButtonPressed: Boolean; FShowHiddenGroupsBounds: Boolean; FTopPos: Integer; FUpdateLockCount: Integer; // Objects FOptionsImage: TdxLayoutImageOptions; FOptionsStoring: TdxStoringOptions; FRootGroup: TdxLayoutGroup; FLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; FPainter: TdxLayoutControlPainter; FViewInfo: TdxLayoutControlViewInfo; // Items FAbsoluteItems: TcxComponentList; FAvailableItems: TcxComponentList; // Customization FShowDesignSelectors: Boolean; FHighlightRoot: Boolean; FCustomization: Boolean; FCustomizeAvailableItemsViewKind: TdxLayoutAvailableItemsViewKind; FCustomizeForm: TdxLayoutControlCustomCustomizeForm; FCustomizeFormBounds: TRect; FCustomizeFormClass: TdxLayoutControlCustomCustomizeFormClass; FCustomizeFormTabbedView: Boolean; FCustomizeFormUpdateLockCount: Integer; // Internal Flags FIsPlaceControlsNeeded: Boolean; FIsPlacingControls: Boolean; // Storing FStoredStream: TMemoryStream; // UndoRedo FUndoRedoManager: TdxUndoRedoManager; 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 GetIsLayoutLoading: Boolean; function GetLayoutDirection: TdxLayoutDirection; function GetOccupiedClientWidth: Integer; function GetOccupiedClientHeight: 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 SetOptionsImage(Value: TdxLayoutImageOptions); 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); // 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; procedure DXMInvalidateSelectionLayer(var Message: TMessage); message DXM_INVALIDATESELECTIONLAYER; protected FSelectionHelper: IdxLayoutDesignerHelper; procedure AlignControls(AControl: TControl; var Rect: TRect); override; procedure CreateParams(var Params: TCreateParams); override; {$IFNDEF DELPHI12} procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; {$ENDIF} function GetCursor(X, Y: Integer): TCursor; 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; // Conditions function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override; function CanFocusOnClick(X, Y: Integer): Boolean; override; function HasBackground: Boolean; override; function IsInternalControl(AControl: TControl): Boolean; override; function NeedRedrawOnResize: Boolean; override; // Notifications procedure BoundsChanged; override; procedure FontChanged; override; // Mouse procedure DblClick; 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; // Scrollbars procedure InitScrollBarsParameters; override; function NeedsToBringInternalControlsToFront: Boolean; override; procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); override; // Drag and Drop function AllowAutoDragAndDropAtDesignTime(X, Y: Integer; Shift: TShiftState): Boolean; override; function AllowDragAndDropWithoutFocus: Boolean; override; function CanDrag(X, Y: Integer): Boolean; 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; //IdxCustomizeControlsHelper function CanProcessChildren: Boolean; virtual; 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 PostFree(AObject: TObject); procedure ScrollContent(APrevPos, ACurPos: Integer; AHorzScrolling: Boolean); // selections function GetSelectionHelperClass: TdxLayoutRunTimeSelectionHelperClass; procedure InvalidateSelectionLayer(const R: TRect); virtual; procedure PostBuildSelectionLayer; virtual; procedure PostInvalidateSelectionLayer(const R: TRect); virtual; // storing function GetRootSectionName(AIniFile: TCustomIniFile): string; procedure InternalLoadFromCustomIniFile(AIniFile: TCustomIniFile; ADestroyNonLoadedItems: Boolean); virtual; procedure InternalSaveToCustomIniFile(AIniFile: TCustomIniFile); virtual; procedure LoadFromCustomIniFile(AIniFile: TCustomIniFile); virtual; procedure SaveToCustomIniFile(AIniFile: TCustomIniFile); virtual; // IdxLayoutDesignerHelper procedure AddSelectionChangedListener(AListener: TPersistent); function IsActive: Boolean; function CanDeleteComponent(AComponent: TComponent): Boolean; procedure ClearSelection; procedure DeleteSelection; procedure GetSelection(AList: TList); function IsComponentSelected(AComponent: TPersistent): Boolean; procedure RemoveSelectionChangedListener(AListener: TPersistent); procedure SelectComponent(AComponent: TPersistent; AShift: TShiftState = []); procedure SetSelection(AList: TList); function UniqueName(const BaseName: string): string; //IdxSelectionChanged procedure IdxSelectionChanged.SelectionChanged = LayoutSelectionChanged; procedure LayoutSelectionChanged(ASelection: TList; AAction: TdxSelectionAction); // Undo procedure SaveToUndo; property AllowDrop: Boolean read GetAllowDrop; property BoldFont: TFont read FBoldFont; property IsPlaceControlsNeeded: Boolean read FIsPlaceControlsNeeded write SetIsPlaceControlsNeeded; property IsLayoutLoading: Boolean read GetIsLayoutLoading; property ItemWithMouse: TdxCustomLayoutItem read FItemWithMouse write SetItemWithMouse; property cxLookAndFeel: TcxLookAndFeel read GetCxLookAndFeel; 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: TdxLayoutControlCustomCustomizeForm read FCustomizeForm; property CustomizeFormBounds: TRect read FCustomizeFormBounds write FCustomizeFormBounds; property CustomizeFormClass: TdxLayoutControlCustomCustomizeFormClass read FCustomizeFormClass write FCustomizeFormClass; 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; // Options property OptionsImage: TdxLayoutImageOptions read FOptionsImage write SetOptionsImage; // 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; // Undo property UndoRedoManager: TdxUndoRedoManager read FUndoRedoManager; 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; // Options property OptionsImage; // 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 private FHitItem: TdxCustomLayoutItem; FHitPoint: TPoint; public function Cursor: TCursor; dynamic; class function HitTestCode: Integer; virtual; class function Instance: TdxCustomLayoutHitTest; function IsDeterminedAreaPart: Boolean; virtual; function GetAreaPart: TdxLayoutAreaPart; virtual; function GetGroupForInsert: TdxLayoutGroup; virtual; function GetDesinationItem: TdxCustomLayoutItem; virtual; function GetSourceItem: TdxCustomLayoutItem; virtual; property HitItem: TdxCustomLayoutItem read FHitItem write FHitItem; property HitPoint: TPoint read FHitPoint write FHitPoint; end; TdxCustomLayoutItemHitTest = class(TdxCustomLayoutHitTest); TdxLayoutNoneHitTest = class(TdxCustomLayoutHitTest) public class function HitTestCode: Integer; override; end; TdxCustomLayoutItemHitTestClass = class of TdxCustomLayoutItemHitTest; TdxLayoutItemHitTest = class(TdxCustomLayoutItemHitTest) private function GetHitItem: TdxLayoutItem; procedure SethitItem(Value: TdxLayoutItem); public class function HitTestCode: Integer; override; function GetGroupForInsert: TdxLayoutGroup; override; property HitItem: TdxLayoutItem read GetHitItem write SetHitItem; end; TdxLayoutGroupHitTest = class(TdxCustomLayoutItemHitTest) private function GetHitItem: TdxLayoutGroup; procedure SetHitItem(Value: TdxLayoutGroup); public class function HitTestCode: Integer; override; function GetGroupForInsert: TdxLayoutGroup; override; property HitItem: TdxLayoutGroup read GetHitItem write SetHitItem; end; TdxLayoutTabbedGroupHitTest = class(TdxLayoutGroupHitTest) private function GetSpecific: TdxLayoutGroupViewInfoTabbedSpecific; property Specific: TdxLayoutGroupViewInfoTabbedSpecific read GetSpecific; public function GetDesinationItem: TdxCustomLayoutItem; override; function GetSourceItem: TdxCustomLayoutItem; override; end; TdxLayoutCustomizeFormHitTest = class(TdxCustomLayoutHitTest) public class function HitTestCode: Integer; override; function IsDeterminedAreaPart: Boolean; override; function GetAreaPart: TdxLayoutAreaPart; override; function GetDesinationItem: TdxCustomLayoutItem; override; end; TdxLayoutCustomizeFormAvailableItemsHitTest = class(TdxLayoutCustomizeFormHitTest) public class function HitTestCode: Integer; override; end; TdxLayoutCustomizeFormTreeViewItemsHitTest = class(TdxLayoutCustomizeFormHitTest) public class function HitTestCode: Integer; override; end; TdxLayoutClientAreaHitTest = class(TdxCustomLayoutHitTest) private FControl: TdxCustomLayoutControl; public class function HitTestCode: Integer; override; function GetGroupForInsert: TdxLayoutGroup; override; function GetDesinationItem: TdxCustomLayoutItem; 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 DoDrawGlyph; virtual; procedure AfterDrawText; virtual; procedure BeforeDrawText; virtual; procedure DoPaint; virtual; procedure DrawBackground; virtual; procedure DrawGlyph; 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; FOriginalBounds: TRect; protected function GetLayoutLookAndFeel: TdxCustomLayoutLookAndFeel; virtual; abstract; property OriginalBounds: TRect read FOriginalBounds; 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 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 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 GetIsImageVisible: Boolean; function GetIsTextVisible: Boolean; 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 GetSpaceBetweenImageText: Integer; virtual; function GetText: string; virtual; function GetTextAreaBounds: TRect; virtual; function GetTextColor: TColor; virtual; function GetTextHotColor: TColor; virtual; function GetTextNormalColor: TColor; virtual; function GetTextHeight: Integer; virtual; function GetTextWidth: Integer; virtual; function GetVisibleText: string; virtual; function IsNeedSpaceBetweenImageText: Boolean; function IsPointInHotTrackBounds(const P: TPoint): Boolean; virtual; procedure PrepareCanvas; virtual; function GetImageAreaBounds: TRect; virtual; function GetImageBounds: TRect; virtual; function GetImageHeight: Integer; virtual; function GetImageWidth: Integer; 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 ImageAreaBounds: TRect read GetImageAreaBounds; property ImageBounds: TRect read GetImageBounds; property ImageHeight: Integer read GetImageHeight; property ImageWidth: Integer read GetImageWidth; property IsCustomization: Boolean read GetIsCustomization; property IsDefaultColor: Boolean read GetIsDefaultColor; property IsHotTrackable: Boolean read GetIsHotTrackable; property IsImageVisible: Boolean read GetIsImageVisible; property IsTextVisible: Boolean read GetIsTextVisible; 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(const P: TPoint): 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 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 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 GetSpaceBetweenImageText: Integer; override; function GetTextAreaBounds: TRect; override; function GetTextWidth: Integer; override; property IsFixedWidth: Boolean read GetIsFixedWidth; property Item: TdxLayoutItem read GetItem; property ItemViewInfo: TdxLayoutItemViewInfo read GetItemViewInfo; public 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 procedure CorrectAreaPart(var AAreaPart: TdxLayoutAreaPart); virtual; function GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; virtual; abstract; function GetAreaPart(const P: TPoint): TdxLayoutAreaPart; virtual; function GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): TRect; 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 GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; override; function GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): 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 IsAtInsertionPos(const R: TRect; const P: TPoint): Boolean; override; end; TdxLayoutGroupViewInfoVerticalSpecific = class(TdxLayoutGroupViewInfoSpecific) protected procedure ConvertCoords(var R: TRect); override; function GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; override; function GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): 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 FOnPaint: TNotifyEvent; procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST; protected procedure BoundsChanged; override; function GetDesignHitTest(X, Y: Integer; Shift: TShiftState): Boolean; override; procedure Paint; override; procedure DoPaint; property OnPaint: TNotifyEvent read FOnPaint write FOnPaint; 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 FSpecificPainting: Boolean; FTabControl: TdxLayoutTabbedGroupTabControl; FTabControlElementViewInfo: TdxTabControlElementViewInfo; procedure ActiveTabChanged(ASender: TObject); procedure TabControlPaint(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 GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; override; procedure CorrectAreaPart(var AAreaPart: TdxLayoutAreaPart); override; function GetAreaPart(const P: TPoint): TdxLayoutAreaPart; override; function GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): TRect; 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 procedure CorrectAreaPart(var AAreaPart: TdxLayoutAreaPart); function GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; function GetAreaPart(const P: TPoint): TdxLayoutAreaPart; override; function GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): TRect; // 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; var dxLayoutDesignTimeSelectionHelperClass: TdxLayoutRunTimeSelectionHelperClass; dxLayoutRunTimeSelectionHelperClass: TdxLayoutRunTimeSelectionHelperClass; implementation {$R *.res} uses Types, TypInfo, Menus, Registry, Math, Variants, {$IFDEF DELPHI7} UxTheme, Themes, {$ENDIF} cxContainer, dxOffice11, dxLayoutControlAdapters, dxLayoutCustomizeForm, dxLayoutStrs, dxLayoutDragAndDrop; 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 = 2; dxLayoutGlyphSpace = 4; dxLayoutSelectionMarkerWidth = 5; dxLayoutThinPartWidth = 2; 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 { TdxCustomizationControlHelper } TdxCustomizationControlHelper = class(TdxControlsDesignSelectorHelper) private FLayoutItem: TdxLayoutItem; FIsValuesStored: Boolean; FStoredSelStart: Integer; FStoredSelEnd: Integer; FStoredTabStop: Boolean; procedure SetLayoutItem(AValue: TdxLayoutItem); protected function DoControlWndProc(var Message: TMessage): Boolean; override; function GetChildClass: TdxControlsDesignSelectorHelperClass; override; function IsActiveDesignSelector: Boolean; override; function IsSelected: Boolean; override; function IsValid: Boolean; override; function CanDrawDesignSelector: Boolean; override; function IsCustomization: Boolean; function IsDesigning: Boolean; procedure CustomizationChanged; procedure StoreValues; procedure RestoreValues; public destructor Destroy; override; procedure Assign(Source: TPersistent); override; property LayoutItem: TdxLayoutItem read FLayoutItem write SetLayoutItem; end; { TdxDesignCustomizationHelper } TdxDesignCustomizationHelper = class private FLayoutControls: TcxComponentList; protected function FindActiveDesigner(out ADesigner: IdxLayoutDesignerHelper): Boolean; public constructor Create; destructor Destroy; override; class procedure AddLayout(ALayout: TdxCustomLayoutControl); class procedure RemoveLayout(ALayout: TdxCustomLayoutControl); 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; FDesignCustomizationHelper: TdxDesignCustomizationHelper; function dxDesignCustomizationHelper: TdxDesignCustomizationHelper; begin if FDesignCustomizationHelper = nil then FDesignCustomizationHelper := TdxDesignCustomizationHelper.Create; Result := FDesignCustomizationHelper; end; 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; { TdxCustomizationControlHelper } destructor TdxCustomizationControlHelper.Destroy; begin RestoreValues; inherited Destroy; end; procedure TdxCustomizationControlHelper.Assign(Source: TPersistent); var AItem: TdxCustomizationControlHelper; begin if Source is TdxCustomizationControlHelper then begin AItem := Source as TdxCustomizationControlHelper; FLayoutItem := AItem.LayoutItem; end; inherited Assign(Source); end; function TdxCustomizationControlHelper.DoControlWndProc(var Message: TMessage): Boolean; begin Result := True; if IsValid and IsCustomization then case Message.Msg of WM_NCHITTEST: begin Message.Result := HTTRANSPARENT; Result := False; end; CM_HITTEST: begin Message.Result := HTNOWHERE; Result := False; end; end; if IsValid then case Message.Msg of WM_PAINT, WM_ERASEBKGND, WM_NCPAINT, CM_INVALIDATE, CM_TEXTCHANGED: if (Control = nil) or not (csPaintCopy in Control.ControlState) then LayoutItem.Container.PostInvalidateSelectionLayer(LayoutItem.ViewInfo.ControlViewInfo.Bounds); end; Result := Result and inherited DoControlWndProc(Message);; end; function TdxCustomizationControlHelper.GetChildClass: TdxControlsDesignSelectorHelperClass; begin Result := TdxCustomizationControlHelper; end; procedure TdxCustomizationControlHelper.CustomizationChanged; begin if not IsValid then Exit; if IsCustomization then StoreValues else RestoreValues; end; procedure TdxCustomizationControlHelper.StoreValues; var I: Integer; begin if not IsValid or not IsWinControl or IsDesigning or FIsValuesStored then Exit; SendMessage(ControlWnd, EM_GETSEL, Integer(@FStoredSelStart), Integer(@FStoredSelEnd)); SendMessage(ControlWnd, EM_SETSEL, FStoredSelEnd, FStoredSelEnd); if Control <> nil then begin FStoredTabStop := ControlAsWinControl.TabStop; ControlAsWinControl.TabStop := False; end; FIsValuesStored := True; for I := 0 to Children.Count - 1 do TdxCustomizationControlHelper(Children[I]).StoreValues; end; procedure TdxCustomizationControlHelper.RestoreValues; var I: Integer; begin if not IsValid or not IsWinControl or IsDesigning or not FIsValuesStored then Exit; SendMessage(ControlWnd, EM_SETSEL, FStoredSelStart, FStoredSelEnd); if Control <> nil then ControlAsWinControl.TabStop := FStoredTabStop; FIsValuesStored := False; for I := 0 to Children.Count - 1 do TdxCustomizationControlHelper(Children[I]).RestoreValues; end; function TdxCustomizationControlHelper.IsActiveDesignSelector: Boolean; begin Result := inherited IsActiveDesignSelector and IsDesigning and LayoutItem.Container.ShowDesignSelectors; end; function TdxCustomizationControlHelper.IsSelected: Boolean; begin Result := (not LayoutItem.Container.Customization and LayoutItem.ViewInfo.Selected) or (LayoutItem.Container.Customization and LayoutItem.Container.IsComponentSelected(LayoutItem.Control)); end; function TdxCustomizationControlHelper.IsCustomization: Boolean; begin Result := LayoutItem.Container.Customization; end; function TdxCustomizationControlHelper.IsDesigning: Boolean; begin Result := LayoutItem.IsDesigning; end; function TdxCustomizationControlHelper.IsValid: Boolean; begin Result := inherited IsValid and (LayoutItem <> nil) and (LayoutItem.ViewInfo <> nil); end; function TdxCustomizationControlHelper.CanDrawDesignSelector: Boolean; begin Result := inherited CanDrawDesignSelector and LayoutItem.ActuallyVisible; end; procedure TdxCustomizationControlHelper.SetLayoutItem(AValue: TdxLayoutItem); begin if AValue <> FLayoutItem then begin FLayoutItem := AValue; CheckChildren; end; end; { TdxDesignCustomizationHelper } var FKeyboardHookHandle: HHOOK; function IsParentFocused(AParent: THandle): Boolean; begin Result := (AParent <> 0) and ((AParent = GetFocus) or IsChildClassWindow(AParent) and IsParentFocused(GetParent(AParent))); end; function ProcessKeyboardMessage(AKey: WPARAM; AFlags: LPARAM): Boolean; function SelectItemParent(AComponent: TComponent): Boolean; var AIntf: IdxLayoutSelectableItem; begin Result := Supports(AComponent, IdxLayoutSelectableItem, AIntf); if Result then AIntf.SelectParent; end; function KeyPressed: Boolean; begin Result := (AFlags shr 31) and 1 = 0; end; function IsDragged(AList: TcxComponentList): Boolean; var I: Integer; AIntf: IdxLayoutSelectableItem; begin Result := False; for I := 0 to AList.Count - 1 do begin Result := Supports(AList[I], IdxLayoutSelectableItem, AIntf) and AIntf.IsDragged; if Result then Break; end; end; function CanProcessKeyDown(AList: TcxComponentList): Boolean; begin Result := not IsDragged(AList); end; var AList: TcxComponentList; ADesigner: IdxLayoutDesignerHelper; begin Result := KeyPressed; if Result then begin AList := TcxComponentList.Create; try if dxDesignCustomizationHelper.FindActiveDesigner(ADesigner) then ADesigner.GetSelection(AList); Result := (AList.Count > 0) and CanProcessKeyDown(AList); if Result then case AKey of VK_DELETE: begin ADesigner.DeleteSelection; Result := False; end; VK_ESCAPE: Result := SelectItemParent(AList[0]); else Result := False; end; finally AList.Free; end; end; end; function KeyboardHookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin if (Code = HC_ACTION) and ProcessKeyboardMessage(wParam, lParam) then Result := 1 else Result := CallNextHookEx(FKeyboardHookHandle, Code, wParam, lParam); end; constructor TdxDesignCustomizationHelper.Create; begin inherited; FLayoutControls := TcxComponentList.Create(False); SetHook(FKeyboardHookHandle, WH_KEYBOARD, KeyboardHookProc); end; destructor TdxDesignCustomizationHelper.Destroy; begin ReleaseHook(FKeyboardHookHandle); FreeAndNil(FLayoutControls); inherited; end; class procedure TdxDesignCustomizationHelper.AddLayout(ALayout: TdxCustomLayoutControl); begin if dxDesignCustomizationHelper.FLayoutControls.IndexOf(ALayout) = -1 then dxDesignCustomizationHelper.FLayoutControls.Add(ALayout); end; class procedure TdxDesignCustomizationHelper.RemoveLayout(ALayout: TdxCustomLayoutControl); begin dxDesignCustomizationHelper.FLayoutControls.Extract(ALayout); end; function TdxDesignCustomizationHelper.FindActiveDesigner(out ADesigner: IdxLayoutDesignerHelper): Boolean; var I: Integer; ALayout: TdxCustomLayoutControl; begin Result := False; for I := 0 to FLayoutControls.Count - 1 do begin ALayout := FLayoutControls[I] as TdxCustomLayoutControl; Result := Supports(ALayout, IdxLayoutDesignerHelper, ADesigner) and ADesigner.IsActive and ALayout.HandleAllocated and ((ALayout.Handle = GetFocus) or ((ALayout.Parent <> nil) and ALayout.Parent.HandleAllocated and IsParentFocused(ALayout.Parent.Handle))); if Result then Break; end; 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; { TdxLayoutControlCustomCustomizeForm } destructor TdxLayoutControlCustomCustomizeForm.Destroy; begin Control.Customization := False; inherited Destroy; end; function TdxLayoutControlCustomCustomizeForm.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; begin Result := TdxLayoutCustomizeFormHitTest.Instance; TdxLayoutCustomizeFormHitTest(Result).HitItem := nil; end; procedure TdxLayoutControlCustomCustomizeForm.UpdateCaption; begin end; procedure TdxLayoutControlCustomCustomizeForm.UpdateContent; begin end; procedure TdxLayoutControlCustomCustomizeForm.UpdateSelection; begin end; procedure TdxLayoutControlCustomCustomizeForm.UpdateView; begin end; procedure TdxLayoutControlCustomCustomizeForm.CreateParams(var Params: TCreateParams); begin inherited; if Control <> nil then Params.WndParent := Control.Handle; end; procedure TdxLayoutControlCustomCustomizeForm.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if (Operation = opRemove) and (AComponent = Control) then Free; end; procedure TdxLayoutControlCustomCustomizeForm.InitializeControl; begin UpdateCaption; end; procedure TdxLayoutControlCustomCustomizeForm.SetControl(AValue: TdxCustomLayoutControl); procedure StoreMetrics; begin cxDialogsMetricsStore.StoreMetrics(Self); end; procedure RestoreMetrics; begin if Control <> nil then if EqualRect(Control.CustomizeFormBounds, cxNullRect) then BoundsRect := Control.CalculateCustomizeFormBounds(BoundsRect) else BoundsRect := Control.CustomizeFormBounds; cxDialogsMetricsStore.InitDialog(Self); Position := poDesigned; end; begin if Control <> AValue then begin if Control <> nil then begin StoreMetrics; Control.RemoveFreeNotification(Self); end; FControl := AValue; if Control <> nil then begin Control.FreeNotification(Self); RestoreMetrics; end; RecreateWnd; end; InitializeControl; end; { TdxCustomLayoutItemOptions } constructor TdxCustomLayoutItemOptions.Create(AItem: TdxCustomLayoutItem); begin inherited Create; FItem := AItem; end; procedure TdxCustomLayoutItemOptions.Changed; begin FItem.Changed; end; { TdxCustomLayoutItemImageOptions } constructor TdxCustomLayoutItemImageOptions.Create(AItem: TdxCustomLayoutItem); begin inherited Create(AItem); FGlyph := TBitmap.Create; FGlyph.OnChange := GlyphChanged; FImageIndex := -1; end; destructor TdxCustomLayoutItemImageOptions.Destroy; begin FreeAndNil(FGlyph); inherited Destroy; end; procedure TdxCustomLayoutItemImageOptions.Assign(Source: TPersistent); begin if Source is TdxCustomLayoutItemImageOptions then with Source as TdxCustomLayoutItemImageOptions do begin Self.BeginUpdate; try Self.Glyph := Glyph; Self.ImageIndex := ImageIndex; finally Self.EndUpdate; end; end else inherited Assign(Source); end; procedure TdxCustomLayoutItemImageOptions.BeginUpdate; begin Item.Container.BeginUpdate; end; procedure TdxCustomLayoutItemImageOptions.EndUpdate; begin Item.Container.CancelUpdate; Changed; end; function TdxCustomLayoutItemImageOptions.GetCurrentImage(out AImage: TBitmap; out AImageList: TCustomImageList; out AImageIndex: Integer): Boolean; var AImages: TCustomImageList; begin AImage := nil; AImageList := nil; AImageIndex := -1; Result := not Glyph.Empty; if Result then AImage := Glyph else begin AImages := GetImageList(Item.Enabled); Result := cxGraphics.IsImageAssigned(AImages, ImageIndex); if Result then begin AImageList := AImages; AImageIndex := ImageIndex; end; end; end; function TdxCustomLayoutItemImageOptions.GetImageList(AEnabled: Boolean): TCustomImageList; var ADesabledImages: TCustomImageList; begin ADesabledImages := Item.Container.OptionsImage.DisabledImages; if AEnabled or not Assigned(ADesabledImages) then Result := Item.Container.OptionsImage.Images else Result := ADesabledImages; end; function TdxCustomLayoutItemImageOptions.GetImageSize: TSize; var AGlyph: TBitmap; AImageList: TCustomImageList; AImageIndex: Integer; begin Result := cxNullSize; if GetCurrentImage(AGlyph, AImageList, AImageIndex) then if Assigned(AGlyph) then Result := cxClasses.Size(AGlyph.Width, AGlyph.Height) else if Assigned(AImageList) then Result := cxClasses.Size(AImageList.Width, AImageList.Height); end; function TdxCustomLayoutItemImageOptions.IsImageAssigned: Boolean; var AImage: TBitmap; AImageList: TCustomImageList; AImageIndex: Integer; begin Result := GetCurrentImage(AImage, AImageList, AImageIndex); end; procedure TdxCustomLayoutItemImageOptions.SetGlyph(AValue: TBitmap); begin FGlyph.Assign(AValue); end; procedure TdxCustomLayoutItemImageOptions.SetImageIndex(AValue: Integer); begin if FImageIndex <> AValue then begin FImageIndex := AValue; Changed; end; end; procedure TdxCustomLayoutItemImageOptions.GlyphChanged(Sender: TObject); begin Changed; end; { TdxCustomLayoutItemCaptionOptions } constructor TdxCustomLayoutItemCaptionOptions.Create(AItem: TdxCustomLayoutItem); begin inherited; FImageOptions := TdxCustomLayoutItemImageOptions.Create(AItem); FShowAccelChar := True; FVisibleElements := [cveImage, cveText]; FVisible := True; end; destructor TdxCustomLayoutItemCaptionOptions.Destroy; begin FreeAndNil(FImageOptions); inherited Destroy; end; function TdxCustomLayoutItemCaptionOptions.GetGlyph: TBitmap; begin Result := ImageOptions.Glyph; end; function TdxCustomLayoutItemCaptionOptions.GetImageIndex: Integer; begin Result := ImageOptions.ImageIndex; end; procedure TdxCustomLayoutItemCaptionOptions.SetAlignHorz(Value: TAlignment); begin if FAlignHorz <> Value then begin FAlignHorz := Value; Changed; end; end; procedure TdxCustomLayoutItemCaptionOptions.SetGlyph(AValue: TBitmap); begin ImageOptions.Glyph := AValue; end; procedure TdxCustomLayoutItemCaptionOptions.SetImageIndex(AValue: Integer); begin ImageOptions.ImageIndex := AValue; end; procedure TdxCustomLayoutItemCaptionOptions.SetImageOptions(Value: TdxCustomLayoutItemImageOptions); begin FImageOptions.Assign(Value); end; procedure TdxCustomLayoutItemCaptionOptions.SetShowAccelChar(Value: Boolean); begin if FShowAccelChar <> Value then begin FShowAccelChar := Value; Changed; end; end; procedure TdxCustomLayoutItemCaptionOptions.SetText(const Value: string); begin if FText <> Value then begin FText := Value; Item.ResetCachedTextHeight; Changed; Item.Container.CustomizeFormUpdate([cfutContent, cfutSelection]); end; end; procedure TdxCustomLayoutItemCaptionOptions.SetVisibleElements(Value: TdxLayoutItemCaptionVisibleElements); begin if FVisibleElements <> Value then begin FVisibleElements := Value; Changed; end; end; procedure TdxCustomLayoutItemCaptionOptions.SetVisible(Value: Boolean); begin if FVisible <> Value then begin FVisible := Value; Changed; end; 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; { TdxCustomLayoutItem } constructor TdxCustomLayoutItem.Create(AOwner: TComponent); begin inherited; FAllowRemove := True; FAlignHorz := ahParentManaged; FAlignVert := avParentManaged; FCaptionOptions := GetCaptionOptionsClass.Create(Self); FEnabled := True; FOffsets := TdxLayoutOffsets.Create(Self); 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; cxClearObjectLinks(Self); 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.GetCaption: string; begin Result := CaptionOptions.Text; 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 (Caption = '') then Result := Name else Result := StripHotKey(Caption); end; function TdxCustomLayoutItem.GetEnabled: Boolean; begin if not (liavEnabled in FAssignedValues) and (Parent <> nil) then Result := Parent.Enabled else Result := FEnabled; 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 CaptionOptions.Text := Value; 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 Enabled <> Value then begin FEnabled := Value; if FEnabled then Exclude(FAssignedValues, liavEnabled) else Include(FAssignedValues, liavEnabled); 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 CaptionOptions.Visible := Value; 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, cfutSelection]); 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.CustomizationChanged; begin // do nothing end; procedure TdxCustomLayoutItem.LayoutLookAndFeelChanged; begin // do nothing 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.CanDragAndDrop: Boolean; begin Result := not IsRoot; 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(ictMedium); 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 if ViewInfo <> nil then Result := ViewInfo.GetCursor(X, Y) else Result := crDefault; 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 := CaptionOptions.Visible; 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; function TdxCustomLayoutItem.CanInit: Boolean; begin Result := not (IsLoading or Container.IsLayoutLoading); end; procedure TdxCustomLayoutItem.DoInit; begin if GetLayoutLookAndFeel <> nil then LayoutLookAndFeelChanged; end; procedure TdxCustomLayoutItem.Init; begin if CanInit then DoInit; 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 begin if not IsDesigning and Container.Customization then Container.SetFocus; TdxCustomLayoutItemHitTest(AHitTest).GetSourceItem.SelectComponent(Shift); end; 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; end; function TdxCustomLayoutItem.IsChild(AOwner: TComponent): 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; 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; procedure MakeActuallyVisible(AItem: TdxCustomLayoutItem); begin if AItem.Parent <> nil then begin AItem.Parent.ItemIndex := AItem.Index; MakeActuallyVisible(AItem.Parent); end; end; function CanBeActuallyVisible(AItem: TdxCustomLayoutItem): Boolean; begin Result := AItem.Visible and (AItem.IsRoot or (AItem.Parent <> nil) and CanBeActuallyVisible(AItem.Parent)); end; begin if not CanBeActuallyVisible(Self) then Exit; if not ActuallyVisible then MakeActuallyVisible(Self); 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) and (APack or (AParent <> Parent) or (Index <> AIndex)); if not Result then Exit; ASourceContainer := Container; ADestinationContainer := AParent.Container; ADestinationContainer.BeginUpdate; ASourceContainer.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; { 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); if FItem.IsDesigning then FItem.ShowCaption := ShowItemCaption; FItem.ControlOptions.ShowBorder := ShowBorder; if ShowBorder then begin AHeight := Control.ClientHeight; HideControlBorder; Control.Height := AHeight; end; end; procedure TdxCustomLayoutControlAdapter.InternalLayoutLookAndFeelChanged; begin if Item.ControlOptions.AutoColor and (Item.ViewInfo <> nil) then TControlAccess(Control).Color := Item.ViewInfo.Color; 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; var ALookAndFeelContainer: IcxLookAndFeelContainer; begin InternalLayoutLookAndFeelChanged; if Supports(Control, IcxLookAndFeelContainer, ALookAndFeelContainer) then LayoutLookAndFeel.InitializeSubControlCxLookAndFeel(ALookAndFeelContainer.GetLookAndFeel); 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; { 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; { TdxLayoutItem } constructor TdxLayoutItem.Create(AOwner: TComponent); begin inherited; FControlOptions := GetControlOptionsClass.Create(Self); end; destructor TdxLayoutItem.Destroy; begin Control := nil; FControlOptions.Free; FreeAndNil(FCustomizeControlHelper); 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(FCustomizeControlHelper); 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; begin Control.Enabled := Enabled; FDefaultControlWndProc := Control.WindowProc; Control.WindowProc := ControlWndProc; 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; FCustomizeControlHelper := TdxCustomizationControlHelper.Create(Control); (FCustomizeControlHelper as TdxCustomizationControlHelper).LayoutItem := Self; 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; 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.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.CustomizationChanged; begin if HasControl then (FCustomizeControlHelper as TdxCustomizationControlHelper).CustomizationChanged; 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; 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.DoInit; 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) and not Parent.Hidden; 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.FLayout := ACommonValue; if IsCommonValue(1, ACommonValue) then CaptionOptions.FAlignHorz := ACommonValue; if IsCommonValue(2, ACommonValue) then CaptionOptions.FAlignVert := 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 R: TRect; begin if HasControl and (FCustomizeControlHelper <> nil) then begin R := ViewInfo.DesignSelectorRect; R := cxRectOffset(R, ViewInfo.ControlViewInfo.Bounds.TopLeft, False); FCustomizeControlHelper.SelectorBounds := R; 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; function NeedSaveOriginalControlSize: Boolean; begin Result := IsControlResized and FControlAdapter.AllowCheckSize and ControlSizeChanged; end; begin 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 and FControlAdapter.AllowCheckSize)) then begin if NeedSaveOriginalControlSize then SaveOriginalControlSize; Changed; end; CM_TABSTOPCHANGED: Container.ViewInfo.DoCalculateTabOrders; CM_ENABLEDCHANGED: Enabled := Control.Enabled; 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 := Enabled; end; procedure TdxLayoutItem.SetControlFocus; begin TWinControl(FControl).SetFocus; end; procedure TdxLayoutItem.SetControlVisibility; procedure InternalSetControlVisibility(AValue: Boolean); begin if Control.Visible <> AValue then begin Control.Visible := AValue; // to make the control invisible on showing if not AValue then Control.SetBounds(10000, 10000, FOriginalControlSize.X, FOriginalControlSize.Y) else Control.BoundsRect := ViewInfo.FControlViewInfo.ControlBounds; end; end; begin if HasControl then InternalSetControlVisibility(ActuallyVisible and ViewInfo.ActuallyVisible); 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; 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 not Locked and IsUserDefined; 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.CustomizationChanged; var I: Integer; begin for I := 0 to FItems.Count - 1 do Items[I].CustomizationChanged; end; procedure TdxLayoutGroup.DoPack; var I: Integer; begin for I := Count - 1 downto 0 do Items[I].Pack; if IsSuperfluous then begin if (Parent <> nil) and (Parent.Count = 1) and (Count > 0) then Parent.LayoutDirection := LayoutDirection; MoveChildrenToParent; Free; end; 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; 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.IsSuperfluous: Boolean; begin Result := not IsRoot and not Locked and Hidden and ((Count = 0) or (Count = 1) or (Parent <> nil) and (Parent.Count = 1)); 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; { TdxLayoutGroupHelper } class function TdxLayoutGroupHelper.GetChildItemsAlignHorz: TdxLayoutAlignHorz; begin Result := ahClient; end; class function TdxLayoutGroupHelper.GetChildItemsAlignVert: TdxLayoutAlignVert; begin Result := avClient; end; class function TdxLayoutGroupHelper.GetOrthogonalDirection: TdxLayoutDirection; begin Result := ldVertical; end; class function TdxLayoutGroupHelper.GetSpecificClass: TdxLayoutGroupViewInfoSpecificClass; begin Result := TdxLayoutGroupViewInfoSpecific; 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; { 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; { 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; { TdxLayoutImageOptions } constructor TdxLayoutImageOptions.Create(AControl: TdxCustomLayoutControl); begin inherited Create(AControl); FNotifyComponent := TcxFreeNotificator.Create(nil); FNotifyComponent.OnFreeNotification := FreeNotification; FDisabledImagesChangeLink := TChangeLink.Create; FDisabledImagesChangeLink.OnChange := DisabledImagesChange; FImagesChangeLink := TChangeLink.Create; FImagesChangeLink.OnChange := ImagesChange; end; destructor TdxLayoutImageOptions.Destroy; begin FreeAndNil(FImagesChangeLink); FreeAndNIl(FDisabledImagesChangeLink); FreeAndNil(FNotifyComponent); inherited Destroy; end; procedure TdxLayoutImageOptions.Assign(Source: TPersistent); begin if Source is TdxLayoutImageOptions then with Source as TdxLayoutImageOptions do begin Self.BeginUpdate; try Self.DisabledImages := DisabledImages; Self.Images := Images; finally Self.EndUpdate; end; end else inherited Assign(Source); end; procedure TdxLayoutImageOptions.Changed; begin Control.LayoutChanged(False); end; procedure TdxLayoutImageOptions.BeginUpdate; begin Control.BeginUpdate;; end; procedure TdxLayoutImageOptions.EndUpdate; begin Control.CancelUpdate; Changed; end; procedure TdxLayoutImageOptions.SetImages(AValue: TCustomImageList); begin SetImageList(AValue, FImages, FImagesChangeLink); end; procedure TdxLayoutImageOptions.SetDisabledImages(AValue: TCustomImageList); begin SetImageList(AValue, FDisabledImages, FDisabledImagesChangeLink); end; procedure TdxLayoutImageOptions.DisabledImagesChange(Sender: TObject); begin Changed; end; procedure TdxLayoutImageOptions.ImagesChange(Sender: TObject); begin Changed; end; procedure TdxLayoutImageOptions.SetImageList(var ANewValue, AOldValue: TCustomImageList; const AChangeLink: TChangeLink); begin cxSetImageList(ANewValue, AOldValue, AChangeLink, FNotifyComponent); end; procedure TdxLayoutImageOptions.FreeNotification(AComponent: TComponent); begin if AComponent = DisabledImages then DisabledImages := nil; if AComponent = Images then Images := nil; end; { TdxUndoRedoManager } constructor TdxUndoRedoManager.Create(AControl: TdxCustomLayoutControl); begin inherited Create(AControl); FUndoList := TcxObjectList.Create; end; destructor TdxUndoRedoManager.Destroy; begin FreeAndNil(FUndoList); FreeAndNil(FCurrentLayout); inherited; end; function TdxUndoRedoManager.CanRedo: Boolean; begin Result := RedoCount > 0; end; function TdxUndoRedoManager.CanUndo: Boolean; begin Result := UndoCount > 0; end; procedure TdxUndoRedoManager.Redo; var AIni: TMemIniFile; begin if CanRedo then begin Inc(FLockCount); try Inc(FIndex); if FIndex = FUndoList.Count then AIni := FCurrentLayout else AIni := TMemIniFile(FUndoList[FIndex]); Control.InternalLoadFromCustomIniFile(AIni, True); finally Dec(FLockCount); end; end; end; procedure TdxUndoRedoManager.Undo; var AIni: TMemIniFile; begin if CanUndo then begin if FCurrentLayout = nil then begin FCurrentLayout := TMemIniFile.Create(''); Control.InternalSaveToCustomIniFile(FCurrentLayout); end; Inc(FLockCount); try Dec(FIndex); AIni := TMemIniFile(FUndoList[FIndex]); Control.InternalLoadFromCustomIniFile(AIni, True); finally Dec(FLockCount); end; end; end; procedure TdxUndoRedoManager.SaveLayout; var AIni: TMemIniFile; begin if IsLocked then Exit; AIni := TMemIniFile.Create(''); Control.InternalSaveToCustomIniFile(AIni); AddUndo(AIni); end; function TdxUndoRedoManager.IsLocked: Boolean; begin Result := FLockCount > 0; end; procedure TdxUndoRedoManager.Clear; begin FUndoList.Clear; FreeAndNil(FCurrentLayout); end; procedure TdxUndoRedoManager.AddUndo(ALayout: TMemIniFile); begin while FIndex < FUndoList.Count do FUndoList.Delete(FIndex); FreeAndNil(FCurrentLayout); FUndoList.Add(ALayout); FIndex := FUndoList.Count; end; function TdxUndoRedoManager.GetRedoCount: Integer; begin Result := FUndoList.Count - UndoCount; end; function TdxUndoRedoManager.GetUndoCount: Integer; begin Result := FIndex; end; { TdxStoringOptions } 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; { 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; FOptionsImage := TdxLayoutImageOptions.Create(Self); FAbsoluteItems := TcxComponentList.Create; FAvailableItems := TcxComponentList.Create; FAvailableItems.OnComponentListChanged := AvailableItemListChanged; FOptionsStoring := TdxStoringOptions.Create; FStoredStream := TMemoryStream.Create; FUndoRedoManager := TdxUndoRedoManager.Create(Self); FAutoControlAlignment := True; FAutoControlTabOrders := True; FHighlightRoot := True; FShowDesignSelectors := True; FBoldFont := TFont.Create; RefreshBoldFont; FCustomizeFormClass := TdxLayoutControlCustomizeForm; GetLayoutLookAndFeel.AddUser(Self); InitializeSubControlsCxLookAndFeel; CreateRootGroup; //FGroups.UseIndent := False; CreateConstraints; dxDesignCustomizationHelper.AddLayout(Self); FSelectionHelper := GetSelectionHelperClass.Create(Self); FSelectionHelper.AddSelectionChangedListener(Self); FCustomizeAvailableItemsViewKind := oivkTree; end; destructor TdxCustomLayoutControl.Destroy; begin FSelectionHelper.RemoveSelectionChangedListener(Self); dxDesignCustomizationHelper.RemoveLayout(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(FUndoRedoManager); FreeAndNil(FStoredStream); FreeAndNil(FOptionsStoring); FAvailableItems.OwnsObjects := True; FreeAndNil(FAvailableItems); FreeAndNil(FAbsoluteItems); FreeAndNil(FOptionsImage); 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.GetIsLayoutLoading: Boolean; begin Result := FLoadingCount > 0; end; function TdxCustomLayoutControl.GetOccupiedClientWidth: Integer; begin Result := ViewInfo.ItemsViewInfo.CalculateWidth; end; function TdxCustomLayoutControl.GetOccupiedClientHeight: Integer; begin Result := ViewInfo.ItemsViewInfo.CalculateHeight; 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); var AParentForm: TCustomForm; begin if (FCustomization <> Value) and (not Value or HandleAllocated) then begin if Value then begin if not IsDestroying and not IsDesigning and IsChildWindow(Self, GetFocus) then begin AParentForm := GetParentForm(Self); if (AParentForm <> nil) and Visible then AParentForm.ActiveControl := Self; end; FCustomizeForm := CustomizeFormClass.Create(nil); FCustomizeForm.Control := Self; FCustomization := True; CustomizeFormUpdate([cfutContent, cfutSelection, cfutView]); FCustomizeForm.Show; 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; end; 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, cfutView]); end; end; procedure TdxCustomLayoutControl.SetCustomizeFormTabbedView(Value: Boolean); begin if FCustomizeFormTabbedView <> Value then begin FCustomizeFormTabbedView := Value; CustomizeFormUpdate([cfutView]); end; end; procedure TdxCustomLayoutControl.SetShowDesignSelectors(Value: Boolean); begin if FShowDesignSelectors <> Value then begin FShowDesignSelectors := Value; InvalidateWithChildren; CustomizeFormUpdate([cfutView]); end; end; procedure TdxCustomLayoutControl.SetHighlightRoot(Value: Boolean); begin if FHighlightRoot <> Value then begin FHighlightRoot := Value; LayoutChanged(False); CustomizeFormUpdate([cfutView]); end; end; procedure TdxCustomLayoutControl.SetIsPlaceControlsNeeded(Value: Boolean); begin if FIsPlaceControlsNeeded <> Value then begin FIsPlaceControlsNeeded := Value; if Value then PlaceControls(nil); end; end; procedure TdxCustomLayoutControl.SetOptionsImage(Value: TdxLayoutImageOptions); begin FOptionsImage.Assign(Value); 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; procedure TdxCustomLayoutControl.DXMInvalidateSelectionLayer(var Message: TMessage); var R: TRect; begin with Message do R := Rect(WParamLo, WParamHi, LParamLo, LParamHi); InvalidateSelectionLayer(R); 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(False); 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 Result := crDefault; if DragAndDropState = ddsNone then begin AHitTest := ViewInfo.GetHitTest(X, Y); if AHitTest.HitItem <> nil then Result := AHitTest.HitItem.GetCursor(X, Y); if Result = crDefault then Result := inherited GetCursor(X, Y); end; 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; function TdxCustomLayoutControl.NeedRedrawOnResize: Boolean; begin Result := ViewInfo.LayoutLookAndFeel.NeedRedrawOnResize; end; procedure TdxCustomLayoutControl.Loaded; begin inherited; if not IsDesigning then Restore; LayoutChanged(False); 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, cfutSelection]); 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); function PtInDesignSelectorRect(const P: TPoint): Boolean; var AControl: TControl; AHitTest: TdxCustomLayoutHitTest; begin Result := False; AControl := ControlAtPos(P, True); if (AControl <> nil) and not (AControl is TWinControl) then begin AHitTest := ViewInfo.GetHitTest(P); Result := (AHitTest <> nil) and (AHitTest is TdxLayoutItemHitTest) and (AHitTest as TdxLayoutItemHitTest).HitItem.ViewInfo.PtInDesignSelectorRect(P); end; end; begin if (IsDesigning or Customization) and HandleAllocated then case Message.Msg of WM_LBUTTONDOWN: if (GetCapture <> Handle) and (Customization or PtInDesignSelectorRect(SmallPointToPoint(TWMMouse(Message).Pos))) then SetCaptureControl(Self); 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); AItem := AHitTest.GetSourceItem; if (AItem <> nil) and AItem.CanDragAndDrop then begin (DragAndDropObject as TdxLayoutControlDragAndDropObject).Init(dsControl, AItem); Result := True; 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; InvalidateControl(Self, True, True); CustomizeFormUpdate([cfutView]); end; procedure TdxCustomLayoutControl.LayoutLookAndFeelUserDestroyed; begin LayoutLookAndFeel := nil; end; procedure TdxCustomLayoutControl.SelectionChanged; begin Items.SelectionChanged; end; function TdxCustomLayoutControl.CanProcessChildren: Boolean; begin Result := True; 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; 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; function TdxCustomLayoutControl.GetSelectionHelperClass: TdxLayoutRunTimeSelectionHelperClass; begin if IsDesigning then Result := dxLayoutDesignTimeSelectionHelperClass else Result := dxLayoutRunTimeSelectionHelperClass; end; procedure TdxCustomLayoutControl.InvalidateSelectionLayer(const R: TRect); begin if (ViewInfo <> nil) and (ViewInfo.SelectionLayer <> nil) then ViewInfo.SelectionLayer.InvalidateRect(R); end; procedure TdxCustomLayoutControl.PostBuildSelectionLayer; begin if HandleAllocated then PostMessage(Handle, DXM_BUILDSELECTIONLAYER, 0, 0); end; procedure TdxCustomLayoutControl.PostInvalidateSelectionLayer(const R: TRect); begin if HandleAllocated then with R do PostMessage(Handle, DXM_INVALIDATESELECTIONLAYER, MakeWParam(Left, Top), MakeLParam(Right, Bottom)); 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, cfutView]); 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 CustomizeForm.UpdateCaption; if cfutContent in AUpdateTypes then CustomizeForm.UpdateContent; if cfutSelection in AUpdateTypes then CustomizeForm.UpdateSelection; if cfutView in AUpdateTypes then CustomizeForm.UpdateView; end; procedure TdxCustomLayoutControl.DoCustomization; begin CallNotify(FOnCustomization, Self); if not IsDestroying then Items.CustomizationChanged; 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; if ANeedPack then 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; function TdxCustomLayoutControl.GetRootSectionName(AIniFile: TCustomIniFile): string; begin if AIniFile.SectionExists(Name) then Result := Name else Result := ''; end; procedure TdxCustomLayoutControl.InternalLoadFromCustomIniFile(AIniFile: TCustomIniFile; ADestroyNonLoadedItems: Boolean); var AItems: TList; APositions: TList; AItemCount, I: Integer; ARootSection: string; 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 AItem: TdxCustomLayoutItem; procedure LoadCaption; var AItemCaptionOptions: TdxLayoutItemCaptionOptions; begin AItem.Caption := AIniFile.ReadString(ASection, 'Caption', ''); AItem.CaptionOptions.AlignHorz := TAlignment(AIniFile.ReadInteger(ASection, 'CaptionAlignHorz', 0)); if AItem.CaptionOptions is TdxLayoutItemCaptionOptions then begin AItemCaptionOptions := AItem.CaptionOptions as TdxLayoutItemCaptionOptions; AItemCaptionOptions.AlignVert := TdxAlignmentVert(AIniFile.ReadInteger(ASection, 'CaptionAlignVert', 1)); AItemCaptionOptions.Layout := TdxCaptionLayout(AIniFile.ReadInteger(ASection, 'CaptionLayout', 0)); end; end; var AName, AParentName: string; 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)); end; LoadCaption; AItems.Extract(AItem); end; procedure DestroyNonLoadedItems; var I: Integer; begin for I := 0 to AItems.Count - 1 do if ADestroyNonLoadedItems and TdxCustomLayoutItem(AItems[I]).CanDelete 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 ARootSection := GetRootSectionName(AIniFile); AItemCount := AIniFile.ReadInteger(ARootSection, 'ItemCount', -1); if AItemCount = -1 then Exit; BeginUpdate; Inc(FLoadingCount); try PrepareItems; for I := 0 to AItemCount - 1 do LoadItem(GetItemSection(I)); DestroyNonLoadedItems; UpdatePositions; finally Dec(FLoadingCount); EndUpdate; end; finally for I := 0 to APositions.Count - 1 do Dispose(PdxLayoutItemPosition(APositions[I])); APositions.Free; AItems.Free; end; end; function CompareItems(Item1, Item2: Pointer): Integer; function GetLevel(AItem: TdxCustomLayoutItem): Integer; begin if AItem.Parent <> nil then Result := GetLevel(AItem.Parent) + 1 else Result := 0; end; var AItem1, AItem2: TdxCustomLayoutItem; begin AItem1 := TdxCustomLayoutItem(Item1); AItem2 := TdxCustomLayoutItem(Item2); Result := GetLevel(AItem1) - GetLevel(AItem2); if Result = 0 then if (AItem1.Parent = AItem2.Parent) and (AItem1.Parent <> nil) then Result := AItem1.Index - AItem2.Index else Result := Integer(AItem1.Parent = nil) - Integer(AItem2.Parent = nil); if (Result = 0) and (AItem1.Parent <> nil) then Result := CompareItems(AItem1.Parent, AItem2.Parent); if Result = 0 then 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.InternalSaveToCustomIniFile(AIniFile: TCustomIniFile); var AItems: TList; I: Integer; ARootSection: string; function CreateItemsList: TList; begin Result := TList.Create; Result.Count := AbsoluteItemCount; Move(FAbsoluteItems.List^, Result.List^, Result.Count * SizeOf(Pointer)); Result.Sort(CompareItems); 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; procedure SaveCaption; var AItemCaptionOptions: TdxLayoutItemCaptionOptions; begin AIniFile.WriteString(ASection, 'Caption', AItem.Caption); AIniFile.WriteInteger(ASection, 'CaptionAlignHorz', Integer(AItem.CaptionOptions.AlignHorz)); if AItem.CaptionOptions is TdxLayoutItemCaptionOptions then begin AItemCaptionOptions := AItem.CaptionOptions as TdxLayoutItemCaptionOptions; AIniFile.WriteInteger(ASection, 'CaptionAlignVert', Integer(AItemCaptionOptions.AlignVert)); AIniFile.WriteInteger(ASection, 'CaptionLayout', Integer(AItemCaptionOptions.Layout)); end; 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)); end; SaveCaption; end; begin ARootSection := Name; 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; procedure TdxCustomLayoutControl.LoadFromCustomIniFile(AIniFile: TCustomIniFile); begin InternalLoadFromCustomIniFile(AIniFile, False); end; procedure TdxCustomLayoutControl.SaveToCustomIniFile(AIniFile: TCustomIniFile); begin InternalSaveToCustomIniFile(AIniFile); end; procedure TdxCustomLayoutControl.AddSelectionChangedListener(AListener: TPersistent); begin if (FSelectionHelper <> nil) then FSelectionHelper.AddSelectionChangedListener(AListener); end; function TdxCustomLayoutControl.IsActive: Boolean; begin Result := (FSelectionHelper <> nil) and FSelectionHelper.IsActive; 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.DeleteSelection; begin if (FSelectionHelper <> nil) then FSelectionHelper.DeleteSelection; 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.RemoveSelectionChangedListener(AListener: TPersistent); begin if FSelectionHelper <> nil then FSelectionHelper.RemoveSelectionChangedListener(AListener); 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: TdxSelectionAction); begin if not IsDestroying and (AAction in [saAdded, saChanged]) and not IsUpdateLocked then begin ViewInfo.BuildSelectionLayer; if IsDesigning then InvalidateRect(GetDesignSelectorRect, True); CustomizeFormUpdate([cfutSelection]); end; end; procedure TdxCustomLayoutControl.SaveToUndo; begin if ([csLoading, csReading, csDestroying] * ComponentState = []) and not IsUpdateLocked then UndoRedoManager.SaveLayout; 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); 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); 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; { 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.IsDeterminedAreaPart: Boolean; begin Result := False; end; function TdxCustomLayoutHitTest.GetAreaPart: TdxLayoutAreaPart; begin Result := apNone; end; function TdxCustomLayoutHitTest.GetGroupForInsert: TdxLayoutGroup; begin Result := nil; end; function TdxCustomLayoutHitTest.GetDesinationItem: TdxCustomLayoutItem; begin Result := HitItem; end; function TdxCustomLayoutHitTest.GetSourceItem: TdxCustomLayoutItem; begin Result := HitItem; end; { TdxLayoutNoneHitTest } class function TdxLayoutNoneHitTest.HitTestCode: Integer; begin Result := htNone; end; { TdxLayoutItemHitTest } function TdxLayoutItemHitTest.GetHitItem: TdxLayoutItem; begin Result := TdxLayoutItem(inherited HitItem); end; procedure TdxLayoutItemHitTest.SetHitItem(Value: TdxLayoutItem); begin inherited HitItem := Value; end; class function TdxLayoutItemHitTest.HitTestCode: Integer; begin Result := htItem; end; function TdxLayoutItemHitTest.GetGroupForInsert: TdxLayoutGroup; begin Result := HitItem.Parent; end; { TdxLayoutGroupHitTest } function TdxLayoutGroupHitTest.GetHitItem: TdxLayoutGroup; begin Result := TdxLayoutGroup(inherited HitItem); end; procedure TdxLayoutGroupHitTest.SetHitItem(Value: TdxLayoutGroup); begin inherited HitItem := Value; end; class function TdxLayoutGroupHitTest.HitTestCode: Integer; begin Result := htGroup; end; function TdxLayoutGroupHitTest.GetGroupForInsert: TdxLayoutGroup; begin Result := HitItem; end; { TdxLayoutTabbedGroupHitTest } function TdxLayoutTabbedGroupHitTest.GetDesinationItem: TdxCustomLayoutItem; var ATabIndex: Integer; AClientPoint: TPoint; begin if Specific.HasTabControl then begin AClientPoint := cxPointOffset(FHitPoint, Point(Specific.FTabControl.Left, Specific.FTabControl.Top), False); ATabIndex := Specific.FTabControl.IndexOfTabAt(AClientPoint.X, AClientPoint.Y); if ATabIndex <> -1 then Result := HitItem.ViewInfo.ItemViewInfos[ATabIndex].Item else Result := inherited GetDesinationItem; end else Result := inherited GetDesinationItem; end; function TdxLayoutTabbedGroupHitTest.GetSourceItem: TdxCustomLayoutItem; var ATabIndex: Integer; AClientPoint: TPoint; begin if Specific.HasTabControl then begin AClientPoint := cxPointOffset(FHitPoint, Point(Specific.FTabControl.Left, Specific.FTabControl.Top), False); ATabIndex := Specific.FTabControl.IndexOfTabAt(AClientPoint.X, AClientPoint.Y); if ATabIndex <> -1 then Result := HitItem.ViewInfo.ItemViewInfos[ATabIndex].Item else Result := inherited GetSourceItem; end else Result := inherited GetSourceItem; end; function TdxLayoutTabbedGroupHitTest.GetSpecific: TdxLayoutGroupViewInfoTabbedSpecific; begin Result := HitItem.ViewInfo.Specific as TdxLayoutGroupViewInfoTabbedSpecific; end; { TdxLayoutCustomizeFormHitTest } class function TdxLayoutCustomizeFormHitTest.HitTestCode: Integer; begin Result := htCustomizeForm; end; function TdxLayoutCustomizeFormHitTest.IsDeterminedAreaPart: Boolean; begin Result := True; end; function TdxLayoutCustomizeFormHitTest.GetAreaPart: TdxLayoutAreaPart; begin if HitItem is TdxLayoutGroup then Result := apLastChild else if (HitItem is TdxLayoutItem) and (HitItem.Parent <> nil) then Result := apAfter else Result := apNone; end; function TdxLayoutCustomizeFormHitTest.GetDesinationItem: TdxCustomLayoutItem; begin //#DG feature is not ready yet Result := HitItem; Result := nil; 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; function TdxLayoutClientAreaHitTest.GetGroupForInsert: TdxLayoutGroup; begin Result := Control.Items; end; function TdxLayoutClientAreaHitTest.GetDesinationItem: TdxCustomLayoutItem; begin Result := Control.Items; end; { TdxCustomLayoutControlHandler } constructor TdxCustomLayoutControlHandler.Create(AControl: TdxCustomLayoutControl); begin inherited Create; FControl := AControl; end; function TdxCustomLayoutControlHandler.GetViewInfo: TdxLayoutControlViewInfo; begin Result := FControl.ViewInfo; 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.DoPaint; begin DrawBackground; DrawText; DrawGlyph; end; procedure TdxCustomLayoutItemCaptionPainter.DrawBackground; begin end; procedure TdxCustomLayoutItemCaptionPainter.DrawGlyph; begin if ViewInfo.IsImageVisible then DoDrawGlyph; end; procedure TdxCustomLayoutItemCaptionPainter.DrawText; begin if ViewInfo.IsTextVisible then begin BeforeDrawText; DoDrawText; AfterDrawText; end; end; procedure TdxCustomLayoutItemCaptionPainter.DoDrawText; begin with ViewInfo do Self.Canvas.DrawText(Text, TextAreaBounds, CalculateTextFlags, Enabled); end; procedure TdxCustomLayoutItemCaptionPainter.DoDrawGlyph; const DrawModes: array [Boolean] of TcxImageDrawMode = (idmDisabled, idmNormal); var AGlyph: TBitmap; R: TRect; AImageList: TCustomImageList; AImageIndex: Integer; function TransformToDisabledImage: Boolean; begin Result := ViewInfo.Enabled or (not IsGlyphAssigned(AGlyph) and (AImageList = ViewInfo.Item.Container.OptionsImage.DisabledImages)); end; begin if ViewInfo.Item.CaptionOptions.ImageOptions.GetCurrentImage(AGlyph, AImageList, AImageIndex) then begin R := ViewInfo.ImageBounds; cxDrawImage(Canvas.Handle, R, R, AGlyph, AImageList, AImageIndex, DrawModes[TransformToDisabledImage]); end; end; procedure TdxCustomLayoutItemCaptionPainter.Paint; begin if RectVisible(Canvas.Handle, ViewInfo.Bounds) then DoPaint; 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 not ViewInfo.ActuallyVisible); end; function TdxLayoutItemPainter.CanPaintSpecificPart: Boolean; begin Result := CanPaint and ViewInfo.ActuallyVisible 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 TdxLayoutItemViewInfo(AItemViewInfo).ActuallyVisible and (AControlViewInfo.Control <> nil) then if AControlViewInfo.Control is TWinControl then AWinControlViewInfos.Add(AControlViewInfo) else AControlViewInfos.Add(AControlViewInfo); end; end; procedure ProcessControls; var I: Integer; AViewInfo: TdxLayoutItemControlViewInfo; begin for I := 0 to AControlViewInfos.Count - 1 do begin AViewInfo := TdxLayoutItemControlViewInfo(AControlViewInfos[I]); AViewInfo.Control.BoundsRect := AViewInfo.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; { TdxCustomLayoutElementViewInfo } procedure TdxCustomLayoutElementViewInfo.Calculate(const ABounds: TRect); begin FBounds := ABounds; FOriginalBounds := 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.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.GetIsImageVisible: Boolean; begin Result := (cveImage in Item.CaptionOptions.VisibleElements) and Item.CaptionOptions.ImageOptions.IsImageAssigned; end; function TdxCustomLayoutItemCaptionViewInfo.GetIsTextVisible: Boolean; begin Result := (cveText in Item.CaptionOptions.VisibleElements) and (Text <> ''); 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 not ItemViewInfo.ActuallyVisible); 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 Enabled 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 := Enabled 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.GetSpaceBetweenImageText: Integer; begin Result := dxLayoutGlyphSpace; end; function TdxCustomLayoutItemCaptionViewInfo.GetText: string; begin Result := Item.Caption; end; function TdxCustomLayoutItemCaptionViewInfo.GetTextAreaBounds: TRect; var AImageAreaWidth: Integer; begin if IsTextVisible then begin Result := Bounds; if IsImageVisible then begin AImageAreaWidth := cxRectWidth(ImageAreaBounds); if IsNeedSpaceBetweenImageText then Inc(AImageAreaWidth, GetSpaceBetweenImageText); if Item.CaptionOptions.AlignHorz = taRightJustify then Result.Right := Result.Right - AImageAreaWidth else Result.Left := Result.Left + AImageAreaWidth; end; if Enabled and (Text <> '') then with Result do begin Dec(Right); Dec(Bottom); end; end else Result := cxNullRect; 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.GetTextHeight: Integer; var R: TRect; begin if IsTextVisible then begin if Item.CachedTextHeight = 0 then begin PrepareCanvas; if MultiLine then begin R := Rect(0, 0, TextWidth - 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; Inc(Result); // for disabling end else Result := 0; end; function TdxCustomLayoutItemCaptionViewInfo.GetTextWidth: Integer; var AText: string; begin if IsTextVisible then begin AText := VisibleText; PrepareCanvas; Result := Canvas.TextWidth(AText); Inc(Result); // for disabling end else Result := 0; end; function TdxCustomLayoutItemCaptionViewInfo.GetVisibleText: string; begin Result := Text; if Item.CaptionOptions.ShowAccelChar then Result := StripHotKey(Result); end; function TdxCustomLayoutItemCaptionViewInfo.IsNeedSpaceBetweenImageText: Boolean; begin Result := IsTextVisible and IsImageVisible; end; function TdxCustomLayoutItemCaptionViewInfo.IsPointInHotTrackBounds(const P: TPoint): Boolean; var ABounds: TRectArray; I: Integer; begin Result := IsImageVisible and PtInRect(ImageBounds, P); if not Result and IsTextVisible then begin 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; end; procedure TdxCustomLayoutItemCaptionViewInfo.PrepareCanvas; begin Canvas.Font := Font; end; function TdxCustomLayoutItemCaptionViewInfo.GetImageAreaBounds: TRect; begin Result := Bounds; if Item.CaptionOptions.AlignHorz = taRightJustify then Result.Left := Result.Right - ImageWidth else Result.Right := Result.Left + ImageWidth; end; function TdxCustomLayoutItemCaptionViewInfo.GetImageBounds: TRect; begin if IsImageVisible then Result := cxRectCenter(ImageAreaBounds, ImageWidth, ImageHeight) else Result := cxNullRect; end; function TdxCustomLayoutItemCaptionViewInfo.GetImageHeight: Integer; begin Result := Item.CaptionOptions.ImageOptions.GetImageSize.cy; end; function TdxCustomLayoutItemCaptionViewInfo.GetImageWidth: Integer; begin Result := Item.CaptionOptions.ImageOptions.GetImageSize.cx; end; function TdxCustomLayoutItemCaptionViewInfo.CalculateHeight: Integer; begin if Visible then Result := Max(TextHeight, ImageHeight) else Result := 0; end; function TdxCustomLayoutItemCaptionViewInfo.CalculateWidth: Integer; begin if Visible then begin Result := TextWidth + ImageWidth; if IsNeedSpaceBetweenImageText then Inc(Result, GetSpaceBetweenImageText); end 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, dxLayoutSelectionMarkerWidth); 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; const SelectionGab = dxLayoutSelectionOffset / 2; function CanUseSelectionOffset: Boolean; var ARootViewInfo: TdxLayoutGroupViewInfo; begin ARootViewInfo := ContainerViewInfo.ItemsViewInfo; Result := ((ParentViewInfo = nil) and (not Item.IsRoot or ((ARootViewInfo.ItemsAreaOffsetHorz > SelectionGab) and (ARootViewInfo.ItemsAreaOffsetVert > SelectionGab)))) or ((ParentViewInfo <> nil) and (ParentViewInfo.UseItemOffset and (ParentViewInfo.ItemOffset > SelectionGab))); 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, dxLayoutSelectionMarkerWidth div 2, dxLayoutSelectionMarkerWidth 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(const P: TPoint): TdxCustomLayoutItemHitTest; begin Result := GetHitTestClass.Instance as TdxCustomLayoutItemHitTest; Result.HitItem := Item; Result.HitPoint := P; 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]; if ParentViewInfo <> nil then ParentViewInfo.CorrectAreaPart(Result); 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.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(P) 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.GetSpaceBetweenImageText: Integer; begin Result := ItemViewInfo.ControlOffsetHorz; 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.GetTextWidth: Integer; begin if Visible and IsFixedWidth then Result := Item.CaptionOptions.Width else Result := inherited GetTextWidth; 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 and (not ItemViewInfo.IsDragImagePainted or ItemViewInfo.ActuallyVisible); 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 SelectorRectOffset = 3; SelectorRectWidth = 10; var AControlBounds: TRect; begin AControlBounds := ControlViewInfo.ControlBounds; Result := AControlBounds; Result.Left := Result.Right - SelectorRectWidth; Result.Top := Result.Bottom - SelectorRectWidth; OffsetRect(Result, -SelectorRectOffset, -SelectorRectOffset); 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 CaptionViewInfo.IsTextVisible 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; procedure TdxLayoutGroupViewInfoSpecific.CorrectAreaPart(var AAreaPart: TdxLayoutAreaPart); begin // do nothing 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.GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): TRect; begin Result := cxInvalidRect; 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.GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; begin if AAreaPart in [apLeft, apRight, apAfter, apBefore] then Result := atInsert else Result := atCreateGroup; end; function TdxLayoutGroupViewInfoHorizontalSpecific.GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): TRect; begin if AAreaPart = apCenter then begin Result := GroupViewInfo.ClientBounds; with Result do Right := Left + dxLayoutThinPartWidth; InflateRect(Result, Integer(cxRectWidth(Result) = 0), Integer(cxRectHeight(Result) = 0)); end else Result := inherited GetAreaPartBounds(AAreaPart, AItemViewInfo); end; 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.GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; begin if AAreaPart in [apTop, apBottom, apAfter, apBefore] then Result := atInsert else Result := atCreateGroup; end; function TdxLayoutGroupViewInfoVerticalSpecific.GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): TRect; begin if AAreaPart = apCenter then begin Result := GroupViewInfo.ClientBounds; with Result do Bottom := Top + dxLayoutThinPartWidth; InflateRect(Result, Integer(cxRectWidth(Result) = 0), Integer(cxRectHeight(Result) = 0)); end else Result := inherited GetAreaPartBounds(AAreaPart, AItemViewInfo); 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.Paint; begin inherited; DoPaint; end; procedure TdxLayoutTabbedGroupTabControl.DoPaint; begin CallNotify(FOnPaint, Self); 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; FTabControl.LockChangeEvent(True); try FTabControl.TabIndex := GroupViewInfo.Group.ItemIndex; finally FTabControl.LockChangeEvent(False); end; 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.GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; begin Result := atInsert; end; procedure TdxLayoutGroupViewInfoTabbedSpecific.CorrectAreaPart(var AAreaPart: TdxLayoutAreaPart); begin if AAreaPart in [apLeft, apTop] then AAreaPart := apBefore; if AAreaPart in [apRight, apBottom] then AAreaPart := apAfter; end; function TdxLayoutGroupViewInfoTabbedSpecific.GetAreaPart(const P: TPoint): TdxLayoutAreaPart; begin if HasTabControl and PtInRect(FTabControl.BoundsRect, P) then Result := apLastChild else Result := inherited GetAreaPart(P); end; function TdxLayoutGroupViewInfoTabbedSpecific.GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): TRect; begin //#DG ToDo: refactor case AAreaPart of apBefore: begin Result := FTabControl.TabsTabs[FTabControl.TabIndex].VisibleRect; Result.Right := Result.Left; Result.Right := Result.Right + dxLayoutThinPartWidth; OffsetRect(Result, FTabControl.Left, FTabControl.Top); end; apAfter: begin Result := FTabControl.TabsTabs[FTabControl.TabIndex].VisibleRect; Result.Left := Result.Right; Result.Right := Result.Right + dxLayoutThinPartWidth; OffsetRect(Result, FTabControl.Left, FTabControl.Top); end; apLastChild: begin Result := FTabControl.TabsTabs[FTabControl.Tabs.Count - 1].VisibleRect; Result.Left := Result.Right; Result.Right := Result.Right + dxLayoutThinPartWidth; OffsetRect(Result, FTabControl.Left, FTabControl.Top); end; else Result := inherited GetAreaPartBounds(AAreaPart, AItemviewInfo); 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); var P: TPoint; ADisplayRect, ABoundsRect: TRect; begin if not HasTabControl or FSpecificPainting then inherited else begin ACanvas.SaveState; FSpecificPainting := True; try ABoundsRect := FTabControl.BoundsRect; ADisplayRect := FTabControl.DisplayRect; P := cxPointOffset(ADisplayRect.TopLeft, ABoundsRect.TopLeft); cxPaintTo(FTabControl, ACanvas, P, ADisplayRect, False); finally FSpecificPainting := False; 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); GroupViewInfo.LayoutLookAndFeel.InitializeSubControlCxLookAndFeel(FTabControl.LookAndFeel); FTabControl.OnChange := ActiveTabChanged; FTabControl.OnPaint := TabControlPaint; 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; procedure TdxLayoutGroupViewInfoTabbedSpecific.TabControlPaint(ASender: TObject); begin if not (csPaintCopy in FTabControl.ControlState) then GroupViewInfo.Group.Container.PostInvalidateSelectionLayer(FTabControl.BoundsRect); 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 if Group.LayoutDirection = ldTabbed then Result := TdxLayoutTabbedGroupHitTest else 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; procedure TdxLayoutGroupViewInfo.CorrectAreaPart(var AAreaPart: TdxLayoutAreaPart); begin Specific.CorrectAreaPart(AAreaPart); end; function TdxLayoutGroupViewInfo.GetActionType(AAreaPart: TdxLayoutAreaPart): TdxLayoutActionType; begin if AAreaPart = apNone then Result := atNone else if (AAreaPart in [apCenter, apFirstChild, apLastChild]) then Result := atInsert else Result := Specific.GetActionType(AAreaPart); end; function TdxLayoutGroupViewInfo.GetAreaPart(const P: TPoint): TdxLayoutAreaPart; begin Result := Specific.GetAreaPart(P); if Result = apNone then Result := inherited GetAreaPart(P); end; function TdxLayoutGroupViewInfo.GetAreaPartBounds(AAreaPart: TdxLayoutAreaPart; AItemViewInfo: TdxCustomLayoutItemViewInfo): TRect; const PartWidth = 2; begin Result := AItemViewInfo.SelectionBorderRect; case AAreaPart of apLeft: with Result do Right := Left + PartWidth; apTop: with Result do Bottom := Top + PartWidth; apRight: with Result do Left := Right - PartWidth; apBottom: with Result do Top := Bottom - PartWidth; else Result := Specific.GetAreaPartBounds(AAreaPart, AItemViewInfo); end; 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 := 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; { 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 := 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 begin Result := TdxLayoutClientAreaHitTest.Instance; TdxLayoutClientAreaHitTest(Result).Control := Control; end; 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; initialization RegisterClasses([TdxLayoutItem, TdxLayoutGroup, TdxLayoutAlignmentConstraint]); HitTests := THitTests.Create; dxLayoutRunTimeSelectionHelperClass := TdxLayoutRunTimeSelectionHelper; dxLayoutDesignTimeSelectionHelperClass := TdxLayoutRunTimeSelectionHelper; PageControlDependsControls.Add(Pointer(TdxCustomLayoutControl)); finalization PageControlDependsControls.Remove(Pointer(TdxCustomLayoutControl)); FreeAndNil(HitTests); FreeAndNil(FDesignCustomizationHelper); end.