git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@55 05c56307-c608-d34a-929d-697000501d7a
1964 lines
62 KiB
ObjectPascal
1964 lines
62 KiB
ObjectPascal
|
|
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressLayoutControl customize form }
|
|
{ }
|
|
{ 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 dxLayoutCustomizeForm;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Contnrs, Controls, Forms, Dialogs,
|
|
ComCtrls, ActnList, Menus, ToolWin, StdCtrls, ImgList, cxClasses,
|
|
dxLayoutLookAndFeels, cxControls, cxGraphics, dxLayoutControl, dxLayoutDragAndDrop,
|
|
cxLookAndFeelPainters, cxButtons, cxContainer, cxEdit, cxGroupBox,
|
|
cxLookAndFeels, cxTreeView, cxCheckBox, dxLayoutcxEditAdapters;
|
|
|
|
type
|
|
TdxLayoutControlCustomizeForm = class(TdxLayoutControlCustomCustomizeForm)
|
|
alMain: TActionList;
|
|
acAddGroup: TAction;
|
|
acAddItem: TAction;
|
|
acClose: TAction;
|
|
acTreeViewExpandAll: TAction;
|
|
acTreeViewCollapseAll: TAction;
|
|
acTreeViewItemsDelete: TAction;
|
|
acAlignLeftSide: TAction;
|
|
acAlignRightSide: TAction;
|
|
acAlignTopSide: TAction;
|
|
acAlignBottomSide: TAction;
|
|
acAlignNone: TAction;
|
|
ilActions: TcxImageList;
|
|
ilItems: TcxImageList;
|
|
pmTreeViewActions: TPopupMenu;
|
|
miExpandAll: TMenuItem;
|
|
miCallapseAll: TMenuItem;
|
|
miSeparator1: TMenuItem;
|
|
miTreeViewDelete: TMenuItem;
|
|
miSeparator2: TMenuItem;
|
|
miAlignBy: TMenuItem;
|
|
pmAvailableItemsActions: TPopupMenu;
|
|
AddGroup1: TMenuItem;
|
|
AddItem1: TMenuItem;
|
|
Delete1: TMenuItem;
|
|
pmAlign: TPopupMenu;
|
|
Left1: TMenuItem;
|
|
Right1: TMenuItem;
|
|
op1: TMenuItem;
|
|
Bottom1: TMenuItem;
|
|
miSeparator3: TMenuItem;
|
|
miSeparator4: TMenuItem;
|
|
None1: TMenuItem;
|
|
lcMainGroup_Root: TdxLayoutGroup;
|
|
lcMain: TdxLayoutControl;
|
|
lcgTreeView: TdxLayoutGroup;
|
|
lcgAvailableItems: TdxLayoutGroup;
|
|
acAvailableItemsDelete: TAction;
|
|
acAvailableItemsExpandAll: TAction;
|
|
acAvailableItemsCollapseAll: TAction;
|
|
acAvailableItemsViewAsList: TAction;
|
|
acTabbedView: TAction;
|
|
acHighlightRoot: TAction;
|
|
lcMainGroup1: TdxLayoutGroup;
|
|
acShowDesignSelectors: TAction;
|
|
acStore: TAction;
|
|
acRestore: TAction;
|
|
ilHelper: TcxImageList;
|
|
acTreeViewItemRename: TAction;
|
|
miTreeViewItemRename: TMenuItem;
|
|
Rename2: TMenuItem;
|
|
acAvailableItemRename: TAction;
|
|
acUndo: TAction;
|
|
acRedo: TAction;
|
|
N1: TMenuItem;
|
|
Undo1: TMenuItem;
|
|
Redo1: TMenuItem;
|
|
N2: TMenuItem;
|
|
Undo2: TMenuItem;
|
|
Redo2: TMenuItem;
|
|
acAlignBy: TAction;
|
|
tvItems: TcxTreeView;
|
|
lcMainItem6: TdxLayoutItem;
|
|
tvAvailableItems: TcxTreeView;
|
|
lcMainItem8: TdxLayoutItem;
|
|
btnClose: TcxButton;
|
|
lcMainItem1: TdxLayoutItem;
|
|
lcMainGroup3: TdxLayoutGroup;
|
|
cbTabbedView: TcxCheckBox;
|
|
lcMainItem4: TdxLayoutItem;
|
|
liShowDesignSelectors: TdxLayoutItem;
|
|
btnShowDesignSelectors: TcxButton;
|
|
liHighlightRoot: TdxLayoutItem;
|
|
btnHighlightRoot: TcxButton;
|
|
liRestore: TdxLayoutItem;
|
|
btnRestore: TcxButton;
|
|
liStore: TdxLayoutItem;
|
|
btnStore: TcxButton;
|
|
liRedo: TdxLayoutItem;
|
|
btnRedo: TcxButton;
|
|
liUndo: TdxLayoutItem;
|
|
btnUndo: TcxButton;
|
|
lcMainGroup2: TdxLayoutGroup;
|
|
liAlignBy: TdxLayoutItem;
|
|
btnAlignBy: TcxButton;
|
|
lcMainItem7: TdxLayoutItem;
|
|
btnTreeViewItemsDelete: TcxButton;
|
|
lcMainItem9: TdxLayoutItem;
|
|
btnTreeViewCollapseAll: TcxButton;
|
|
lcMainItem10: TdxLayoutItem;
|
|
btnTreeViewExpandAll: TcxButton;
|
|
lgTreeView: TdxLayoutGroup;
|
|
lgAvailableItems: TdxLayoutGroup;
|
|
lcMainItem3: TdxLayoutItem;
|
|
btnAvailableItemsViewAsList: TcxButton;
|
|
lcMainItem11: TdxLayoutItem;
|
|
btnAvailableItemsDelete: TcxButton;
|
|
liAddCustomItem: TdxLayoutItem;
|
|
btnAddItem: TcxButton;
|
|
lcMainItem13: TdxLayoutItem;
|
|
btnAddGroup: TcxButton;
|
|
lcMainItem14: TdxLayoutItem;
|
|
btnAvailableItemsCollapseAll: TcxButton;
|
|
lcMainItem15: TdxLayoutItem;
|
|
btnAvailableItemsExpandAll: TcxButton;
|
|
acHAlignLeft: TAction;
|
|
acHAlignCenter: TAction;
|
|
acHAlignRight: TAction;
|
|
acHAlignClient: TAction;
|
|
acHAlignParent: TAction;
|
|
miAlignHorz: TMenuItem;
|
|
ahLeft1: TMenuItem;
|
|
ahCenter1: TMenuItem;
|
|
ahRight1: TMenuItem;
|
|
ahClient1: TMenuItem;
|
|
ahParentManaged1: TMenuItem;
|
|
acVAlignTop: TAction;
|
|
acVAlignBottom: TAction;
|
|
acVAlignCenter: TAction;
|
|
acVAlignClient: TAction;
|
|
acVAlignParent: TAction;
|
|
miAlignVert: TMenuItem;
|
|
acVAlignTop1: TMenuItem;
|
|
acVAlignCenter1: TMenuItem;
|
|
acVAlignBottom1: TMenuItem;
|
|
acVAlignClient1: TMenuItem;
|
|
acVAlignParent1: TMenuItem;
|
|
acDirectionHorizontal: TAction;
|
|
acDirectionVertical: TAction;
|
|
acDirectionTabbed: TAction;
|
|
miDirection: TMenuItem;
|
|
acDirectionHorizontal1: TMenuItem;
|
|
acDirectionVertical1: TMenuItem;
|
|
acDirectionTabbed1: TMenuItem;
|
|
acAddEmptySpaceItem: TAction;
|
|
acShowBorder: TAction;
|
|
miShowBorder: TMenuItem;
|
|
acAddSeparator: TAction;
|
|
AddEmptySpaceItem1: TMenuItem;
|
|
acAddSeparator1: TMenuItem;
|
|
acAddSplitter: TAction;
|
|
acAddLabeledItem: TAction;
|
|
PopupMenu1: TPopupMenu;
|
|
AddEmptySpaceItem2: TMenuItem;
|
|
acAddLabeledItem1: TMenuItem;
|
|
acAddSeparator2: TMenuItem;
|
|
acAddSplitter1: TMenuItem;
|
|
acAddCustomItem: TAction;
|
|
AddSplitter1: TMenuItem;
|
|
AddLabel1: TMenuItem;
|
|
lcMainSeparatorItem1: TdxLayoutSeparatorItem;
|
|
lcMainSeparatorItem2: TdxLayoutSeparatorItem;
|
|
N3: TMenuItem;
|
|
lcMainSeparatorItem3: TdxLayoutSeparatorItem;
|
|
lsAlignBy: TdxLayoutSeparatorItem;
|
|
N4: TMenuItem;
|
|
ExpandAll1: TMenuItem;
|
|
CallapseAll1: TMenuItem;
|
|
liAddItem: TdxLayoutItem;
|
|
cxButton1: TcxButton;
|
|
lsSeparator4: TdxLayoutSeparatorItem;
|
|
procedure acCloseExecute(Sender: TObject);
|
|
procedure acAddGroupExecute(Sender: TObject);
|
|
procedure acAddItemExecute(Sender: TObject);
|
|
procedure tvItemsEdited(Sender: TObject; Node: TTreeNode;
|
|
var S: String);
|
|
procedure tvItemsMouseDown(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
procedure ItemsMouseMove(Sender: TObject; Shift: TShiftState; X,
|
|
Y: Integer);
|
|
procedure ItemsMouseUp(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
procedure tvItemsChange(Sender: TObject; Node: TTreeNode);
|
|
procedure tvItemsChanging(Sender: TObject; Node: TTreeNode;
|
|
var AllowChange: Boolean);
|
|
procedure AlignExecute(Sender: TObject);
|
|
procedure acTreeViewItemsDeleteExecute(Sender: TObject);
|
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
|
procedure tvItemsContextPopup(Sender: TObject; MousePos: TPoint;
|
|
var Handled: Boolean);
|
|
procedure acAvailableItemsDeleteExecute(Sender: TObject);
|
|
procedure tvItemsCustomDrawItem(Sender: TCustomTreeView;
|
|
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
|
|
procedure tvAvailableItemsContextPopup(Sender: TObject;
|
|
MousePos: TPoint; var Handled: Boolean);
|
|
procedure acAvailableItemsExpandAllExecute(Sender: TObject);
|
|
procedure acAvailableItemsCollapseAllExecute(Sender: TObject);
|
|
procedure acTreeViewExpandAllExecute(Sender: TObject);
|
|
procedure acTreeViewCollapseAllExecute(Sender: TObject);
|
|
procedure acAvailableItemsViewAsListExecute(Sender: TObject);
|
|
procedure tvItemsEditing(Sender: TObject; Node: TTreeNode;
|
|
var AllowEdit: Boolean);
|
|
procedure FormShortCut(var Msg: TWMKey; var Handled: Boolean);
|
|
procedure FormKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
procedure acTabbedViewExecute(Sender: TObject);
|
|
procedure acHighlightRootExecute(Sender: TObject);
|
|
procedure acShowDesignSelectorsExecute(Sender: TObject);
|
|
procedure acStoreExecute(Sender: TObject);
|
|
procedure acRestoreExecute(Sender: TObject);
|
|
procedure acTreeViewItemRenameExecute(Sender: TObject);
|
|
procedure acAvailableItemRenameExecute(Sender: TObject);
|
|
procedure acUndoExecute(Sender: TObject);
|
|
procedure acRedoExecute(Sender: TObject);
|
|
procedure acAlignByExecute(Sender: TObject);
|
|
procedure acHAlignExecute(Sender: TObject);
|
|
procedure pmTreeViewActionsPopup(Sender: TObject);
|
|
procedure acVAlignExecute(Sender: TObject);
|
|
procedure acDirectionsExecute(Sender: TObject);
|
|
procedure acAddEmptySpaceItemExecute(Sender: TObject);
|
|
procedure acShowBorderExecute(Sender: TObject);
|
|
procedure acAddSeparatorExecute(Sender: TObject);
|
|
procedure acAddCustomItemExecute(Sender: TObject);
|
|
procedure acAddLabeledItemExecute(Sender: TObject);
|
|
procedure acAddSplitterExecute(Sender: TObject);
|
|
procedure tvItemsDeletion(Sender: TObject; Node: TTreeNode);
|
|
private
|
|
FDragHelper: TdxLayoutDragAndDropHelper;
|
|
FCollapsedItems: TcxComponentList;
|
|
FCollapsedItemsStoredCount: Integer;
|
|
FLockCount: Integer;
|
|
FAvailableItemsWndProc: TWndMethod;
|
|
FItemsWndProc: TWndMethod;
|
|
procedure AddItemNode(ANodes: TTreeNodes; AParentNode: TTreeNode; AItem: TdxCustomLayoutItem; AAddChildren: Boolean = True);
|
|
procedure AvailableItemsWndProc(var Message: TMessage);
|
|
function CreateItem(AClass: TdxCustomLayoutItemClass; const ACaption: string): TdxCustomLayoutItem;
|
|
procedure DoAfterInsertionItem(AItem: TdxCustomLayoutItem);
|
|
function GetImageIndex(AItem: TdxCustomLayoutItem): Integer;
|
|
function GetIsLocked: Boolean;
|
|
procedure InitializePopupMenu;
|
|
procedure ItemsWndProc(var Message: TMessage);
|
|
procedure RefreshImages;
|
|
procedure RefreshLists(ARefreshSelection: Boolean = False);
|
|
procedure RefreshNode(ANode: TTreeNode);
|
|
procedure RefreshButtonStates;
|
|
procedure RefreshView;
|
|
procedure SaveToUndo;
|
|
procedure SelectItem(AItem: TdxCustomLayoutItem);
|
|
procedure SetItemsSelections(AList: TList);
|
|
procedure SetLayoutItemsSelections(ATreeView: TTreeView);
|
|
function TreeViewWndProcHandler(ATreeView: TTreeView; var Message: TMessage): Boolean;
|
|
|
|
procedure RestoreCollapsedNodes;
|
|
procedure StoreCollapsedNodes;
|
|
protected
|
|
procedure CreateWindowHandle(const Params: TCreateParams); override;
|
|
procedure DestroyWindowHandle; override;
|
|
procedure Loaded; override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
|
|
procedure ItemChanged(AItem: TdxCustomLayoutItem); override;
|
|
procedure InitializeControl; override;
|
|
function GetLayoutPopupMenu: TPopupMenu; override;
|
|
function CanDeleteItems(ATreeView: TcxTreeView): Boolean;
|
|
procedure DeleteItems(AList: TComponentList; ATreeView: TTreeView);
|
|
function GetNode(AItem: TdxCustomLayoutItem; out ANode: TTreeNode): Boolean;
|
|
procedure Localize; virtual;
|
|
function NeedRefreshItemsAfterDeleting(AComponent: TPersistent): Boolean;
|
|
procedure RefreshAvailableItems;
|
|
procedure RefreshEnableds;
|
|
procedure RefreshTreeView;
|
|
|
|
procedure StoreTreeViewWndProc(ATreeView: TTreeView; var AStoredWndMethod: TWndMethod; ANewWndMethod: TWndMethod);
|
|
procedure RestoreTreeViewWndProc(ATreeView: TTreeView; var AStoredWndMethod: TWndMethod);
|
|
|
|
property DragHelper: TdxLayoutDragAndDropHelper read FDragHelper;
|
|
property IsLocked: Boolean read GetIsLocked;
|
|
property LockCount: Integer read FLockCount;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
function GetHitTest(const P: TPoint): TdxCustomLayoutHitTest; override;
|
|
procedure ToggleHotTrackState(AItem: TdxCustomLayoutItem); override;
|
|
|
|
// Updates
|
|
procedure BeginUpdate;
|
|
procedure CancelUpdate;
|
|
procedure EndUpdate;
|
|
|
|
procedure UpdateAvailableItems; override;
|
|
procedure UpdateCaption; override;
|
|
procedure UpdateContent; override;
|
|
procedure UpdateDragAndDropState; override;
|
|
procedure UpdateSelection; override;
|
|
procedure UpdateView; override;
|
|
procedure UpdateVisibleItems; override;
|
|
end;
|
|
|
|
procedure cxTreeViewGetSelection(ATreeView: TTreeView; AList: TList);
|
|
procedure cxTreeViewSyncSelection(ATreeView: TTreeView; AList: TList);
|
|
|
|
implementation
|
|
|
|
{$R *.DFM}
|
|
|
|
uses
|
|
Types, Math, CommCtrl, dxLayoutCommon, dxLayoutEditForm, cxGeometry,
|
|
dxLayoutStrs, dxCore, dxOffice11, dxLayoutSelection;
|
|
|
|
type
|
|
TdxLayoutDragAndDropObjectAccess = class(TdxLayoutDragAndDropObject);
|
|
TdxCustomLayoutControlAccess = class(TdxCustomLayoutControl);
|
|
TdxCustomLayoutItemAccess = class(TdxCustomLayoutItem);
|
|
TdxCustomLayoutItemViewInfoAccess = class(TdxCustomLayoutItemViewInfo);
|
|
TToolBarAccess = class(TToolBar);
|
|
|
|
function CompareItemsByClass(Item1, Item2: Pointer): Integer;
|
|
var
|
|
AItem1, AItem2: TdxCustomLayoutItem;
|
|
begin
|
|
AItem1 := TdxCustomLayoutItem(Item1);
|
|
AItem2 := TdxCustomLayoutItem(Item2);
|
|
Result := Integer(AItem1.ClassType) - Integer(AItem2.ClassType);
|
|
end;
|
|
|
|
function CompareItemsByName(Item1, Item2: Pointer): Integer;
|
|
|
|
procedure SplitNameByTrailingDigits(const AName: string; out ATrailingDigits: Integer;
|
|
out ANameWithoutTrailingDigitals: string);
|
|
var
|
|
ACurrentLength: Integer;
|
|
begin
|
|
ANameWithoutTrailingDigitals := AName;
|
|
ACurrentLength := Length(ANameWithoutTrailingDigitals);
|
|
while (ACurrentLength > 0) and
|
|
dxCharIsNumeric(ANameWithoutTrailingDigitals[ACurrentLength]) do
|
|
begin
|
|
ATrailingDigits := ATrailingDigits * 10 +
|
|
StrToInt(ANameWithoutTrailingDigitals[ACurrentLength]);
|
|
ANameWithoutTrailingDigitals := Copy(ANameWithoutTrailingDigitals, 1, ACurrentLength - 1);
|
|
ACurrentLength := Length(ANameWithoutTrailingDigitals);
|
|
end;
|
|
if ACurrentLength = Length(AName) then
|
|
ATrailingDigits := -1
|
|
else
|
|
ATrailingDigits := StrToInt(Copy(AName, ACurrentLength + 1, Length(AName) - ACurrentLength));
|
|
end;
|
|
|
|
var
|
|
AName1, AName2: string;
|
|
ANameWithoutLastDigitals1, ANameWithoutLastDigitals2: string;
|
|
ANumber1, ANumber2: Integer;
|
|
begin
|
|
Result := CompareItemsByClass(Item1, Item2);
|
|
if Result = 0 then
|
|
begin
|
|
AName1 := TdxCustomLayoutItem(Item1).CaptionForCustomizeForm;
|
|
AName2 := TdxCustomLayoutItem(Item2).CaptionForCustomizeForm;
|
|
if AName1 = AName2 then
|
|
begin
|
|
AName1 := AName1 + TdxCustomLayoutItem(Item1).Name;
|
|
AName2 := AName2 + TdxCustomLayoutItem(Item2).Name;
|
|
end;
|
|
SplitNameByTrailingDigits(AName1, ANumber1, ANameWithoutLastDigitals1);
|
|
SplitNameByTrailingDigits(AName2, ANumber2, ANameWithoutLastDigitals2);
|
|
Result := CompareText(ANameWithoutLastDigitals1, ANameWithoutLastDigitals2);
|
|
if Result = 0 then
|
|
Result := ANumber1 - ANumber2;
|
|
end;
|
|
end;
|
|
|
|
function CompareItems(Item1, Item2: Pointer): Integer;
|
|
begin
|
|
Result := CompareItemsByClass(Item1, Item2);
|
|
if (Result = 0) and (TObject(Item1) is TdxLayoutGroup) then
|
|
Result := Integer(TdxLayoutGroup(Item1).Count > 0) - Integer(TdxLayoutGroup(Item2).Count > 0);
|
|
if Result = 0 then
|
|
Result := CompareItemsByName(Item1, Item2);
|
|
end;
|
|
|
|
procedure cxTreeViewGetSelection(ATreeView: TTreeView; AList: TList);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to ATreeView.SelectionCount - 1 do
|
|
AList.Add(ATreeView.Selections[I].Data);
|
|
end;
|
|
|
|
procedure cxTreeViewSyncSelection(ATreeView: TTreeView; AList: TList);
|
|
|
|
procedure InternalSyncSelection(ANode: TTreeNode);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ANode = nil then
|
|
Exit;
|
|
if ANode.Selected xor (ANode.Data <> nil) and (AList.IndexOf(ANode.Data) >= 0) then
|
|
if ANode.Selected then
|
|
ATreeView.Deselect(ANode)
|
|
else
|
|
ATreeView.Select(ANode, [ssCtrl]);
|
|
ANode.Focused := ANode.Selected;
|
|
for I := 0 to ANode.Count - 1 do
|
|
InternalSyncSelection(ANode[I]);
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with ATreeView do
|
|
begin
|
|
if AList.Count > 0 then
|
|
for I := 0 to Items.Count - 1 do
|
|
InternalSyncSelection(Items[I])
|
|
else
|
|
ATreeView.ClearSelection(False);
|
|
end;
|
|
if ATreeView.SelectionCount = 0 then
|
|
ATreeView.Selected := nil;
|
|
end;
|
|
|
|
{ TdxLayoutDesignForm }
|
|
|
|
constructor TdxLayoutControlCustomizeForm.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FCollapsedItems := TcxComponentList.Create(False);
|
|
Localize;
|
|
InitializePopupMenu;
|
|
RefreshImages;
|
|
tvItems.InnerTreeView.PopupMenu := pmTreeViewActions;
|
|
tvAvailableItems.InnerTreeView.PopupMenu := pmAvailableItemsActions;
|
|
end;
|
|
|
|
destructor TdxLayoutControlCustomizeForm.Destroy;
|
|
begin
|
|
FreeAndNil(FDragHelper);
|
|
FreeAndNil(FCollapsedItems);
|
|
inherited;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest;
|
|
|
|
function IsMenuKeyDown: Boolean;
|
|
begin
|
|
Result := GetAsyncKeyState(VK_MENU) <> 0;
|
|
end;
|
|
|
|
function GetAreaPart(AItem: TdxCustomLayoutItem): TdxLayoutAreaPart;
|
|
const
|
|
AreaParts: array[Boolean] of TdxLayoutAreaPart = (apAfter, apBefore);
|
|
var
|
|
ASourceItem: TdxCustomLayoutItem;
|
|
ASourceNode, ADestinationNode: TTreeNode;
|
|
AIsBefore: Boolean;
|
|
begin
|
|
if (AItem is TdxLayoutGroup) and IsMenuKeyDown then
|
|
Result := apLastChild
|
|
else
|
|
if (dxLayoutDragAndDropObject <> nil) and (TdxLayoutDragAndDropObjectAccess(dxLayoutDragAndDropObject).Control = Control) then
|
|
begin
|
|
ASourceItem := dxLayoutDragAndDropObject.SourceItem;
|
|
AIsBefore := GetNode(ASourceItem, ASourceNode) and GetNode(AItem, ADestinationNode) and
|
|
(ASourceNode.TreeView = ADestinationNode.TreeView) and
|
|
(ASourceNode.AbsoluteIndex > ADestinationNode.AbsoluteIndex);
|
|
Result := AreaParts[AIsBefore];
|
|
end
|
|
else
|
|
Result := apAfter;
|
|
end;
|
|
|
|
function GetHitNode(ATreeView: TcxTreeView): TTreeNode;
|
|
begin
|
|
with cxPointOffset(P, ATreeView.BoundsRect.TopLeft, False) do
|
|
if htOnItem in ATreeView.GetHitTestInfoAt(X, Y) then
|
|
Result := ATreeView.GetNodeAt(X, Y)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
var
|
|
AItem: TdxCustomLayoutItem;
|
|
ANode: TTreeNode;
|
|
begin
|
|
ANode := nil;
|
|
if tvItems.Visible and PtInRect(tvItems.BoundsRect, P) then
|
|
begin
|
|
Result := TdxLayoutCustomizeFormTreeViewItemsHitTest.Instance;
|
|
ANode := GetHitNode(tvItems);
|
|
end
|
|
else
|
|
if tvAvailableItems.Visible and PtInRect(tvAvailableItems.BoundsRect, P) then
|
|
begin
|
|
Result := TdxLayoutCustomizeFormAvailableItemsHitTest.Instance;
|
|
ANode := GetHitNode(tvAvailableItems);
|
|
end
|
|
else
|
|
Result := inherited GetHitTest(P);
|
|
if ANode <> nil then
|
|
begin
|
|
AItem := TdxCustomLayoutItem(ANode.Data);
|
|
TdxLayoutCustomizeFormHitTest(Result).HitItem := AItem;
|
|
TdxLayoutCustomizeFormHitTest(Result).AreaPart := GetAreaPart(AItem);
|
|
end
|
|
else
|
|
TdxLayoutCustomizeFormHitTest(Result).HitItem := nil;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.ToggleHotTrackState(AItem: TdxCustomLayoutItem);
|
|
var
|
|
ANode: TTreeNode;
|
|
R: TRect;
|
|
begin
|
|
if GetNode(AItem, ANode) and ANode.IsVisible then
|
|
begin
|
|
R := ANode.DisplayRect(False);
|
|
InvalidateRect(ANode.TreeView.Handle, @R, True);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.BeginUpdate;
|
|
begin
|
|
Inc(FLockCount);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.CancelUpdate;
|
|
begin
|
|
Dec(FLockCount);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.EndUpdate;
|
|
begin
|
|
Dec(FLockCount);
|
|
if LockCount = 0 then
|
|
RefreshLists(True);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.UpdateAvailableItems;
|
|
begin
|
|
RefreshAvailableItems;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.UpdateCaption;
|
|
begin
|
|
if Control.IsDesigning then
|
|
Caption := Format(cxGetResourceString(@sdxLayoutControlDesignerCaptionFormat), [cxGetFullComponentName(Control)])
|
|
else
|
|
Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormCaption);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.UpdateContent;
|
|
begin
|
|
RefreshLists;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.UpdateDragAndDropState;
|
|
begin
|
|
if (FDragHelper.DragItem <> nil) and (Control.DragAndDropState = ddsNone) then
|
|
FDragHelper.Reset;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.UpdateSelection;
|
|
var
|
|
AList: TList;
|
|
AIntf: IdxLayoutDesignerHelper;
|
|
begin
|
|
if IsLocked then
|
|
Exit;
|
|
AList := TList.Create;
|
|
try
|
|
if Supports(Control, IdxLayoutDesignerHelper, AIntf) then
|
|
begin
|
|
AIntf.GetSelection(AList);
|
|
AIntf := nil;
|
|
end;
|
|
SetItemsSelections(AList);
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.UpdateView;
|
|
begin
|
|
RefreshView;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.UpdateVisibleItems;
|
|
begin
|
|
RefreshTreeView;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.CreateWindowHandle(const Params: TCreateParams);
|
|
begin
|
|
inherited CreateWindowHandle(Params);
|
|
StoreTreeViewWndProc(tvItems.InnerTreeView, FItemsWndProc, ItemsWndProc);
|
|
StoreTreeViewWndProc(tvAvailableItems.InnerTreeView, FAvailableItemsWndProc, AvailableItemsWndProc);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.DestroyWindowHandle;
|
|
begin
|
|
inherited DestroyWindowHandle;
|
|
RestoreTreeViewWndProc(tvItems.InnerTreeView, FItemsWndProc);
|
|
RestoreTreeViewWndProc(tvAvailableItems.InnerTreeView, FAvailableItemsWndProc);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
Constraints.MinHeight := Height div 2;
|
|
Constraints.MinWidth := Width;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.Notification(AComponent: TComponent; Operation: TOperation);
|
|
var
|
|
ANode: TTreeNode;
|
|
begin
|
|
inherited;
|
|
if (Operation = opRemove) and (AComponent is TdxCustomLayoutItem) and GetNode(AComponent as TdxCustomLayoutItem, ANode) then
|
|
ANode.Delete;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.CanDeleteItems(ATreeView: TcxTreeView): Boolean;
|
|
var
|
|
AList: TList;
|
|
I: Integer;
|
|
AIntf: IdxLayoutDesignerHelper;
|
|
begin
|
|
Result := not ATreeView.IsEditing;
|
|
if Result then
|
|
begin
|
|
AList := TList.Create;
|
|
try
|
|
cxTreeViewGetSelection(ATreeView.InnerTreeView, AList);
|
|
Result := AList.Count > 0;
|
|
if Result then
|
|
for I := 0 to AList.Count - 1 do
|
|
begin
|
|
if Supports(Control, IdxLayoutDesignerHelper, AIntf) then
|
|
begin
|
|
Result := AIntf.CanDeleteComponent(TComponent(AList[I]));
|
|
AIntf := nil;
|
|
end;
|
|
if not Result then
|
|
Break;
|
|
end;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.DeleteItems(AList: TComponentList; ATreeView: TTreeView);
|
|
begin
|
|
if AList.Count = 0 then
|
|
Exit;
|
|
SaveToUndo;
|
|
BeginUpdate;
|
|
ATreeView.Items.BeginUpdate;
|
|
try
|
|
Control.BeginUpdate;
|
|
try
|
|
while AList.Count > 0 do
|
|
AList[0].Free;
|
|
finally
|
|
Control.EndUpdate;
|
|
end;
|
|
finally
|
|
ATreeView.Items.EndUpdate;
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.GetNode(AItem: TdxCustomLayoutItem; out ANode: TTreeNode): Boolean;
|
|
|
|
function FindNode(ANodes: TTreeNodes): TTreeNode;
|
|
|
|
function FindNode(ANode: TTreeNode): TTreeNode;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := nil;
|
|
if ANode.Data = AItem then
|
|
Result := ANode
|
|
else
|
|
if ANode.HasChildren then
|
|
for I := 0 to ANode.Count - 1 do
|
|
begin
|
|
Result := FindNode(ANode.Item[I]);
|
|
if Result <> nil then
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := nil;
|
|
for I := 0 to ANodes.Count - 1 do
|
|
begin
|
|
Result := FindNode(ANodes[I]);
|
|
if Result <> nil then
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
ANode := FindNode(tvAvailableItems.Items);
|
|
if ANode = nil then
|
|
ANode := FindNode(tvItems.Items);
|
|
Result := ANode <> nil;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.GetLayoutPopupMenu: TPopupMenu;
|
|
begin
|
|
Result := pmTreeViewActions;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.ItemChanged(AItem: TdxCustomLayoutItem);
|
|
var
|
|
ANode: TTreeNode;
|
|
begin
|
|
if GetNode(AItem, ANode) and not IsLocked then
|
|
RefreshNode(ANode);
|
|
if not IsLocked then
|
|
RefreshButtonStates;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.InitializeControl;
|
|
begin
|
|
lcMain.BeginUpdate;
|
|
try
|
|
FDragHelper.Free;
|
|
FDragHelper := TdxLayoutDragAndDropHelper.Create(Control);
|
|
inherited;
|
|
tvItems.FullExpand;
|
|
tvAvailableItems.FullExpand;
|
|
finally
|
|
lcMain.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.Localize;
|
|
begin
|
|
acAddGroup.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddGroup);
|
|
acAddGroup.Hint := StripHotKey(acAddGroup.Caption);
|
|
|
|
acAddItem.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddItem);
|
|
acAddItem.Hint := StripHotKey(acAddItem.Caption);
|
|
|
|
acAddCustomItem.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddAuxiliaryItem);
|
|
acAddCustomItem.Hint := StripHotKey(acAddCustomItem.Caption);
|
|
|
|
acAddEmptySpaceItem.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddEmptySpaceItem);
|
|
acAddEmptySpaceItem.Hint := StripHotKey(acAddEmptySpaceItem.Caption);
|
|
|
|
acAddSeparator.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddSeparatorItem);
|
|
acAddSeparator.Hint := StripHotKey(acAddSeparator.Caption);
|
|
|
|
acAddSplitter.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddSplitterItem);
|
|
acAddSplitter.Hint := StripHotKey(acAddSplitter.Caption);
|
|
|
|
acAddLabeledItem.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddLabeledItem);
|
|
acAddLabeledItem.Hint := StripHotKey(acAddLabeledItem.Caption);
|
|
|
|
acAvailableItemsDelete.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormDelete);
|
|
acAvailableItemsDelete.Hint := cxGetResourceString(@sdxLayoutControlCustomizeFormDeleteHint);
|
|
|
|
acTreeViewItemsDelete.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormDelete);
|
|
acTreeViewItemsDelete.Hint := cxGetResourceString(@sdxLayoutControlCustomizeFormDeleteHint);
|
|
|
|
acAlignBy.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAlignBy);
|
|
acAlignBy.Hint := StripHotKey(acAlignBy.Caption);
|
|
|
|
acClose.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormClose);
|
|
acClose.Hint := StripHotKey(acClose.Caption);
|
|
|
|
acTreeViewExpandAll.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormExpandAll);
|
|
acTreeViewExpandAll.Hint := StripHotKey(acTreeViewExpandAll.Caption);
|
|
|
|
acAvailableItemsExpandAll.Caption := acTreeViewExpandAll.Caption;
|
|
acAvailableItemsExpandAll.Hint := acTreeViewExpandAll.Hint;
|
|
|
|
acTreeViewCollapseAll.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormCollapseAll);
|
|
acTreeViewCollapseAll.Hint := StripHotKey(acTreeViewCollapseAll.Caption);
|
|
|
|
acAvailableItemsCollapseAll.Caption := acTreeViewCollapseAll.Caption;
|
|
acAvailableItemsCollapseAll.Hint := StripHotKey(acTreeViewCollapseAll.Hint);
|
|
|
|
acAlignLeftSide.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAlignLeftSide);
|
|
acAlignRightSide.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAlignRightSide);
|
|
acAlignTopSide.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAlignTopSide);
|
|
acAlignBottomSide.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAlignBottomSide);
|
|
acAlignNone.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAlignNone);
|
|
|
|
miAlignHorz.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormHAlign);
|
|
acHAlignLeft.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormHAlignLeft);
|
|
acHAlignCenter.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormHAlignCenter);
|
|
acHAlignRight.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormHAlignRight);
|
|
acHAlignClient.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormHAlignClient);
|
|
acHAlignParent.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormHAlignParent);
|
|
|
|
miAlignVert.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormVAlign);
|
|
acVAlignTop.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormVAlignTop);
|
|
acVAlignCenter.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormVAlignCenter);
|
|
acVAlignBottom.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormVAlignBottom);
|
|
acVAlignClient.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormVAlignClient);
|
|
acVAlignParent.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormVAlignParent);
|
|
|
|
miDirection.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormDirection);
|
|
acDirectionHorizontal.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormDirectionHorizontal);
|
|
acDirectionVertical.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormDirectionVertical);
|
|
acDirectionTabbed.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormDirectionTabbed);
|
|
|
|
acShowBorder.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormShowBorder);
|
|
|
|
lcgTreeView.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormTreeViewGroup);
|
|
lcgAvailableItems.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormListViewGroup);
|
|
|
|
acTabbedView.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormTabbedView);
|
|
acTabbedView.Hint := StripHotKey(acTabbedView.Caption);
|
|
|
|
acAvailableItemsViewAsList.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormTreeView);
|
|
acAvailableItemsViewAsList.Hint := StripHotKey(acAvailableItemsViewAsList.Caption);
|
|
|
|
acStore.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormStore);
|
|
acStore.Hint := StripHotKey(acStore.Caption);
|
|
|
|
acRestore.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormRestore);
|
|
acRestore.Hint := StripHotKey(acRestore.Caption);
|
|
|
|
acTreeViewItemRename.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormRename);
|
|
acTreeViewItemRename.Hint := acTreeViewItemRename.Caption;
|
|
|
|
acAvailableItemRename.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormRename);
|
|
acAvailableItemRename.Hint := acAvailableItemRename.Caption;
|
|
|
|
acUndo.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormUndo);
|
|
acUndo.Hint := acUndo.Caption;
|
|
|
|
acRedo.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormRedo);
|
|
acRedo.Hint := acRedo.Caption;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.NeedRefreshItemsAfterDeleting(AComponent: TPersistent): Boolean;
|
|
begin
|
|
Result := (AComponent is TdxCustomLayoutItem) and
|
|
(TdxCustomLayoutItem(AComponent).Container = Control);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RefreshAvailableItems;
|
|
|
|
procedure PopulateItemChildren(AList: TList; AItem: TdxCustomLayoutItem);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if AItem is TdxLayoutGroup then
|
|
begin
|
|
for I := 0 to TdxLayoutGroup(AItem).Count - 1 do
|
|
begin
|
|
AList.Add(TdxLayoutGroup(AItem).Items[I]);
|
|
PopulateItemChildren(AList, TdxLayoutGroup(AItem).Items[I]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure PopulateItems(AList: TList);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Control.AvailableItemCount - 1 do
|
|
begin
|
|
AList.Add(Control.AvailableItems[I]);
|
|
if Control.CustomizeAvailableItemsViewKind = aivkList then
|
|
PopulateItemChildren(AList, Control.AvailableItems[I]);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AList: TList;
|
|
I: Integer;
|
|
begin
|
|
with tvAvailableItems do
|
|
begin
|
|
BeginUpdate;
|
|
Items.BeginUpdate;
|
|
try
|
|
StoreCollapsedNodes;
|
|
Items.Clear;
|
|
AList := TList.Create;
|
|
try
|
|
PopulateItems(AList);
|
|
case Control.CustomizeAvailableItemsViewKind of
|
|
aivkList:
|
|
begin
|
|
AList.Sort(CompareItemsByName);
|
|
for I := 0 to AList.Count - 1 do
|
|
AddItemNode(Items, nil, TdxCustomLayoutItem(AList[I]), False);
|
|
end;
|
|
aivkTree:
|
|
begin
|
|
AList.Sort(CompareItems);
|
|
for I := 0 to AList.Count - 1 do
|
|
AddItemNode(Items, nil, TdxCustomLayoutItem(AList[I]));
|
|
end;
|
|
end;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
RestoreCollapsedNodes;
|
|
finally
|
|
Items.EndUpdate;
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
tvAvailableItems.ShowRoot := Control.CustomizeAvailableItemsViewKind = aivkTree;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RefreshEnableds;
|
|
begin
|
|
if not IsLocked then
|
|
begin
|
|
acAlignBy.Enabled := (tvItems.SelectionCount > 1);
|
|
acAvailableItemsExpandAll.Enabled := Control.CustomizeAvailableItemsViewKind = aivkTree;
|
|
acAvailableItemsCollapseAll.Enabled := Control.CustomizeAvailableItemsViewKind = aivkTree;
|
|
acRestore.Enabled := Control.CanRestore;
|
|
acTreeViewItemRename.Enabled := (tvItems.Selected <> nil) and (tvItems.SelectionCount = 1) and
|
|
not (TObject(tvItems.Selected.Data) as TdxCustomLayoutItem).IsRoot and not TdxCustomLayoutItemAccess(tvItems.Selected.Data).IsParentLocked;
|
|
acAvailableItemRename.Enabled := (tvAvailableItems.Selected <> nil) and (tvAvailableItems.SelectionCount = 1) and
|
|
not TdxCustomLayoutItemAccess(tvAvailableItems.Selected.Data).IsParentLocked;
|
|
acUndo.Enabled := Control.UndoRedoManager.CanUndo;
|
|
acRedo.Enabled := Control.UndoRedoManager.CanRedo;
|
|
acAddItem.Enabled := Control.IsDesigning;
|
|
acTreeViewItemsDelete.Enabled := CanDeleteItems(tvItems);
|
|
acAvailableItemsDelete.Enabled := CanDeleteItems(tvAvailableItems);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RefreshTreeView;
|
|
begin
|
|
with tvItems do
|
|
begin
|
|
BeginUpdate;
|
|
Items.BeginUpdate;
|
|
try
|
|
StoreCollapsedNodes;
|
|
Items.Clear;
|
|
AddItemNode(Items, nil, Control.Items);
|
|
RestoreCollapsedNodes;
|
|
finally
|
|
Items.EndUpdate;
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.StoreTreeViewWndProc(ATreeView: TTreeView; var AStoredWndMethod: TWndMethod; ANewWndMethod: TWndMethod);
|
|
begin
|
|
AStoredWndMethod := ATreeView.WindowProc;
|
|
ATreeView.WindowProc := ANewWndMethod;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RestoreTreeViewWndProc(ATreeView: TTreeView; var AStoredWndMethod: TWndMethod);
|
|
begin
|
|
if Assigned(AStoredWndMethod) then
|
|
ATreeView.WindowProc := AStoredWndMethod;
|
|
AStoredWndMethod := nil;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.AddItemNode(ANodes: TTreeNodes; AParentNode: TTreeNode; AItem: TdxCustomLayoutItem; AAddChildren: Boolean = True);
|
|
var
|
|
I: Integer;
|
|
AThisNode: TTreeNode;
|
|
AGroup: TdxLayoutGroup;
|
|
begin
|
|
AThisNode := ANodes.AddChild(AParentNode, '');
|
|
AThisNode.Data := AItem;
|
|
AItem.FreeNotification(Self);
|
|
RefreshNode(AThisNode);
|
|
AThisNode.Selected := False;
|
|
AThisNode.Focused := False;
|
|
if AAddChildren and (AItem is TdxLayoutGroup) then
|
|
begin
|
|
AGroup := TdxLayoutGroup(AItem);
|
|
for I := 0 to AGroup.Count - 1 do
|
|
AddItemNode(ANodes, AThisNode, AGroup[I]);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.AvailableItemsWndProc(var Message: TMessage);
|
|
begin
|
|
if not TreeViewWndProcHandler(tvAvailableItems.InnerTreeView, Message) then
|
|
begin
|
|
case Message.Msg of
|
|
WM_DESTROY:
|
|
begin
|
|
RestoreTreeViewWndProc(tvAvailableItems.InnerTreeView, FAvailableItemsWndProc);
|
|
tvAvailableItems.InnerTreeView.WindowProc(Message);
|
|
end;
|
|
else
|
|
FAvailableItemsWndProc(Message);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.CreateItem(AClass: TdxCustomLayoutItemClass; const ACaption: string): TdxCustomLayoutItem;
|
|
begin
|
|
SaveToUndo;
|
|
BeginUpdate;
|
|
try
|
|
Result := Control.CreateItem(AClass);
|
|
Result.Caption := ACaption;
|
|
DoAfterInsertionItem(Result);
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
RefreshAvailableItems;
|
|
UpdateSelection;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.DoAfterInsertionItem(AItem: TdxCustomLayoutItem);
|
|
var
|
|
AIntf: IdxLayoutDesignerHelper;
|
|
begin
|
|
if Supports(Control, IdxLayoutDesignerHelper, AIntf) then
|
|
begin
|
|
AIntf.SelectComponent(AItem);
|
|
AIntf := nil;
|
|
end;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.GetImageIndex(AItem: TdxCustomLayoutItem): Integer;
|
|
const
|
|
AGroupIndexMap: array[Boolean, TdxLayoutDirection] of Integer = (
|
|
(7, 8, 9),
|
|
(17, 18, 19));
|
|
ASeparatorIndexMap: array[Boolean] of Integer = (2, 3);
|
|
ASplitterIndexMap: array[Boolean] of Integer = (4, 5);
|
|
|
|
var
|
|
AGroup: TdxLayoutGroup;
|
|
begin
|
|
if AItem is TdxLayoutGroup then
|
|
begin
|
|
AGroup := AItem as TdxLayoutGroup;
|
|
Result := AGroupIndexMap[AGroup.Hidden and not AGroup.IsRoot, AGroup.LayoutDirection];
|
|
end
|
|
else
|
|
if AItem is TdxLayoutEmptySpaceItem then
|
|
Result := 6
|
|
else
|
|
if AItem is TdxLayoutLabeledItem then
|
|
Result := 1
|
|
else
|
|
if AItem is TdxLayoutSeparatorItem then
|
|
Result := ASeparatorIndexMap[(AItem as TdxLayoutSeparatorItem).IsVertical]
|
|
else
|
|
if AItem is TdxLayoutSplitterItem then
|
|
Result := ASplitterIndexMap[(AItem as TdxLayoutSplitterItem).IsVertical]
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.GetIsLocked: Boolean;
|
|
begin
|
|
Result := (LockCount > 0) or TdxCustomLayoutControlAccess(Control).IsUpdateLocked;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.InitializePopupMenu;
|
|
var
|
|
I: Integer;
|
|
AMenuItem: TMenuItem;
|
|
begin
|
|
for I := 0 to pmAlign.Items.Count - 1 do
|
|
begin
|
|
AMenuItem := TMenuItem.Create(miAlignBy);
|
|
AMenuItem.Caption := pmAlign.Items[I].Caption;
|
|
AMenuItem.Action := pmAlign.Items[I].Action;
|
|
miAlignBy.Add(AMenuItem);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.ItemsWndProc(var Message: TMessage);
|
|
begin
|
|
if not TreeViewWndProcHandler(tvItems.InnerTreeView, Message) then
|
|
begin
|
|
case Message.Msg of
|
|
WM_DESTROY:
|
|
begin
|
|
RestoreTreeViewWndProc(tvItems.InnerTreeView, FItemsWndProc);
|
|
tvItems.InnerTreeView.WindowProc(Message);
|
|
end;
|
|
else
|
|
FItemsWndProc(Message);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RefreshImages;
|
|
begin
|
|
cxTransformImages(ilItems, ilHelper, clWindow, False);
|
|
if not IsXPManifestEnabled then
|
|
cxTransformImages(ilItems, clWindow);
|
|
ilItems.AddImages(ilHelper);
|
|
ilHelper.Clear;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RefreshLists(ARefreshSelection: Boolean = False);
|
|
begin
|
|
if IsLocked then
|
|
Exit;
|
|
BeginUpdate;
|
|
try
|
|
StoreCollapsedNodes;
|
|
RefreshAvailableItems;
|
|
RefreshTreeView;
|
|
RestoreCollapsedNodes;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
if ARefreshSelection then
|
|
UpdateSelection;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RefreshNode(ANode: TTreeNode);
|
|
var
|
|
AItem: TdxCustomLayoutItem;
|
|
begin
|
|
AItem := ANode.Data;
|
|
if AItem.IsRoot then
|
|
ANode.Text := cxGetResourceString(@sdxLayoutControlRoot)
|
|
else
|
|
ANode.Text := AItem.CaptionForCustomizeForm;
|
|
ANode.ImageIndex := GetImageIndex(AItem);
|
|
ANode.SelectedIndex := ANode.ImageIndex;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RefreshButtonStates;
|
|
begin
|
|
acAvailableItemsViewAsList.Checked := Control.CustomizeAvailableItemsViewKind = aivkTree;
|
|
acTabbedView.Checked := Control.CustomizeFormTabbedView;
|
|
acHighlightRoot.Checked := Control.HighlightRoot;
|
|
acShowDesignSelectors.Checked := Control.ShowDesignSelectors;
|
|
|
|
RefreshEnableds;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RefreshView;
|
|
const
|
|
MainGroupDirectionMap: array[Boolean] of TdxLayoutDirection = (ldHorizontal, ldTabbed);
|
|
begin
|
|
lcMainGroup1.LayoutDirection := MainGroupDirectionMap[Control.CustomizeFormTabbedView];
|
|
acShowDesignSelectors.Visible := Control.IsDesigning;
|
|
liShowDesignSelectors.Visible := acShowDesignSelectors.Visible;
|
|
acHighlightRoot.Visible := Control.IsDesigning;
|
|
liHighlightRoot.Visible := acHighlightRoot.Visible;
|
|
acStore.Visible := not Control.IsDesigning;
|
|
liStore.Visible := acStore.Visible;
|
|
acRestore.Visible := not Control.IsDesigning;
|
|
liRestore.Visible := acRestore.Visible;
|
|
acUndo.Visible := not Control.IsDesigning;
|
|
liUndo.Visible := acUndo.Visible;
|
|
acRedo.Visible := not Control.IsDesigning;
|
|
liRedo.Visible := acRedo.Visible;
|
|
lsSeparator4.Visible := acRedo.Visible;
|
|
acAddItem.Visible := Control.IsDesigning;
|
|
liAddItem.Visible := acAddItem.Visible;
|
|
|
|
acAlignBy.Visible := Control.IsDesigning;
|
|
lsAlignBy.Visible := acAlignBy.Visible;
|
|
liAlignBy.Visible := acAlignBy.Visible;
|
|
|
|
lcMain.LayoutLookAndFeel := TdxCustomLayoutControlAccess(Control).GetLayoutLookAndFeel;
|
|
RefreshButtonStates;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.SaveToUndo;
|
|
begin
|
|
TdxCustomLayoutControlAccess(Control).SaveToUndo;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.SelectItem(AItem: TdxCustomLayoutItem);
|
|
var
|
|
AIntf: IdxLayoutDesignerHelper;
|
|
begin
|
|
if Supports(Control, IdxLayoutDesignerHelper, AIntf) then
|
|
begin
|
|
if AItem <> nil then
|
|
AIntf.SelectComponent(AItem)
|
|
else
|
|
AIntf.SelectComponent(Control);
|
|
AIntf := nil;
|
|
end;
|
|
RefreshEnableds;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.SetItemsSelections(AList: TList);
|
|
|
|
procedure SetTreeViewAsActiveControl(ATreeView: TcxTreeView);
|
|
begin
|
|
if ATreeView.Visible then
|
|
ActiveControl := ATreeView.InnerTreeView
|
|
else
|
|
ActiveControl := nil;
|
|
end;
|
|
|
|
var
|
|
AItem: TdxCustomLayoutItemAccess;
|
|
begin
|
|
if IsLocked then
|
|
Exit;
|
|
BeginUpdate;
|
|
try
|
|
cxTreeViewSyncSelection(tvItems.InnerTreeView, AList);
|
|
cxTreeViewSyncSelection(tvAvailableItems.InnerTreeView, AList);
|
|
if (AList.Count > 0) and (TObject(AList.Last) is TdxCustomLayoutItem) then
|
|
begin
|
|
AItem := TdxCustomLayoutItemAccess(AList.Last);
|
|
if AItem.IsAvailable then
|
|
SetTreeViewAsActiveControl(tvAvailableItems)
|
|
else
|
|
SetTreeViewAsActiveControl(tvItems);
|
|
end;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
RefreshEnableds;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.SetLayoutItemsSelections(ATreeView: TTreeView);
|
|
var
|
|
AList: TList;
|
|
AIntf: IdxLayoutDesignerHelper;
|
|
begin
|
|
AList := TList.Create;
|
|
try
|
|
cxTreeViewGetSelection(ATreeView, AList);
|
|
if Supports(Control, IdxLayoutDesignerHelper, AIntf) then
|
|
begin
|
|
AIntf.SetSelection(AList);
|
|
AIntf := nil;
|
|
end;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
function TdxLayoutControlCustomizeForm.TreeViewWndProcHandler(ATreeView: TTreeView; var Message: TMessage): Boolean;
|
|
|
|
procedure ShowContextMenu;
|
|
var
|
|
AHitTest: THitTests;
|
|
begin
|
|
AHitTest := ATreeView.GetHitTestInfoAt(Message.LParamLo, Message.LParamHi);
|
|
if (htOnItem in AHitTest) then
|
|
ATreeView.Perform(WM_CONTEXTMENU, ATreeView.Handle, Integer(PointToSmallPoint(GetMouseCursorPos)));
|
|
end;
|
|
|
|
var
|
|
ANode: TTreeNode;
|
|
AShift: TShiftState;
|
|
begin
|
|
Result := False;
|
|
case Message.Msg of
|
|
CN_NOTIFY:
|
|
case TWMNotify(Message).NMHdr^.code of
|
|
NM_RCLICK:
|
|
begin
|
|
ShowContextMenu;
|
|
Message.Result := 1;
|
|
Result := True;
|
|
end;
|
|
end;
|
|
WM_RBUTTONDOWN:
|
|
begin
|
|
if ATreeView.Selected <> nil then
|
|
ATreeView.Selected.EndEdit(False);
|
|
ANode := ATreeView.GetNodeAt(Message.LParamLo, Message.LParamHi);
|
|
if ANode <> nil then
|
|
begin
|
|
ANode.Focused := True;
|
|
AShift := KeysToShiftState(Message.WParam);
|
|
if not ANode.Selected then
|
|
begin
|
|
if [ssShift, ssCtrl] * AShift <> [] then
|
|
AShift := [];
|
|
BeginUpdate;
|
|
try
|
|
ATreeView.Select(ANode, AShift);
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
SetLayoutItemsSelections(ATreeView);
|
|
end;
|
|
end;
|
|
Message.Result := 1;
|
|
Result := True;
|
|
end;
|
|
WM_LBUTTONDOWN:
|
|
begin
|
|
ANode := ATreeView.GetNodeAt(Message.LParamLo, Message.LParamHi);
|
|
if (ANode <> nil) and (ATreeView.SelectionCount > 1) then
|
|
begin
|
|
ANode.Focused := True;
|
|
AShift := KeysToShiftState(Message.WParam);
|
|
if ANode.Selected and ([ssCtrl, ssShift] * AShift = []) then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
ATreeView.ClearSelection;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.RestoreCollapsedNodes;
|
|
var
|
|
I: Integer;
|
|
ANode: TTreeNode;
|
|
begin
|
|
Dec(FCollapsedItemsStoredCount);
|
|
if FCollapsedItemsStoredCount = 0 then
|
|
begin
|
|
tvItems.FullExpand;
|
|
tvAvailableItems.FullExpand;
|
|
for I := 0 to FCollapsedItems.Count - 1 do
|
|
if GetNode(FCollapsedItems[I] as TdxCustomLayoutItem, ANode) then
|
|
ANode.Expanded := False;
|
|
FCollapsedItems.Clear;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.StoreCollapsedNodes;
|
|
|
|
procedure CheckNode(ANode: TTreeNode);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ANode.HasChildren then
|
|
begin
|
|
if not ANode.Expanded then
|
|
FCollapsedItems.Add(TComponent(ANode.Data));
|
|
for I := 0 to ANode.Count - 1 do
|
|
CheckNode(ANode[I]);
|
|
end;
|
|
end;
|
|
|
|
procedure CheckTreeView(ATreeView: TTreeView);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to ATreeView.Items.Count - 1 do
|
|
CheckNode(ATreeView.Items[I]);
|
|
end;
|
|
|
|
begin
|
|
Inc(FCollapsedItemsStoredCount);
|
|
if FCollapsedItemsStoredCount > 1 then
|
|
Exit;
|
|
FCollapsedItems.Clear;
|
|
CheckTreeView(tvAvailableItems.InnerTreeView);
|
|
CheckTreeView(tvItems.InnerTreeView);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acCloseExecute(Sender: TObject);
|
|
begin
|
|
Close;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAddGroupExecute(Sender: TObject);
|
|
begin
|
|
CreateItem(TdxCustomLayoutControlAccess(Control).GetDefaultGroupClass, cxGetResourceString(@sdxLayoutControlNewGroupCaption));
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAddItemExecute(Sender: TObject);
|
|
begin
|
|
CreateItem(TdxCustomLayoutControlAccess(Control).GetDefaultItemClass, cxGetResourceString(@sdxLayoutControlNewItemCaption));
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAddEmptySpaceItemExecute(Sender: TObject);
|
|
var
|
|
AItem: TdxCustomLayoutItem;
|
|
begin
|
|
AItem := CreateItem(TdxLayoutEmptySpaceItem, cxGetResourceString(@sdxLayoutControlNewEmptySpaceItemCaption));
|
|
AItem.Width := 10;
|
|
AItem.Height := 10;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAddSeparatorExecute(Sender: TObject);
|
|
begin
|
|
CreateItem(TdxLayoutSeparatorItem, cxGetResourceString(@sdxLayoutControlNewSeparatorItemCaption));
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAddCustomItemExecute(
|
|
Sender: TObject);
|
|
begin
|
|
//
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAddLabeledItemExecute(
|
|
Sender: TObject);
|
|
begin
|
|
CreateItem(TdxLayoutLabeledItem, cxGetResourceString(@sdxLayoutControlNewLabeledItemCaption));
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAddSplitterExecute(
|
|
Sender: TObject);
|
|
var
|
|
AItem: TdxCustomLayoutItem;
|
|
begin
|
|
SaveToUndo;
|
|
AItem := Control.CreateItem(TdxLayoutSplitterItem);
|
|
AItem.Caption := cxGetResourceString(@sdxLayoutControlNewSplitterItemCaption);
|
|
DoAfterInsertionItem(AItem);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvItemsEdited(Sender: TObject; Node: TTreeNode;
|
|
var S: String);
|
|
begin
|
|
if TdxCustomLayoutItem(Node.Data).IsRoot then
|
|
Exit;
|
|
SaveToUndo;
|
|
RefreshButtonStates;
|
|
BeginUpdate;
|
|
try
|
|
if Control.IsDesigning then
|
|
TdxCustomLayoutItem(Node.Data).Name := S
|
|
else
|
|
TdxCustomLayoutItem(Node.Data).Caption := S;
|
|
Node.Text := TdxCustomLayoutItem(Node.Data).CaptionForCustomizeForm;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvItemsMouseDown(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
ANode: TTreeNode;
|
|
ATreeView: TcxTreeView;
|
|
AHitTests: THitTests;
|
|
begin
|
|
ATreeView := TcxTreeView(Sender);
|
|
AHitTests := ATreeView.GetHitTestInfoAt(X, Y);
|
|
if htOnItem in AHitTests then
|
|
begin
|
|
ANode := ATreeView.GetNodeAt(X, Y);
|
|
if ANode = nil then
|
|
Exit;
|
|
if (Button = mbLeft) and ANode.Selected and (ANode = ATreeView.Selected) then
|
|
DragHelper.InitializeDragItem(ATreeView.Selected.Data, X, Y);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.ItemsMouseMove(Sender: TObject; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
var
|
|
ASource: TdxLayoutDragSource;
|
|
begin
|
|
if Sender = tvItems then
|
|
ASource := dsCustomizeFormTreeViewItems
|
|
else
|
|
ASource := dsCustomizeFormAvailableItems;
|
|
if ssLeft in Shift then
|
|
DragHelper.TryBeginDragAndDrop(X, Y, ASource);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.ItemsMouseUp(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if Button = mbLeft then
|
|
DragHelper.Reset;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvItemsChange(Sender: TObject; Node: TTreeNode);
|
|
begin
|
|
if not IsLocked then
|
|
SetLayoutItemsSelections(Sender as TTreeView);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvItemsChanging(Sender: TObject; Node: TTreeNode;
|
|
var AllowChange: Boolean);
|
|
begin
|
|
AllowChange := (Node = nil) or (Node.Data <> nil);
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.AlignExecute(Sender: TObject);
|
|
var
|
|
AList: TList;
|
|
I: Integer;
|
|
ATag: Integer;
|
|
AIntf: IdxLayoutDesignerHelper;
|
|
begin
|
|
//todo: TdxLayoutControlAccess(Control).SaveToUndo;
|
|
ATag := (Sender as TAction).Tag;
|
|
AList := TList.Create;
|
|
try
|
|
if Supports(Control, IdxLayoutDesignerHelper, AIntf) then
|
|
begin
|
|
AIntf.GetSelection(AList);
|
|
AIntf := nil;
|
|
end;
|
|
BeginUpdate;
|
|
try
|
|
Control.BeginUpdate;
|
|
try
|
|
if ATag = -1 then
|
|
for I := 0 to AList.Count - 1 do
|
|
TdxCustomLayoutItem(AList[I]).AlignmentConstraint := nil
|
|
else
|
|
with Control.CreateAlignmentConstraint do
|
|
begin
|
|
Kind := TdxLayoutAlignmentConstraintKind(ATag);
|
|
for I := 0 to AList.Count - 1 do
|
|
AddItem(TdxCustomLayoutItem(AList[I]));
|
|
end;
|
|
finally
|
|
Control.EndUpdate;
|
|
end;
|
|
finally
|
|
CancelUpdate;
|
|
end;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acTreeViewItemsDeleteExecute(Sender: TObject);
|
|
var
|
|
AList: TComponentList;
|
|
begin
|
|
if tvItems.IsEditing then
|
|
tvItems.Selected.EndEdit(True);
|
|
AList := TComponentList.Create;
|
|
try
|
|
cxTreeViewGetSelection(tvItems.InnerTreeView, AList);
|
|
DeleteItems(AList, tvItems.InnerTreeView);
|
|
RefreshTreeView;
|
|
UpdateSelection;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.FormClose(Sender: TObject;
|
|
var Action: TCloseAction);
|
|
begin
|
|
cxDialogsMetricsStore.StoreMetrics(Self);
|
|
Action := caFree;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvItemsContextPopup(
|
|
Sender: TObject; MousePos: TPoint; var Handled: Boolean);
|
|
begin
|
|
acAvailableItemsDelete.Enabled := False;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAvailableItemsDeleteExecute(
|
|
Sender: TObject);
|
|
var
|
|
AList: TComponentList;
|
|
begin
|
|
AList := TComponentList.Create;
|
|
try
|
|
cxTreeViewGetSelection(tvAvailableItems.InnerTreeView, AList);
|
|
DeleteItems(AList, tvAvailableItems.InnerTreeView);
|
|
RefreshAvailableItems;
|
|
UpdateSelection;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvItemsCustomDrawItem(
|
|
Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
|
|
var DefaultDraw: Boolean);
|
|
function IsDestination(AItem: TdxCustomLayoutItem): Boolean;
|
|
begin
|
|
Result := (dxLayoutDragAndDropObject <> nil) and (TdxLayoutDragAndDropObjectAccess(dxLayoutDragAndDropObject).DestinationItem = AItem);
|
|
end;
|
|
|
|
begin
|
|
if Node.Deleting then
|
|
Exit;
|
|
if (TObject(Node.Data) is TdxLayoutGroup) and TdxLayoutGroup(Node.Data).Hidden and
|
|
not TdxLayoutGroup(Node.Data).IsRoot then
|
|
Sender.Canvas.Font.Style := [fsItalic];
|
|
if IsDestination(Node.Data) then
|
|
begin
|
|
Sender.Canvas.Font.Color := clHighlightText;
|
|
Sender.Canvas.Brush.Color := clHighlight;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvAvailableItemsContextPopup(
|
|
Sender: TObject; MousePos: TPoint; var Handled: Boolean);
|
|
begin
|
|
acTreeViewItemsDelete.Enabled := False;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAvailableItemsExpandAllExecute(
|
|
Sender: TObject);
|
|
begin
|
|
tvAvailableItems.FullExpand;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAvailableItemsCollapseAllExecute(
|
|
Sender: TObject);
|
|
begin
|
|
tvAvailableItems.FullCollapse;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acTreeViewExpandAllExecute(
|
|
Sender: TObject);
|
|
begin
|
|
tvItems.FullExpand;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acTreeViewCollapseAllExecute(
|
|
Sender: TObject);
|
|
begin
|
|
tvItems.FullCollapse;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAvailableItemsViewAsListExecute(
|
|
Sender: TObject);
|
|
const
|
|
AViewKindMap: array [Boolean] of TdxLayoutAvailableItemsViewKind = (aivkList, aivkTree);
|
|
begin
|
|
Control.CustomizeAvailableItemsViewKind := AViewKindMap[acAvailableItemsViewAsList.Checked];
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvItemsEditing(Sender: TObject;
|
|
Node: TTreeNode; var AllowEdit: Boolean);
|
|
|
|
function IsKeyDown(AShift: TShiftState): Boolean;
|
|
begin
|
|
Result := (AShift * KeyboardStateToShiftState) <> [];
|
|
end;
|
|
|
|
begin
|
|
AllowEdit := not (TdxCustomLayoutItem(Node.Data).IsRoot or (DragHelper.DragItem <> nil) or
|
|
IsKeyDown([ssCtrl, ssShift]) or TdxCustomLayoutItemAccess(Node.Data).IsParentLocked);
|
|
if not AllowEdit or Control.IsDesigning then
|
|
Exit;
|
|
RefreshEnableds;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.FormShortCut(var Msg: TWMKey;
|
|
var Handled: Boolean);
|
|
begin
|
|
case Msg.CharCode of
|
|
VK_ESCAPE:
|
|
begin
|
|
Handled := tvItems.IsEditing or tvAvailableItems.IsEditing;
|
|
if Handled then
|
|
if tvItems.Selected <> nil then
|
|
tvItems.Selected.EndEdit(True)
|
|
else
|
|
if tvAvailableItems.Selected <> nil then
|
|
tvAvailableItems.Selected.EndEdit(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.FormKeyDown(Sender: TObject;
|
|
var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if Key = VK_DELETE then
|
|
begin
|
|
if tvItems.Focused and not tvItems.IsEditing then
|
|
acTreeViewItemsDelete.Execute;
|
|
if tvAvailableItems.Focused and not tvAvailableItems.IsEditing then
|
|
acAvailableItemsDelete.Execute;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acTabbedViewExecute(
|
|
Sender: TObject);
|
|
begin
|
|
Control.CustomizeFormTabbedView := acTabbedView.Checked;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acHighlightRootExecute(
|
|
Sender: TObject);
|
|
begin
|
|
Control.HighlightRoot := acHighlightRoot.Checked;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acShowDesignSelectorsExecute(
|
|
Sender: TObject);
|
|
begin
|
|
Control.ShowDesignSelectors := acShowDesignSelectors.Checked;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acStoreExecute(Sender: TObject);
|
|
begin
|
|
Control.Store;
|
|
RefreshEnableds;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acRestoreExecute(Sender: TObject);
|
|
begin
|
|
SaveToUndo;
|
|
Control.Restore;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acTreeViewItemRenameExecute(
|
|
Sender: TObject);
|
|
begin
|
|
tvItems.Selected.EditText;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAvailableItemRenameExecute(
|
|
Sender: TObject);
|
|
begin
|
|
tvAvailableItems.Selected.EditText;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acUndoExecute(Sender: TObject);
|
|
begin
|
|
Control.UndoRedoManager.Undo;
|
|
RefreshButtonStates;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acRedoExecute(Sender: TObject);
|
|
begin
|
|
Control.UndoRedoManager.Redo;
|
|
RefreshButtonStates;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acAlignByExecute(Sender: TObject);
|
|
begin
|
|
// for popup
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acHAlignExecute(Sender: TObject);
|
|
var
|
|
AList: TList;
|
|
I: Integer;
|
|
begin
|
|
if tvItems.IsEditing then
|
|
Exit;
|
|
SaveToUndo;
|
|
AList := TList.Create;
|
|
try
|
|
cxTreeViewGetSelection(tvItems.InnerTreeView, AList);
|
|
for I := 0 to AList.Count - 1 do
|
|
TdxCustomLayoutItem(AList[I]).AlignHorz := TdxLayoutAlignHorz((Sender as TAction).Tag);
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.pmTreeViewActionsPopup(
|
|
Sender: TObject);
|
|
|
|
procedure ResetSubMenu(AMenu: TMenuItem);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to AMenu.Count - 1 do
|
|
TAction(AMenu.Items[I].Action).Checked := False;
|
|
end;
|
|
|
|
function IsContainGroupInSelections: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to tvItems.SelectionCount - 1 do
|
|
begin
|
|
Result := TObject(tvItems.Selections[I].Data) is TdxLayoutGroup;
|
|
if Result then
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
function IsContainLockedItemInSelections: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to tvItems.SelectionCount - 1 do
|
|
begin
|
|
Result := TdxCustomLayoutItemAccess(tvItems.Selections[I].Data).IsParentLocked;
|
|
if Result then
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AItem: TdxCustomLayoutItem;
|
|
AHitTest: TdxCustomLayoutHitTest;
|
|
APopupForTree: Boolean;
|
|
AIsContainLockedItem: Boolean;
|
|
AIsContainGroup: Boolean;
|
|
begin
|
|
AHitTest := Control.GetHitTest(Control.ScreenToClient(GetMouseCursorPos));
|
|
APopupForTree := AHitTest.HitTestCode = htTreeViewItems;
|
|
miTreeViewItemRename.Visible := APopupForTree;
|
|
miExpandAll.Visible := APopupForTree;
|
|
miCallapseAll.Visible := APopupForTree;
|
|
miSeparator1.Visible := APopupForTree;
|
|
|
|
AIsContainLockedItem := IsContainLockedItemInSelections;
|
|
AIsContainGroup := IsContainGroupInSelections;
|
|
|
|
miDirection.Visible := AIsContainGroup;
|
|
miShowBorder.Visible := AIsContainGroup;
|
|
|
|
miDirection.Enabled := not AIsContainLockedItem;
|
|
miAlignHorz.Enabled := not AIsContainLockedItem;
|
|
miAlignVert.Enabled := not AIsContainLockedItem;
|
|
|
|
if tvItems.SelectionCount = 1 then
|
|
begin
|
|
AItem := TdxCustomLayoutItem(tvItems.Selected.Data);
|
|
TAction(miAlignHorz.Items[Integer(AItem.AlignHorz)].Action).Checked := True;
|
|
TAction(miAlignVert.Items[Integer(AItem.AlignVert)].Action).Checked := True;
|
|
if AItem is TdxLayoutGroup then
|
|
begin
|
|
TAction(miDirection.Items[Integer((AItem as TdxLayoutGroup).LayoutDirection)].Action).Checked := True;
|
|
acShowBorder.Checked := (AItem as TdxLayoutGroup).ShowBorder;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
ResetSubMenu(miAlignHorz);
|
|
ResetSubMenu(miAlignVert);
|
|
ResetSubMenu(miDirection);
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acVAlignExecute(
|
|
Sender: TObject);
|
|
var
|
|
AList: TList;
|
|
I: Integer;
|
|
begin
|
|
if tvItems.IsEditing then
|
|
Exit;
|
|
SaveToUndo;
|
|
AList := TList.Create;
|
|
try
|
|
cxTreeViewGetSelection(tvItems.InnerTreeView, AList);
|
|
for I := 0 to AList.Count - 1 do
|
|
TdxCustomLayoutItem(AList[I]).AlignVert := TdxLayoutAlignVert((Sender as TAction).Tag);
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acDirectionsExecute(
|
|
Sender: TObject);
|
|
var
|
|
AList: TList;
|
|
I: Integer;
|
|
ANewDirection: TdxLayoutDirection;
|
|
begin
|
|
if tvItems.IsEditing then
|
|
Exit;
|
|
SaveToUndo;
|
|
AList := TList.Create;
|
|
try
|
|
cxTreeViewGetSelection(tvItems.InnerTreeView, AList);
|
|
ANewDirection := TdxLayoutDirection((Sender as TAction).Tag);
|
|
for I := 0 to AList.Count - 1 do
|
|
if TObject(AList[I]) is TdxLayoutGroup then
|
|
TdxLayoutGroup(AList[I]).LayoutDirection := ANewDirection;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
tvItems.Invalidate;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.acShowBorderExecute(
|
|
Sender: TObject);
|
|
var
|
|
AList: TList;
|
|
I: Integer;
|
|
begin
|
|
if tvItems.IsEditing then
|
|
Exit;
|
|
SaveToUndo;
|
|
acShowBorder.Checked := not acShowBorder.Checked;
|
|
AList := TList.Create;
|
|
try
|
|
cxTreeViewGetSelection(tvItems.InnerTreeView, AList);
|
|
for I := 0 to AList.Count - 1 do
|
|
if TObject(AList[I]) is TdxLayoutGroup then
|
|
TdxLayoutGroup(AList[I]).ShowBorder := (Sender as TAction).Checked;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TdxLayoutControlCustomizeForm.tvItemsDeletion(
|
|
Sender: TObject; Node: TTreeNode);
|
|
var
|
|
ANode: TTreeNode;
|
|
begin
|
|
(TObject(Node.Data) as TdxCustomLayoutItem).RemoveFreeNotification(Self);
|
|
if Node = Node.TreeView.Selected then
|
|
begin
|
|
ANode := Node.GetNext;
|
|
if ANode = nil then
|
|
ANode := Node.GetPrev;
|
|
if ANode <> nil then
|
|
if ANode <> nil then
|
|
begin
|
|
ANode.Selected := True;
|
|
SelectItem(ANode.Data);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|