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

1392 lines
43 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;
type
TdxLayoutControlCustomizeFormClass = class of TdxLayoutControlCustomizeForm;
TdxLayoutControlCustomizeForm = class(TForm)
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;
tlbAvailableItems: TToolBar;
tbAddGroup: TToolButton;
tbAddItem: TToolButton;
tbListBoxItemDelete: TToolButton;
ToolButton1: TToolButton;
tbAlignBy: TToolButton;
tbTreeViewExpandAll: TToolButton;
tbTreeViewCollapseAll: TToolButton;
tbTreeViewItemDelete: TToolButton;
ToolButton5: TToolButton;
tvItems: TTreeView;
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;
btnClose: TButton;
lcMainGroup_Root: TdxLayoutGroup;
lcMain: TdxLayoutControl;
lcMainItem3: TdxLayoutItem;
lcMainItem4: TdxLayoutItem;
lcgTreeView: TdxLayoutGroup;
lcgAvailableItems: TdxLayoutGroup;
lcMainItem5: TdxLayoutItem;
lcMainItem6: TdxLayoutItem;
acAvailableItemsDelete: TAction;
tvAvailableItems: TTreeView;
lcMainItem1: TdxLayoutItem;
ToolButton2: TToolButton;
tbAvailableItemsExpandAll: TToolButton;
tbAvailableItemsCollapseAll: TToolButton;
ToolButton7: TToolButton;
tbAvailableItemsViewAsList: TToolButton;
acAvailableItemsExpandAll: TAction;
acAvailableItemsCollapseAll: TAction;
acAvailableItemsViewAsList: TAction;
tlbCustomize: TToolBar;
lcMainItem2: TdxLayoutItem;
ToolButton4: TToolButton;
acTabbedView: TAction;
acHighlightRoot: TAction;
lcMainGroup1: TdxLayoutGroup;
acShowDesignSelectors: TAction;
ToolButton6: TToolButton;
cbTabbedView: TCheckBox;
lcMainItem7: TdxLayoutItem;
lcMainGroup2: TdxLayoutGroup;
lcMainGroup3: TdxLayoutGroup;
ilToolBarActionsDisabled: TcxImageList;
ilToolBarActions: TcxImageList;
ToolButton3: TToolButton;
ToolButton8: TToolButton;
acStore: TAction;
acRestore: TAction;
tlbTreeView: TToolBar;
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);
private
FControl: TdxCustomLayoutControl;
FDragHelper: TdxLayoutDragAndDropHelper;
FLockCount: Integer;
FAvailableItemsWndProc: TWndMethod;
FItemsWndProc: TWndMethod;
procedure AddItemNode(ANodes: TTreeNodes; ANode: TTreeNode; AItem: TdxCustomLayoutItem;
const ACustomName: string = '');
procedure AvailableItemsWndProc(var Message: TMessage);
procedure DoAfterInsertionItem(AItem: TdxCustomLayoutItem);
function GetImageIndex(AItem: TdxCustomLayoutItem): Integer;
function GetIsLocked: Boolean;
function GetNextToSelectItem(ATreeView: TTreeView): TdxCustomLayoutItem;
procedure InitializePopupMenu;
procedure ItemsWndProc(var Message: TMessage);
procedure RefreshLists(ARefreshSelection: Boolean = False);
procedure RefreshButtonStates;
procedure RefreshView;
procedure SelectItem(AItem: TdxCustomLayoutItem);
procedure SetControl(AValue: TdxCustomLayoutControl);
procedure SetItemsSelections(AList: TList);
procedure SetLayoutItemsSelections(ATreeView: TTreeView);
function TreeViewWndProcHandler(ATreeView: TTreeView; var Message: TMessage): Boolean;
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure CalculateAddItemsActionStates;
procedure CalculateDeleteItemsActionStates;
function CanDeleteItems(ATreeView: TTreeView): Boolean;
procedure DeleteItems(AList: TComponentList; ASelectedItem: TdxCustomLayoutItem);
procedure InitializeControl;
procedure Localize; virtual;
function NeedRefreshItemsAfterDeleting(AComponent: TPersistent): Boolean;
procedure RefreshAvailableItems;
procedure RefreshEnableds;
procedure RefreshTreeView;
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; virtual;
// Updates
procedure BeginUpdate;
procedure CancelUpdate;
procedure EndUpdate;
procedure UpdateCaption;
procedure UpdateContent;
procedure UpdateSelection;
property Control: TdxCustomLayoutControl read FControl write SetControl;
end;
procedure cxTreeViewGetSelection(ATreeView: TTreeView; AList: TList);
procedure cxTreeViewSyncSelection(ATreeView: TTreeView; AList: TList);
procedure cxListViewGetSelection(AListView: TListView; AList: TList);
procedure cxListViewSyncSelection(AListView: TListView; AList: TList);
implementation
{$R *.DFM}
uses
Types, Math, CommCtrl, dxLayoutCommon, dxLayoutEditForm, cxGeometry,
dxLayoutStrs, dxCore, dxOffice11;
type
TdxLayoutControlAccess = class(TdxCustomLayoutControl);
TdxCustomLayoutItemAccess = class(TdxCustomLayoutItem);
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;
SplitNameByTrailingDigits(AName1, ANumber1, ANameWithoutLastDigitals1);
AName2 := TdxCustomLayoutItem(Item2).CaptionForCustomizeForm;
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;
procedure cxListViewGetSelection(AListView: TListView; AList: TList);
var
I: Integer;
begin
AList.Clear;
with AListView do
for I := 0 to Items.Count - 1 do
if (Items[I].Data <> nil) and Items[I].Selected then
AList.Add(Items[I].Data);
end;
procedure cxListViewSyncSelection(AListView: TListView; AList: TList);
var
I: Integer;
begin
with AListView do
begin
for I := 0 to AListView.Items.Count - 1 do
with Items[I] do
begin
Selected := AList.IndexOf(Items[I].Data) >= 0;
Focused := Focused or Selected;
end;
end;
end;
{ TdxLayoutDesignForm }
constructor TdxLayoutControlCustomizeForm.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
if not IsXPManifestEnabled then
begin
tlbCustomize.DisabledImages := ilToolBarActionsDisabled;
tlbAvailableItems.DisabledImages := ilToolBarActionsDisabled;
tlbTreeView.DisabledImages := ilToolBarActionsDisabled;
ilToolBarActions.Clear;
cxTransformImages(ilActions, ilToolBarActions, clBtnFace);
ilToolBarActionsDisabled.Clear;
cxTransformImages(ilActions, ilToolBarActionsDisabled, clBtnFace, False);
cxTransformImages(ilItems, clWindow);
end;
Localize;
InitializePopupMenu;
FItemsWndProc := tvItems.WindowProc;
tvItems.WindowProc := ItemsWndProc;
FAvailableItemsWndProc := tvAvailableItems.WindowProc;
tvAvailableItems.WindowProc := AvailableItemsWndProc;
end;
destructor TdxLayoutControlCustomizeForm.Destroy;
begin
Control.Customization := False;
FreeAndNil(FDragHelper);
tvItems.WindowProc := FItemsWndProc;
tvAvailableItems.WindowProc := FAvailableItemsWndProc;
inherited;
end;
function TdxLayoutControlCustomizeForm.GetHitTest(const P: TPoint): TdxCustomLayoutHitTest;
begin
if tvItems.Visible and PtInRect(tvItems.BoundsRect, P) then
Result := TdxLayoutCustomizeFormTreeViewItemsHitTest.Instance
else
if tvAvailableItems.Visible and PtInRect(tvAvailableItems.BoundsRect, P) then
Result := TdxLayoutCustomizeFormAvailableItemsHitTest.Instance
else
Result := TdxLayoutCustomizeFormHitTest.Instance
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.UpdateCaption;
begin
if Control.IsDesigning then
Caption := Format(cxGetResourceString(@sdxLayoutControlDesignerCaptionFormat), [cxGetFullComponentName(Control)])
else
Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormCaption);
end;
procedure TdxLayoutControlCustomizeForm.UpdateContent;
begin
RefreshLists;
RefreshButtonStates;
RefreshView;
if (FDragHelper.DragItem <> nil) and (Control.DragAndDropState = ddsNone) then
FDragHelper.Reset;
end;
procedure TdxLayoutControlCustomizeForm.UpdateSelection;
var
AList: TList;
begin
if IsLocked then
Exit;
AList := TList.Create;
try
(Control as IdxLayoutDesignerHelper).GetSelection(AList);
SetItemsSelections(AList);
finally
AList.Free;
end;
end;
procedure TdxLayoutControlCustomizeForm.CalculateAddItemsActionStates;
begin
acAddGroup.Enabled := True;
acAddItem.Enabled := Control.IsDesigning;
acAddItem.Visible := Control.IsDesigning;
end;
procedure TdxLayoutControlCustomizeForm.CalculateDeleteItemsActionStates;
begin
acTreeViewItemsDelete.Enabled := CanDeleteItems(tvItems);
acAvailableItemsDelete.Enabled := CanDeleteItems(tvAvailableItems);
end;
function TdxLayoutControlCustomizeForm.CanDeleteItems(ATreeView: TTreeView): Boolean;
var
AList: TList;
I: Integer;
begin
Result := not ATreeView.IsEditing;
if Result then
begin
AList := TList.Create;
try
cxTreeViewGetSelection(ATreeView, AList);
Result := AList.Count > 0;
if Result then
for I := 0 to AList.Count - 1 do
begin
Result := (Control as IdxLayoutDesignerHelper).CanDeleteComponent(TComponent(AList[I]));
if not Result then
Break;
end;
finally
AList.Free;
end;
end;
end;
procedure TdxLayoutControlCustomizeForm.DeleteItems(AList: TComponentList;
ASelectedItem: TdxCustomLayoutItem);
begin
if AList.Count = 0 then
Exit;
BeginUpdate;
try
SelectItem(ASelectedItem);
Control.BeginUpdate;
try
while AList.Count > 0 do
AList[0].Free;
finally
Control.EndUpdate;
end;
finally
CancelUpdate;
end;
RefreshLists(True);
end;
procedure TdxLayoutControlCustomizeForm.CreateParams(var Params: TCreateParams);
begin
inherited;
if Control <> nil then
Params.WndParent := Control.Handle;
end;
procedure TdxLayoutControlCustomizeForm.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = Control) then
Free;
end;
procedure TdxLayoutControlCustomizeForm.InitializeControl;
begin
UpdateCaption;
FDragHelper.Free;
FDragHelper := TdxLayoutDragAndDropHelper.Create(Control);
end;
procedure TdxLayoutControlCustomizeForm.Localize;
begin
acAddGroup.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddGroup);
acAddGroup.Hint := StripHotKey(acAddGroup.Caption);
acAddItem.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAddItem);
acAddItem.Hint := StripHotKey(acAddItem.Caption);
acAvailableItemsDelete.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormDelete);
acAvailableItemsDelete.Hint := cxGetResourceString(@sdxLayoutControlCustomizeFormDeleteHint);
acTreeViewItemsDelete.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormDelete);
acTreeViewItemsDelete.Hint := cxGetResourceString(@sdxLayoutControlCustomizeFormDeleteHint);
tbAlignBy.Caption := cxGetResourceString(@sdxLayoutControlCustomizeFormAlignBy);
tbAlignBy.Hint := StripHotKey(tbAlignBy.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);
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);
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 = oivkList then
PopulateItemChildren(AList, Control.AvailableItems[I]);
end;
end;
var
AList: TList;
I: Integer;
begin
with tvAvailableItems do
begin
Items.BeginUpdate;
try
Items.Clear;
AList := TList.Create;
try
PopulateItems(AList);
case Control.CustomizeAvailableItemsViewKind of
oivkList:
begin
AList.Sort(CompareItemsByName);
for I := 0 to AList.Count - 1 do
with Items.AddObject(Items.GetFirstNode,
TdxCustomLayoutItem(AList[I]).CaptionForCustomizeForm, AList[I]) do
begin
ImageIndex := GetImageIndex(AList[I]);
SelectedIndex := ImageIndex;
Selected := False;
Focused := False;
end;
end;
oivkTree:
begin
AList.Sort(CompareItems);
for I := 0 to AList.Count - 1 do
AddItemNode(Items, nil, TdxCustomLayoutItem(AList[I]));
end;
end;
finally
AList.Free;
end;
FullExpand;
finally
Items.EndUpdate;
end;
end;
tvAvailableItems.ShowRoot := Control.CustomizeAvailableItemsViewKind = oivkTree;
end;
procedure TdxLayoutControlCustomizeForm.RefreshEnableds;
begin
if not IsLocked then
begin
tbAlignBy.Enabled := (tvItems.SelectionCount > 1);
miAlignBy.Enabled := tbAlignBy.Enabled;
acAvailableItemsExpandAll.Enabled := Control.CustomizeAvailableItemsViewKind = oivkTree;
acAvailableItemsCollapseAll.Enabled := Control.CustomizeAvailableItemsViewKind = oivkTree;
acRestore.Enabled := Control.CanRestore;
CalculateAddItemsActionStates;
CalculateDeleteItemsActionStates;
end;
end;
procedure TdxLayoutControlCustomizeForm.RefreshTreeView;
begin
with tvItems do
begin
Items.BeginUpdate;
try
Items.Clear;
AddItemNode(Items, Items.GetFirstNode, Control.Items, cxGetResourceString(@sdxLayoutControlRoot));
FullExpand;
finally
Items.EndUpdate;
end;
end;
end;
procedure TdxLayoutControlCustomizeForm.AddItemNode(ANodes: TTreeNodes; ANode: TTreeNode; AItem: TdxCustomLayoutItem;
const ACustomName: string = '');
var
AName: string;
I: Integer;
AThisNode: TTreeNode;
AGroup: TdxLayoutGroup;
begin
if ACustomName = '' then
AName := AItem.CaptionForCustomizeForm
else
AName := ACustomName;
if ANode = nil then
AThisNode := ANodes.AddObject(ANodes.GetFirstNode, AName, AItem)
else
AThisNode := ANodes.AddChildObject(ANode, AName, AItem);
if AItem is TdxLayoutGroup then
begin
AGroup := TdxLayoutGroup(AItem);
for I := 0 to AGroup.Count - 1 do
AddItemNode(ANodes, AThisNode, AGroup[I]);
end;
AThisNode.ImageIndex := GetImageIndex(AItem);
AThisNode.SelectedIndex := AThisNode.ImageIndex;
AThisNode.Selected := False;
AThisNode.Focused := False;
end;
procedure TdxLayoutControlCustomizeForm.AvailableItemsWndProc(var Message: TMessage);
begin
if not TreeViewWndProcHandler(tvAvailableItems, Message) then
FAvailableItemsWndProc(Message);
end;
procedure TdxLayoutControlCustomizeForm.DoAfterInsertionItem(AItem: TdxCustomLayoutItem);
begin
(Control as IdxLayoutDesignerHelper).SelectComponent(AItem);
end;
function TdxLayoutControlCustomizeForm.GetImageIndex(AItem: TdxCustomLayoutItem): Integer;
var
AGroup: TdxLayoutGroup;
begin
if AItem is TdxLayoutGroup then
begin
Result := 1;
AGroup := AItem as TdxLayoutGroup;
if AGroup.Hidden and not AGroup.IsRoot then
Inc(Result);
end
else
Result := 0;
end;
function TdxLayoutControlCustomizeForm.GetIsLocked: Boolean;
begin
Result := (LockCount > 0) or TdxLayoutControlAccess(Control).IsUpdateLocked;
end;
function TdxLayoutControlCustomizeForm.GetNextToSelectItem(ATreeView: TTreeView): TdxCustomLayoutItem;
var
ANode: TTreeNode;
begin
Result := nil;
ANode := ATreeView.FindNextToSelect;
if ANode <> nil then
Result := TdxCustomLayoutItem(ANode.Data)
else
begin
ANode := ATreeView.Selected;
while (ANode <> nil) and ANode.Selected do
ANode := ANode.GetPrev;
if ANode <> nil then
Result := TdxCustomLayoutItem(ANode.Data);
end;
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, Message) then
FItemsWndProc(Message);
end;
procedure TdxLayoutControlCustomizeForm.RefreshLists(ARefreshSelection: Boolean = False);
begin
if IsLocked then
Exit;
BeginUpdate;
try
RefreshAvailableItems;
RefreshTreeView;
finally
CancelUpdate;
end;
if ARefreshSelection then
UpdateSelection;
end;
procedure TdxLayoutControlCustomizeForm.RefreshButtonStates;
begin
acAvailableItemsViewAsList.Checked := Control.CustomizeAvailableItemsViewKind = oivkTree;
acTabbedView.Checked := Control.CustomizeFormTabbedView;
acHighlightRoot.Checked := Control.HighlightRoot;
acShowDesignSelectors.Checked := Control.ShowDesignSelectors;
RefreshEnableds;
end;
procedure TdxLayoutControlCustomizeForm.RefreshView;
begin
if Control.CustomizeFormTabbedView then
lcMainGroup1.LayoutDirection := ldTabbed
else
lcMainGroup1.LayoutDirection := ldHorizontal;
acShowDesignSelectors.Visible := Control.IsDesigning;
acHighlightRoot.Visible := Control.IsDesigning;
acStore.Visible := not Control.IsDesigning;
acRestore.Visible := not Control.IsDesigning;
end;
procedure TdxLayoutControlCustomizeForm.SelectItem(AItem: TdxCustomLayoutItem);
begin
if AItem <> nil then
(Control as IdxLayoutDesignerHelper).SelectComponent(AItem)
else
(Control as IdxLayoutDesignerHelper).SelectComponent(Control);
RefreshEnableds;
end;
procedure TdxLayoutControlCustomizeForm.SetControl(AValue: TdxCustomLayoutControl);
procedure StoreMetrics;
begin
cxDialogsMetricsStore.StoreMetrics(Self);
end;
procedure RestoreMetrics;
begin
if Control <> nil then
if EqualRect(Control.CustomizeFormBounds, cxNullRect) then
BoundsRect := TdxLayoutControlAccess(Control).CalculateCustomizeFormBounds(BoundsRect)
else
BoundsRect := Control.CustomizeFormBounds;
cxDialogsMetricsStore.InitDialog(Self);
Position := poDesigned;
end;
begin
if Control <> AValue then
begin
if Control <> nil then
begin
StoreMetrics;
Control.RemoveFreeNotification(Self);
end;
FControl := AValue;
if Control <> nil then
begin
Control.FreeNotification(Self);
RestoreMetrics;
end;
RecreateWnd;
end;
InitializeControl;
end;
procedure TdxLayoutControlCustomizeForm.SetItemsSelections(AList: TList);
procedure SetTreeViewAsActiveControl(ATreeView: TTreeView);
begin
if ATreeView.Visible then
ActiveControl := ATreeView
else
ActiveControl := nil;
end;
var
AItem: TdxCustomLayoutItemAccess;
begin
if IsLocked then
Exit;
BeginUpdate;
try
cxTreeViewSyncSelection(tvItems, AList);
cxTreeViewSyncSelection(tvAvailableItems, 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;
begin
AList := TList.Create;
try
cxTreeViewGetSelection(ATreeView, AList);
(Control as IdxLayoutDesignerHelper).SetSelection(AList);
finally
AList.Free;
end;
end;
function TdxLayoutControlCustomizeForm.TreeViewWndProcHandler(ATreeView: TTreeView; var Message: TMessage): Boolean;
var
ANode: TTreeNode;
AHitTest : THitTests;
AShift: TShiftState;
begin
Result := False;
case Message.Msg of
CN_NOTIFY:
case TWMNotify(Message).NMHdr^.code of
NM_RCLICK:
begin
AHitTest := ATreeView.GetHitTestInfoAt(Message.LParamLo, Message.LParamHi);
if (htOnItem in AHitTest) then
tvItems.Perform(WM_CONTEXTMENU, ATreeView.Handle, Integer(PointToSmallPoint(GetMouseCursorPos)));
Message.Result := 1;
Result := True;
end;
end;
WM_RBUTTONDOWN:
begin
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.acCloseExecute(Sender: TObject);
begin
Close;
end;
procedure TdxLayoutControlCustomizeForm.acAddGroupExecute(Sender: TObject);
var
AGroup: TdxLayoutGroup;
begin
Control.BeginUpdate;
try
AGroup := Control.CreateGroup;
AGroup.Caption := cxGetResourceString(@sdxLayoutControlNewGroupCaption);
finally
Control.EndUpdate;
end;
DoAfterInsertionItem(AGroup);
end;
procedure TdxLayoutControlCustomizeForm.acAddItemExecute(Sender: TObject);
var
AItem: TdxCustomLayoutItem;
begin
Control.BeginUpdate;
try
AItem := Control.CreateItem;
AItem.Caption := cxGetResourceString(@sdxLayoutControlNewItemCaption);
finally
Control.EndUpdate;
end;
DoAfterInsertionItem(AItem);
end;
procedure TdxLayoutControlCustomizeForm.tvItemsEdited(Sender: TObject; Node: TTreeNode;
var S: String);
begin
if TdxCustomLayoutItem(Node.Data).IsRoot then
Exit;
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: TTreeView;
AHitTests: THitTests;
begin
ATreeView := TTreeView(Sender);
AHitTests := ATreeView.GetHitTestInfoAt(X, Y);
if htOnItem in AHitTests then
begin
ANode := ATreeView.GetNodeAt(X, Y);
if ANode = nil then
Exit;
ANode.Selected := True;
if (Button = mbLeft) and ANode.Selected and (ANode = ATreeView.Selected) then
DragHelper.InitializeDragItem(ATreeView.Selected.Data, X, Y);
if (Button = mbRight) or (ssCtrl in Shift) then
SetLayoutItemsSelections(ATreeView);
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(TTreeView(Sender));
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;
begin
ATag := (Sender as TAction).Tag;
AList := TList.Create;
try
(Control as IdxLayoutDesignerHelper).GetSelection(AList);
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);
procedure CheckSelectedParent(ANode: TTreeNode);
var
AParentNode: TTreeNode;
AItem: TdxCustomLayoutItem;
ANotSelectedChildCount: Integer;
I: Integer;
begin
AParentNode := ANode.Parent;
if AParentNode = nil then
Exit;
AItem := TdxCustomLayoutItem(AParentNode.Data);
if not AParentNode.Selected and not AItem.IsRoot and (AItem is TdxLayoutGroup)
and TdxLayoutGroup(AItem).Hidden then
begin
ANotSelectedChildCount := AParentNode.Count;
for I := 0 to AParentNode.Count - 1 do
if AParentNode[I].Selected then
Dec(ANotSelectedChildCount);
if ANotSelectedChildCount < 2 then
tvItems.Select(AParentNode, [ssCtrl]);
end;
end;
procedure SelectChildren(ANode: TTreeNode);
var
I: Integer;
begin
if ANode.Count > 0 then
for I := 0 to ANode.Count - 1 do
begin
tvItems.Select(ANode[I], [ssCtrl]);
SelectChildren(ANode[I]);
end
end;
procedure CheckNeighbors(ANode: TTreeNode);
var
I: Integer;
AParentNode: TTreeNode;
ANeighborsSelectedCount: Integer;
begin
if (ANode.Parent = nil) or (ANode.Parent.Count = 0) then
Exit;
AParentNode := ANode.Parent;
ANeighborsSelectedCount := 0;
for I := 0 to AParentNode.Count - 1 do
if AParentNode[I].Selected then
Inc(ANeighborsSelectedCount);
if AParentNode.Count - ANeighborsSelectedCount = 1 then
for I := 0 to AParentNode.Count - 1 do
if not AParentNode[I].Selected and (TObject(AParentNode[I].Data) is TdxLayoutGroup) and
TdxLayoutGroup(AParentNode[I].Data).Hidden then
tvItems.Select(AParentNode[I], [ssCtrl]);
end;
procedure AdjustSelectionForDeletion;
var
I: Integer;
AList: TList;
ASaveSelectedNode: TTreeNode;
begin
BeginUpdate;
try
AList := TList.Create;
try
ASaveSelectedNode := tvItems.GetSelections(AList);
for I := 0 to AList.Count - 1 do
begin
SelectChildren(AList[I]);
CheckNeighbors(AList[I]);
CheckSelectedParent(AList[I]);
end;
with ASaveSelectedNode do
TreeView_SelectItem(Handle, ItemId);
finally
AList.Free;
end;
finally
CancelUpdate;
end;
end;
var
AList: TComponentList;
begin
if tvItems.IsEditing then
Exit;
AList := TComponentList.Create;
try
cxTreeViewGetSelection(tvItems, AList);
AdjustSelectionForDeletion;
DeleteItems(AList, GetNextToSelectItem(tvItems));
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
CalculateDeleteItemsActionStates;
acAvailableItemsDelete.Enabled := False;
end;
procedure TdxLayoutControlCustomizeForm.acAvailableItemsDeleteExecute(
Sender: TObject);
var
AList: TComponentList;
begin
if tvAvailableItems.IsEditing then
Exit;
AList := TComponentList.Create;
try
cxTreeViewGetSelection(tvAvailableItems, AList);
DeleteItems(AList, GetNextToSelectItem(tvAvailableItems));
finally
AList.Free;
end;
end;
procedure TdxLayoutControlCustomizeForm.tvItemsCustomDrawItem(
Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
var DefaultDraw: Boolean);
begin
if (TObject(Node.Data) is TdxLayoutGroup) and TdxLayoutGroup(Node.Data).Hidden and
not TdxLayoutGroup(Node.Data).IsRoot then
Sender.Canvas.Font.Style := [fsItalic];
end;
procedure TdxLayoutControlCustomizeForm.tvAvailableItemsContextPopup(
Sender: TObject; MousePos: TPoint; var Handled: Boolean);
begin
CalculateDeleteItemsActionStates;
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);
begin
if acAvailableItemsViewAsList.Checked then
Control.CustomizeAvailableItemsViewKind := oivkTree
else
Control.CustomizeAvailableItemsViewKind := oivkList;
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]));
if not AllowEdit or Control.IsDesigning then
Exit;
Node.Text := TdxCustomLayoutItem(Node.Data).Caption;
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
Control.Restore;
end;
end.