mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-26 19:09:36 +02:00
IDE: implemented closing designer without freeing component
git-svn-id: trunk@10010 -
This commit is contained in:
parent
84d62b1b15
commit
099ee4dc99
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
96
ide/main.pp
96
ide/main.pp
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user