Componentes.Terceros.DevExp.../official/x.48/ExpressLayout Control 2/Sources/dxLayoutCustomizeForm.pas

1964 lines
62 KiB
ObjectPascal
Raw Normal View History

{********************************************************************}
{ }
{ 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.