IDE: implemented closing designer without freeing component

git-svn-id: trunk@10010 -
This commit is contained in:
mattias 2006-09-30 13:57:40 +00:00
parent 84d62b1b15
commit 099ee4dc99
4 changed files with 176 additions and 106 deletions

View File

@ -217,7 +217,7 @@ type
constructor Create(TheDesignerForm: TCustomForm;
AControlSelection: TControlSelection);
procedure DeleteFormAndFree;
procedure FreeDesigner(FreeComponent: boolean);
destructor Destroy; override;
procedure Modified; override;
@ -466,7 +466,7 @@ begin
IgnoreDeletingPersistent:=TList.Create;
end;
procedure TDesigner.DeleteFormAndFree;
procedure TDesigner.FreeDesigner(FreeComponent: boolean);
var
i: Integer;
begin
@ -478,12 +478,14 @@ begin
TheControlSelection.Remove(LookupRoot);
if GlobalDesignHook.LookupRoot=FLookupRoot then
GlobalDesignHook.LookupRoot:=nil;
// tell hooks about deleting
for i:=FLookupRoot.ComponentCount-1 downto 0 do
GlobalDesignHook.PersistentDeleting(FLookupRoot.Components[i]);
GlobalDesignHook.PersistentDeleting(FLookupRoot);
if FreeComponent then begin
// tell hooks about deleting
for i:=FLookupRoot.ComponentCount-1 downto 0 do
GlobalDesignHook.PersistentDeleting(FLookupRoot.Components[i]);
GlobalDesignHook.PersistentDeleting(FLookupRoot);
end;
// delete
TheFormEditor.DeleteComponent(FLookupRoot,true);
TheFormEditor.DeleteComponent(FLookupRoot,FreeComponent);
end;
Free;
end;

View File

@ -287,6 +287,9 @@ function CompareComponentAndInterface(Key, Data: Pointer): integer;
function CompareDefPropCacheItems(Item1, Item2: TDefinePropertiesCacheItem): integer;
function ComparePersClassNameAndDefPropCacheItem(Key: Pointer;
Item: TDefinePropertiesCacheItem): integer;
function TryFreeComponent(var AComponent: TComponent): boolean;
procedure RegisterStandardClasses;
@ -330,6 +333,35 @@ begin
RegisterClasses([TStringList]);
end;
function TryFreeComponent(var AComponent: TComponent): boolean;
var
OldName, OldClassName: string;
Begin
Result:=false;
{$IFNDEF NoCompCatch}
try
{$ENDIF}
OldName:=AComponent.Name;
OldClassName:=AComponent.ClassName;
AComponent.Free;
Result := True;
{$IFNDEF NoCompCatch}
except
on E: Exception do begin
DebugLn('TComponentInterface.Delete ERROR:',
' "'+OldName+':'+OldClassName+'" ',E.Message);
DumpExceptionBackTrace;
MessageDlg('Error',
'An exception occured during deletion of'#13
+'"'+OldName+':'+OldClassName+'"'#13
+E.Message,
mtError,[mbOk],0);
end;
end;
{$ENDIF}
AComponent:=nil;
end;
{ TComponentInterface }
constructor TComponentInterface.Create;
@ -708,8 +740,8 @@ Begin
Result := False;
end;
Function TComponentInterface.Focus : Boolean;
Begin
function TComponentInterface.Focus : Boolean;
begin
Result := False;
if (FComponent is TWinControl) and (TWinControl(FComponent).CanFocus) then
Begin
@ -718,39 +750,16 @@ Begin
end;
end;
Function TComponentInterface.Delete: Boolean;
var
OldName, OldClassName: string;
Begin
function TComponentInterface.Delete: Boolean;
begin
{$IFDEF VerboseFormEditor}
writeln('TComponentInterface.Delete A ',Component.Name,':',Component.ClassName);
{$ENDIF}
{$IFNDEF NoCompCatch}
try
{$ENDIF}
OldName:=Component.Name;
OldClassName:=Component.ClassName;
Component.Free;
{$IFNDEF NoCompCatch}
except
on E: Exception do begin
DebugLn('TComponentInterface.Delete ERROR:',
' "'+OldName+':'+OldClassName+'" ',E.Message);
DumpExceptionBackTrace;
MessageDlg('Error',
'An exception occured during deletion of'#13
+'"'+OldName+':'+OldClassName+'"'#13
+E.Message,
mtError,[mbOk],0);
end;
end;
{$ENDIF}
FComponent:=nil;
Result:=TryFreeComponent(component);
{$IFDEF VerboseFormEditor}
writeln('TComponentInterface.Delete B ');
{$ENDIF}
Free;
Result := True;
end;
function TComponentInterface.GetComponentEditor: TBaseComponentEditor;
@ -820,56 +829,55 @@ end;
Procedure TCustomFormEditor.DeleteComponent(AComponent: TComponent;
FreeComponent: boolean);
var
Temp : TComponentInterface;
CompIntf : TComponentInterface;
i: integer;
AForm: TCustomForm;
Begin
Temp := TComponentInterface(FindComponent(AComponent));
if Temp <> nil then
begin
FComponentInterfaces.Remove(Temp);
CompIntf := TComponentInterface(FindComponent(AComponent));
if CompIntf <> nil then
FComponentInterfaces.Remove(CompIntf);
DebugLn('TCustomFormEditor.DeleteControl ',
AComponent.ClassName,' ',BoolToStr(IsJITComponent(AComponent)));
if IsJITComponent(AComponent) then begin
// value is a top level component
if FreeComponent then begin
DebugLn(['TCustomFormEditor.DeleteControl ',DbgSName(AComponent),' IsJITComponent=',IsJITComponent(AComponent)]);
if IsJITComponent(AComponent) then begin
// value is a top level component
i:=AComponent.ComponentCount-1;
while i>=0 do begin
DeleteComponent(AComponent.Components[i],FreeComponent);
dec(i);
if i>AComponent.ComponentCount-1 then
i:=AComponent.ComponentCount-1;
while i>=0 do begin
DeleteComponent(AComponent.Components[i],true);
dec(i);
if i>AComponent.ComponentCount-1 then
i:=AComponent.ComponentCount-1;
end;
if PropertyEditorHook.LookupRoot=AComponent then
PropertyEditorHook.LookupRoot:=nil;
if JITFormList.IsJITForm(AComponent) then
// free a form component
JITFormList.DestroyJITComponent(AComponent)
else if JITNonFormList.IsJITNonForm(AComponent) then begin
// free a non form component and its designer form
AForm:=GetDesignerForm(AComponent);
if not (AForm is TNonControlDesignerForm) then
RaiseException('TCustomFormEditor.DeleteControl Where is the TNonControlDesignerForm? '+AComponent.ClassName);
FNonControlForms.Remove(AForm);
TNonControlDesignerForm(AForm).LookupRoot:=nil;
AForm.Free;
JITNonFormList.DestroyJITComponent(AComponent);
end else
RaiseException('TCustomFormEditor.DeleteControl '+AComponent.ClassName);
end;
Temp.Free;
end
else begin
// value is a normal child component
if FreeComponent then
Temp.Delete
else
Temp.Free;
end;
end else begin
if PropertyEditorHook.LookupRoot=AComponent then
PropertyEditorHook.LookupRoot:=nil;
if JITFormList.IsJITForm(AComponent) then begin
// free/unbind a form component
if FreeComponent then
JITFormList.DestroyJITComponent(AComponent);
end else if JITNonFormList.IsJITNonForm(AComponent) then begin
// free/unbind a non form component and its designer form
AForm:=GetDesignerForm(AComponent);
if (AForm<>nil) and (not (AForm is TNonControlDesignerForm)) then
RaiseException('TCustomFormEditor.DeleteControl Where is the TNonControlDesignerForm? '+AComponent.ClassName);
if AForm<>nil then begin
FNonControlForms.Remove(AForm);
TNonControlDesignerForm(AForm).LookupRoot:=nil;
TryFreeComponent(AForm);
end;
if FreeComponent then
JITNonFormList.DestroyJITComponent(AComponent);
end else
RaiseException('TCustomFormEditor.DeleteControl '+AComponent.ClassName);
CompIntf.Free;
end
else if CompIntf<>nil then begin
// value is a normal child component
if FreeComponent then
AComponent.Free;
CompIntf.Delete
else
CompIntf.Free;
end else if FreeComponent then begin
DebugLn(['WARNING: TCustomFormEditor.DeleteComponent freeing orphaned component ',DbgSName(AComponent)]);
TryFreeComponent(AComponent);
end;
end;

View File

@ -584,7 +584,9 @@ type
var ComponentUnitInfo: TUnitInfo): TModalResult;
// methods for 'close unit'
function CloseDesignerForm(AnUnitInfo: TUnitInfo): TModalResult;
function CloseUnitComponent(AnUnitInfo: TUnitInfo): TModalResult;
function UnitComponentIsUsed(AnUnitInfo: TUnitInfo;
CheckHasDesigner: boolean): boolean;
// methods for creating a project
function CreateProjectObject(ProjectDesc,
@ -4754,7 +4756,7 @@ var
LFMFilename: string;
LFMBuf: TCodeBuffer;
begin
CloseDesignerForm(AnUnitInfo);
CloseUnitComponent(AnUnitInfo);
// Note: think about virtual and normal .lfm files.
LFMFilename:=ChangeFileExt(AnUnitInfo.Filename,'.lfm');
@ -4801,7 +4803,7 @@ begin
// close old designer form
if CloseDsgnForm then
CloseDesignerForm(AnUnitInfo)
CloseUnitComponent(AnUnitInfo)
else if AnUnitInfo.Component<>nil then begin
DebugLn(['TMainIDE.DoLoadLFM INCONSISTENCY CloseDsgnForm=',CloseDsgnForm,' Filename=',AnUnitInfo.Filename,' Component=',dbgsName(AnUnitInfo.Component)]);
exit(mrAbort);
@ -5113,17 +5115,31 @@ begin
end;
{-------------------------------------------------------------------------------
function TMainIDE.CloseDesignerForm
function TMainIDE.CloseUnitComponent
Params: AnUnitInfo: TUnitInfo
Result: TModalResult;
Free the designer form of a unit.
-------------------------------------------------------------------------------}
function TMainIDE.CloseDesignerForm(AnUnitInfo: TUnitInfo): TModalResult;
function TMainIDE.CloseUnitComponent(AnUnitInfo: TUnitInfo): TModalResult;
procedure FreeUnusedComponents;
var
CompUnitInfo: TUnitInfo;
begin
CompUnitInfo:=Project1.FirstUnitWithComponent;
while CompUnitInfo<>nil do begin
if not UnitComponentIsUsed(CompUnitInfo,true) then begin
CloseUnitComponent(CompUnitInfo);
exit;
end;
CompUnitInfo:=CompUnitInfo.NextUnitWithComponent;
end;
end;
var
AForm: TCustomForm;
i: integer;
OldDesigner: TDesigner;
LookupRoot: TComponent;
begin
@ -5134,25 +5150,57 @@ begin
OldDesigner:=nil;
if AForm<>nil then
OldDesigner:=TDesigner(AForm.Designer);
if FLastFormActivated=AForm then
FLastFormActivated:=nil;
if (OldDesigner=nil) then begin
DebugLn(['TMainIDE.CloseDesignerForm TODO: free hidden component without designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
// hidden component
DebugLn(['TMainIDE.CloseUnitComponent freeing hidden component without designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
if UnitComponentIsUsed(AnUnitInfo,false) then begin
// hidden component is still used => keep it
end else begin
// hidden component is not used => free it
FormEditor1.DeleteComponent(LookupRoot,true);
AnUnitInfo.Component:=nil;
FreeUnusedComponents;
end;
end else begin
if (AForm=nil) then exit;
if FLastFormActivated=AForm then
FLastFormActivated:=nil;
//debugln('TMainIDE.CloseDesignerForm A ',AnUnitInfo.Filename,' ',dbgsName(LookupRoot));
// unselect components
for i:=LookupRoot.ComponentCount-1 downto 0 do
TheControlSelection.Remove(LookupRoot.Components[i]);
TheControlSelection.Remove(LookupRoot);
// free designer and design form
OldDesigner.DeleteFormAndFree;
// component with designer
if UnitComponentIsUsed(AnUnitInfo,false) then begin
// free designer, keep component hidden
DebugLn(['TMainIDE.CloseUnitComponent hiding component and freeing designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
LCLIntf.ShowWindow(AForm.Handle,SW_HIDE);
OldDesigner.FreeDesigner(false);
end else begin
// free designer and design form
DebugLn(['TMainIDE.CloseUnitComponent freeing component and designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
OldDesigner.FreeDesigner(true);
AnUnitInfo.Component:=nil;
FreeUnusedComponents;
end;
end;
AnUnitInfo.Component:=nil;
Result:=mrOk;
end;
function TMainIDE.UnitComponentIsUsed(AnUnitInfo: TUnitInfo;
CheckHasDesigner: boolean): boolean;
var
LookupRoot: TComponent;
AForm: TCustomForm;
begin
Result:=false;
LookupRoot:=AnUnitInfo.Component;
if LookupRoot=nil then exit;
// check if a designer is open
if CheckHasDesigner then begin
AForm:=FormEditor1.GetDesignerForm(LookupRoot);
if AForm<>nil then exit(true);
end;
// check if another component uses this component
if Project1.UnitUsingComponentUnit(AnUnitInfo)<>nil then
exit(true);
end;
function TMainIDE.CreateProjectObject(ProjectDesc,
FallbackProjectDesc: TProjectDescriptor): TProject;
begin
@ -5657,7 +5705,7 @@ begin
// the file is not really new
NewUnitInfo:=AProject.Units[OldUnitIndex];
// close form
CloseDesignerForm(NewUnitInfo);
CloseUnitComponent(NewUnitInfo);
// assign source
NewUnitInfo.Source:=NewBuffer;
end else
@ -5970,7 +6018,7 @@ begin
end;
// close form
CloseDesignerForm(ActiveUnitInfo);
CloseUnitComponent(ActiveUnitInfo);
// close source editor
SourceNoteBook.CloseFile(PageIndex);
@ -6042,7 +6090,7 @@ var
// this is no pascal source and there is a designer form
// This can be the case, when the file is renamed and reverted
// -> close form
CloseDesignerForm(NewUnitInfo);
CloseUnitComponent(NewUnitInfo);
end;
Result:=mrOk;
end;
@ -9010,7 +9058,7 @@ begin
while AnUnitInfo<>nil do begin
NextUnitInfo:=AnUnitInfo.NextUnitWithComponent;
if not AnUnitInfo.NeedsSaveToDisk then
CloseDesignerForm(AnUnitInfo);
CloseUnitComponent(AnUnitInfo);
AnUnitInfo:=NextUnitInfo;
end;
end;
@ -11251,7 +11299,7 @@ begin
Exit;
end;
end;
CloseDesignerForm(AnUnitInfo);
CloseUnitComponent(AnUnitInfo);
end;
procedure TMainIDE.OnDesignerRenameComponent(ADesigner: TDesigner;

View File

@ -578,7 +578,9 @@ type
function ProjectUnitWithUnitname(const AnUnitName: string): TUnitInfo;
function UnitWithEditorIndex(Index:integer): TUnitInfo;
function UnitWithComponent(AComponent: TComponent): TUnitInfo;
function UnitComponentInheritingFrom(AClass: TComponentClass): TUnitInfo;
function UnitComponentInheritingFrom(AClass: TComponentClass;
Ignore: TUnitInfo): TUnitInfo;
function UnitUsingComponentUnit(ComponentUnit: TUnitInfo): TUnitInfo;
function UnitInfoWithFilename(const AFilename: string): TUnitInfo;
function UnitInfoWithFilename(const AFilename: string;
SearchFlags: TProjectFileSearchFlags): TUnitInfo;
@ -3373,12 +3375,22 @@ begin
Result:=Result.fNext[uilWithComponent];
end;
function TProject.UnitComponentInheritingFrom(AClass: TComponentClass
): TUnitInfo;
function TProject.UnitComponentInheritingFrom(AClass: TComponentClass;
Ignore: TUnitInfo): TUnitInfo;
begin
Result:=fFirst[uilWithComponent];
while (Result<>nil) and (Result.Component.InheritsFrom(AClass)) do
while (Result<>nil) do begin
if (Result<>Ignore) and Result.Component.InheritsFrom(AClass) then exit;
Result:=Result.fNext[uilWithComponent];
end;
end;
function TProject.UnitUsingComponentUnit(ComponentUnit: TUnitInfo): TUnitInfo;
begin
Result:=nil;
if ComponentUnit.Component=nil then exit;
Result:=UnitComponentInheritingFrom(
TComponentClass(ComponentUnit.Component.ClassType),ComponentUnit);
end;
function TProject.UnitInfoWithFilename(const AFilename: string): TUnitInfo;