Componentes.Terceros.DevExp.../internal/x.42/2/ExpressLayout Control/Sources/dxLayoutDesignCommon.pas

701 lines
22 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressLayoutControl design-time common classes }
{ }
{ 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 dxLayoutDesignCommon;
{$I cxVer.inc}
interface
uses
Windows, Classes, Forms, StdCtrls, dxLayoutCommon, dxLayoutControl, dxLayoutLookAndFeels,
{$IFDEF DELPHI6}DesignIntf, DesignEditors, ComponentDesigner, VCLEditors, DesignWindows{$ELSE}
DsgnIntf, LibIntf, DsgnWnds{$ENDIF};
type
TFormDesigner = {$IFDEF DELPHI6}IDesigner{$ELSE}IFormDesigner{$ENDIF};
{$IFDEF DELPHI6}
TDesignerSelectionList = TDesignerSelections;
{$ENDIF}
TDesignerSelectionListAccess = class(TDesignerSelectionList)
public
property Count;
property Items;
end;
TdxLayoutDesignFormClass = class of TdxLayoutDesignForm;
TdxLayoutDesignForm = class(TDesignWindow)
private
FComponent: TComponent;
FDeletingComponents: Boolean;
FSelectingComponents: Boolean;
protected
procedure DoClose(var Action: TCloseAction); override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
function UniqueName(Component: TComponent): string; override;
function CalculateListBoxItemHeight(AListBox: TListBox = nil): Integer;
function CanModify: Boolean; virtual;
procedure DeleteItemsButtonClick(Sender: TObject);
function GetAddItemsButton(AIndex: Integer): TButton; virtual; abstract;
function GetAddItemsButtonCount: Integer; virtual; abstract;
function GetDeleteItemsButton: TButton; virtual; abstract;
function GetItemsListBox: TListBox; virtual; abstract;
function GetSelectedItems(AListBox: TListBox = nil): TDesignerSelectionListAccess;
procedure ItemsListBoxClick(Sender: TObject); virtual;
function NeedRefreshItemsAfterDeleting(AComponent: TPersistent): Boolean; virtual;
procedure RefreshEnableds; virtual;
procedure RefreshItemsListBox; virtual; abstract;
procedure SetComponent(Value: TComponent); virtual;
property DeletingComponents: Boolean read FDeletingComponents write FDeletingComponents;
property SelectingComponents: Boolean read FSelectingComponents write FSelectingComponents;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure AfterConstruction; override;
{$IFDEF DELPHI6}
procedure ItemDeleted(const ADesigner: IDesigner; Item: TPersistent); override;
{$ELSE}
procedure ComponentDeleted(Component: IPersistent); override;
{$ENDIF}
{$IFDEF DELPHI6}
procedure SelectionChanged(const ADesigner: IDesigner; const ASelection: IDesignerSelections); override;
{$ELSE}
procedure SelectionChanged(ASelection: TDesignerSelectionList); override;
{$ENDIF}
procedure RefreshCaption; virtual;
procedure RefreshItems; virtual;
property Component: TComponent read FComponent write SetComponent;
end;
PDesignFormRecord = ^TDesignFormRecord;
TDesignFormRecord = record
Component: TComponent;
Form: TdxLayoutDesignForm;
end;
TdxLayoutRealDesigner = class(TdxLayoutDesigner{$IFDEF DELPHI6}, IDesignNotification{$ENDIF})
private
FComponents: TList;
FDesignFormRecords: TList;
FLayoutControlDesignFormBounds: TRect;
FLayoutLookAndFeelListDesignFormBounds: TRect;
function GetComponent(Index: Integer): TComponent;
function GetComponentCount: Integer;
function GetDesignFormBounds(ADesignForm: TdxLayoutDesignForm): TRect;
function GetDesignFormRecordCount: Integer;
function GetDesignFormRecord(Index: Integer): PDesignFormRecord;
procedure SetDesignFormBounds(ADesignForm: TdxLayoutDesignForm; const Value: TRect);
//procedure ClearDesignFormRecords;
procedure DeleteDesignFormRecord(ADesignFormRecord: PDesignFormRecord);
protected
{$IFDEF DELPHI6}
// IDesignNotification
procedure ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent);
procedure ItemInserted(const ADesigner: IDesigner; AItem: TPersistent);
procedure ItemsModified(const ADesigner: IDesigner);
procedure SelectionChanged(const ADesigner: IDesigner;
const ASelection: IDesignerSelections);
procedure DesignerOpened(const ADesigner: IDesigner; AResurrecting: Boolean);
procedure DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
{$ENDIF}
function FindDesignFormRecord(AComponent: TComponent): PDesignFormRecord;
function GetFormDesigner(AComponent: TComponent): TFormDesigner;
function GetDesignForm(AComponent: TComponent): TdxLayoutDesignForm;
function GetDesignFormClass(AComponent: TComponent): TdxLayoutDesignFormClass;
property ComponentCount: Integer read GetComponentCount;
property Components[Index: Integer]: TComponent read GetComponent;
property DesignFormBounds[ADesignForm: TdxLayoutDesignForm]: TRect
read GetDesignFormBounds write SetDesignFormBounds;
property DesignFormRecordCount: Integer read GetDesignFormRecordCount;
property DesignFormRecords[Index: Integer]: PDesignFormRecord read GetDesignFormRecord;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure RegisterComponent(AComponent: TComponent); override;
procedure UnregisterComponent(AComponent: TComponent); override;
procedure ComponentNameChanged(AComponent: TComponent); override;
function GetDesigner(AComponent: TComponent): TCustomForm; override;
function GetUniqueName(AComponent: TComponent; const ABaseName: string): string; override;
function IsComponentSelected(AComponent: TComponent; APersistent: TPersistent): Boolean; override;
function IsToolSelected: Boolean; override;
procedure ItemsChanged(AComponent: TComponent); override;
procedure SelectComponent(AComponent: TComponent; APersistent: TPersistent;
AInvertSelection: Boolean); override;
procedure HideDesignForm(AComponent: TComponent);
procedure ShowDesignForm(AComponent: TComponent; AFormDesigner: TFormDesigner);
end;
implementation
uses
SysUtils, Controls, Graphics, dxLayoutDesignForm, dxLayoutLookAndFeelListDesignForm;
{ TdxLayoutDesignForm }
constructor TdxLayoutDesignForm.Create(AOwner: TComponent);
begin
inherited;
BorderIcons := [biSystemMenu];
end;
destructor TdxLayoutDesignForm.Destroy;
begin
if not (csDestroying in Component.ComponentState) then
Designer.SelectComponent(Component);
TdxLayoutRealDesigner(dxLayoutDesigner).HideDesignForm(Component);
inherited;
end;
procedure TdxLayoutDesignForm.DoClose(var Action: TCloseAction);
begin
Action := caFree;
inherited;
end;
procedure TdxLayoutDesignForm.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = Component) then
Free;
end;
function TdxLayoutDesignForm.UniqueName(Component: TComponent): string;
begin
Result := Designer.UniqueName(Component.ClassName);
end;
function TdxLayoutDesignForm.CalculateListBoxItemHeight(AListBox: TListBox): Integer;
begin
if AListBox = nil then
AListBox := GetItemsListBox;
Result := 2 + AListBox.Canvas.TextHeight('Qq') + 2;
end;
function TdxLayoutDesignForm.CanModify: Boolean;
begin
Result := not Designer.IsSourceReadOnly and
not (csInline in FComponent.Owner.ComponentState);
end;
procedure TdxLayoutDesignForm.DeleteItemsButtonClick(Sender: TObject);
var
ASelections: TDesignerSelectionListAccess;
I: Integer;
begin
FDeletingComponents := True;
try
ASelections := GetSelectedItems;
try
if ASelections.Count <> 0 then
try
Designer.SelectComponent(Component);
for I := 0 to ASelections.Count - 1 do
ASelections[I].Free;
finally
RefreshItemsListBox;
Designer.Modified;
end;
finally
ASelections.Free;
end;
finally
FDeletingComponents := False;
end;
end;
function TdxLayoutDesignForm.GetSelectedItems(AListBox: TListBox): TDesignerSelectionListAccess;
var
I: Integer;
begin
if AListBox = nil then
AListBox := GetItemsListBox;
Result := TDesignerSelectionListAccess.Create;
with AListBox, Items do
for I := 0 to Count - 1 do
if Selected[I] and (Objects[I] <> nil) then
Result.Add(TPersistent(Objects[I]));
end;
procedure TdxLayoutDesignForm.ItemsListBoxClick(Sender: TObject);
var
ASelections: TDesignerSelectionListAccess;
begin
ASelections := GetSelectedItems(Sender as TListBox);
with ASelections do
if Count = 0 then Add(Component);
FSelectingComponents := True;
try
Designer.SetSelections(ASelections);
finally
FSelectingComponents := False;
RefreshEnableds;
end;
end;
function TdxLayoutDesignForm.NeedRefreshItemsAfterDeleting(AComponent: TPersistent): Boolean;
begin
Result := not (csDestroying in Component.ComponentState);
end;
procedure TdxLayoutDesignForm.RefreshEnableds;
var
ASelections: TDesignerSelectionListAccess;
I: Integer;
begin
ASelections := GetSelectedItems;
try
for I := 0 to GetAddItemsButtonCount - 1 do
GetAddItemsButton(I).Enabled := CanModify;
GetDeleteItemsButton.Enabled := CanModify and (ASelections.Count <> 0);
finally
ASelections.Free;
end;
end;
procedure TdxLayoutDesignForm.SetComponent(Value: TComponent);
begin
FComponent := Value;
FComponent.FreeNotification(Self);
RefreshCaption;
RefreshItemsListBox;
RefreshEnableds;
end;
procedure TdxLayoutDesignForm.AfterConstruction;
begin
inherited;
with GetItemsListBox do
begin
ItemHeight := CalculateListBoxItemHeight;
OnClick := ItemsListBoxClick;
end;
GetDeleteItemsButton.OnClick := DeleteItemsButtonClick;
end;
{$IFDEF DELPHI6}
procedure TdxLayoutDesignForm.ItemDeleted(const ADesigner: IDesigner; Item: TPersistent);
{$ELSE}
procedure TdxLayoutDesignForm.ComponentDeleted(Component: IPersistent);
{$ENDIF}
var
AComponent: TPersistent;
begin
inherited;
if FDeletingComponents then Exit;
{$IFDEF DELPHI6}
AComponent := Item;
{$ELSE}
AComponent := ExtractPersistent(Component);
{$ENDIF}
if NeedRefreshItemsAfterDeleting(AComponent) then
RefreshItems;
end;
{$IFDEF DELPHI6}
procedure TdxLayoutDesignForm.SelectionChanged(const ADesigner: IDesigner; const ASelection: IDesignerSelections);
{$ELSE}
procedure TdxLayoutDesignForm.SelectionChanged(ASelection: TDesignerSelectionList);
{$ENDIF}
var
I, AIndex: Integer;
{$IFNDEF DELPHI6}
ALayoutComponent: IdxLayoutComponent;
{$ENDIF}
begin
inherited;
{$IFNDEF DELPHI6}
if Component.GetInterface(IdxLayoutComponent, ALayoutComponent) then
ALayoutComponent.SelectionChanged;
{$ENDIF}
if FSelectingComponents then Exit;
with GetItemsListBox, Items do
begin
BeginUpdate;
try
for I := 0 to Count - 1 do
Selected[I] := False;
if ASelection <> nil then
for I := 0 to ASelection.Count - 1 do
begin
AIndex := IndexOfObject(ASelection[I]);
if AIndex <> -1 then
Selected[AIndex] := True;
end;
finally
EndUpdate;
RefreshEnableds;
end;
end;
end;
procedure TdxLayoutDesignForm.RefreshCaption;
begin
Caption := 'Designer - ' + FComponent.Name;
end;
procedure TdxLayoutDesignForm.RefreshItems;
var
ASelections: IDesignerSelections;
begin
ASelections := CreateSelectionList;
Designer.GetSelections(ASelections);
RefreshItemsListBox;
{$IFDEF DELPHI6}
SelectionChanged(Designer, ASelections);
{$ELSE}
SelectionChanged(ASelections);
{$ENDIF}
end;
{ TdxLayoutRealDesigner }
constructor TdxLayoutRealDesigner.Create(AOwner: TComponent);
begin
inherited;
FComponents := TList.Create;
FDesignFormRecords := TList.Create;
{$IFDEF DELPHI6}
RegisterDesignNotification(Self);
{$ENDIF}
end;
destructor TdxLayoutRealDesigner.Destroy;
begin
{$IFDEF DELPHI6}
UnregisterDesignNotification(Self);
{$ENDIF}
FComponents.Free;
//ClearDesignFormRecords;
FDesignFormRecords.Free;
inherited;
end;
function TdxLayoutRealDesigner.GetComponent(Index: Integer): TComponent;
begin
Result := FComponents[Index];
end;
function TdxLayoutRealDesigner.GetComponentCount: Integer;
begin
Result := FComponents.Count;
end;
function TdxLayoutRealDesigner.GetDesignFormBounds(ADesignForm: TdxLayoutDesignForm): TRect;
begin
if ADesignForm is TDesignForm then
Result := FLayoutControlDesignFormBounds
else
if ADesignForm is TLookAndFeelListDesignForm then
Result := FLayoutLookAndFeelListDesignFormBounds
else
SetRectEmpty(Result);
end;
function TdxLayoutRealDesigner.GetDesignFormRecordCount: Integer;
begin
Result := FDesignFormRecords.Count;
end;
function TdxLayoutRealDesigner.GetDesignFormRecord(Index: Integer): PDesignFormRecord;
begin
Result := FDesignFormRecords[Index];
end;
procedure TdxLayoutRealDesigner.SetDesignFormBounds(ADesignForm: TdxLayoutDesignForm;
const Value: TRect);
begin
if ADesignForm is TDesignForm then
FLayoutControlDesignFormBounds := Value
else
if ADesignForm is TLookAndFeelListDesignForm then
FLayoutLookAndFeelListDesignFormBounds := Value;
end;
{procedure TdxLayoutRealDesigner.ClearDesignFormRecords;
var
I: Integer;
begin
for I := DesignFormRecordCount - 1 downto 0 do
DeleteDesignFormRecord(DesignFormRecords[I]);
end;}
procedure TdxLayoutRealDesigner.DeleteDesignFormRecord(ADesignFormRecord: PDesignFormRecord);
begin
FDesignFormRecords.Remove(ADesignFormRecord);
Dispose(ADesignFormRecord);
end;
{$IFDEF DELPHI6}
procedure TdxLayoutRealDesigner.ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent);
begin
end;
procedure TdxLayoutRealDesigner.ItemInserted(const ADesigner: IDesigner; AItem: TPersistent);
begin
end;
procedure TdxLayoutRealDesigner.ItemsModified(const ADesigner: IDesigner);
begin
end;
procedure TdxLayoutRealDesigner.SelectionChanged(const ADesigner: IDesigner;
const ASelection: IDesignerSelections);
var
I: Integer;
ALayoutComponent: IdxLayoutComponent;
function HasAsOwner(AComponent, AOwner: TComponent): Boolean;
begin
repeat
Result := AComponent.Owner = AOwner;
AComponent := AComponent.Owner;
until Result or (AComponent = nil);
end;
begin
for I := 0 to ComponentCount - 1 do
if ((ADesigner = nil) or HasAsOwner(Components[I], ADesigner.GetRoot)) and
Components[I].GetInterface(IdxLayoutComponent, ALayoutComponent) then
ALayoutComponent.SelectionChanged;
end;
procedure TdxLayoutRealDesigner.DesignerOpened(const ADesigner: IDesigner;
AResurrecting: Boolean);
begin
end;
procedure TdxLayoutRealDesigner.DesignerClosed(const ADesigner: IDesigner;
AGoingDormant: Boolean);
begin
end;
{$ENDIF}
function TdxLayoutRealDesigner.FindDesignFormRecord(AComponent: TComponent): PDesignFormRecord;
var
I: Integer;
begin
for I := 0 to DesignFormRecordCount - 1 do
begin
Result := DesignFormRecords[I];
if Result^.Component = AComponent then Exit;
end;
Result := nil;
end;
function TdxLayoutRealDesigner.GetFormDesigner(AComponent: TComponent): TFormDesigner;
begin
Result := FindRootDesigner(AComponent) as TFormDesigner;
end;
function TdxLayoutRealDesigner.GetDesignForm(AComponent: TComponent): TdxLayoutDesignForm;
var
ADesignFormRecord: PDesignFormRecord;
begin
ADesignFormRecord := FindDesignFormRecord(AComponent);
if ADesignFormRecord = nil then
Result := nil
else
Result := ADesignFormRecord^.Form;
end;
function TdxLayoutRealDesigner.GetDesignFormClass(AComponent: TComponent): TdxLayoutDesignFormClass;
begin
if AComponent is TdxCustomLayoutControl then
Result := TDesignForm
else
if AComponent is TdxLayoutLookAndFeelList then
Result := TLookAndFeelListDesignForm
else
Result := nil;
end;
procedure TdxLayoutRealDesigner.RegisterComponent(AComponent: TComponent);
begin
FComponents.Add(AComponent);
end;
procedure TdxLayoutRealDesigner.UnregisterComponent(AComponent: TComponent);
begin
FComponents.Remove(AComponent);
end;
procedure TdxLayoutRealDesigner.ComponentNameChanged(AComponent: TComponent);
var
ADesignForm: TdxLayoutDesignForm;
begin
ADesignForm := GetDesignForm(AComponent);
if ADesignForm <> nil then ADesignForm.RefreshCaption;
end;
function TdxLayoutRealDesigner.GetDesigner(AComponent: TComponent): TCustomForm;
begin
Result := GetDesignForm(AComponent);
end;
function TdxLayoutRealDesigner.GetUniqueName(AComponent: TComponent;
const ABaseName: string): string;
begin
Result := GetFormDesigner(AComponent).UniqueName(ABaseName);
end;
function TdxLayoutRealDesigner.IsComponentSelected(AComponent: TComponent;
APersistent: TPersistent): Boolean;
var
ASelections: IDesignerSelections;
I: Integer;
begin
if GetFormDesigner(AComponent) = nil then
Result := False
else
begin
ASelections := CreateSelectionList;
GetFormDesigner(AComponent).GetSelections(ASelections);
for I := 0 to ASelections.Count - 1 do
begin
Result :=
{$IFNDEF DELPHI6}ExtractPersistent{$ENDIF}(ASelections[I]) = APersistent;
if Result then Exit;
end;
Result := False;
end;
end;
function TdxLayoutRealDesigner.IsToolSelected: Boolean;
begin
Result := {$IFDEF DELPHI9}(ActiveDesigner <> nil) and{$ENDIF}
{$IFDEF DELPHI6}ActiveDesigner.Environment{$ELSE}DelphiIDE{$ENDIF}.GetToolSelected;
end;
procedure TdxLayoutRealDesigner.ItemsChanged(AComponent: TComponent);
var
ADesignForm: TdxLayoutDesignForm;
begin
ADesignForm := GetDesignForm(AComponent);
if ADesignForm <> nil then ADesignForm.RefreshItems;
end;
procedure TdxLayoutRealDesigner.SelectComponent(AComponent: TComponent;
APersistent: TPersistent; AInvertSelection: Boolean);
var
ASelections, ANewSelections: IDesignerSelections;
I: Integer;
ASelection: TPersistent;
begin
if AInvertSelection then
begin
ASelections := CreateSelectionList;
GetFormDesigner(AComponent).GetSelections(ASelections);
ANewSelections := CreateSelectionList;
for I := 0 to ASelections.Count - 1 do
begin
ASelection := {$IFNDEF DELPHI6}ExtractPersistent{$ENDIF}(ASelections[I]);
if (ASelection <> AComponent) and (ASelection <> APersistent) then
ANewSelections.Add(ASelections[I]);
end;
if IsComponentSelected(AComponent, APersistent) then
if ANewSelections.Count = 0 then
ANewSelections.Add({$IFNDEF DELPHI6}MakeIPersistent{$ENDIF}(AComponent))
else
else
ANewSelections.Add({$IFNDEF DELPHI6}MakeIPersistent{$ENDIF}(APersistent));
GetFormDesigner(AComponent).SetSelections(ANewSelections);
end
else
GetFormDesigner(AComponent).SelectComponent(APersistent);
end;
procedure TdxLayoutRealDesigner.HideDesignForm(AComponent: TComponent);
var
ADesignFormRecord: PDesignFormRecord;
begin
ADesignFormRecord := FindDesignFormRecord(AComponent);
DesignFormBounds[ADesignFormRecord.Form] := ADesignFormRecord.Form.BoundsRect;
DeleteDesignFormRecord(ADesignFormRecord);
end;
procedure TdxLayoutRealDesigner.ShowDesignForm(AComponent: TComponent;
AFormDesigner: TFormDesigner);
var
ADesignForm: TdxLayoutDesignForm;
ADesignFormBounds: TRect;
ADesignFormRecord: PDesignFormRecord;
begin
ADesignForm := GetDesignForm(AComponent);
if ADesignForm = nil then
begin
ADesignForm := GetDesignFormClass(AComponent).Create(nil);
ADesignForm.Designer := AFormDesigner;
ADesignForm.Component := AComponent;
New(ADesignFormRecord);
with ADesignFormRecord^ do
begin
Component := AComponent;
Form := ADesignForm;
end;
FDesignFormRecords.Add(ADesignFormRecord);
ADesignForm.Show;
ADesignFormBounds := DesignFormBounds[ADesignForm];
if not IsRectEmpty(ADesignFormBounds) then
ADesignForm.BoundsRect := ADesignFormBounds;
end
else
ADesignForm.BringToFront;
end;
initialization
dxLayoutDesigner := TdxLayoutRealDesigner.Create(nil);
finalization
FreeAndNil(dxLayoutDesigner);
end.