From 00b85598ab6f85f8bddb9c16ad7bdb162147512d Mon Sep 17 00:00:00 2001 From: mattias Date: Mon, 16 Oct 2006 18:20:42 +0000 Subject: [PATCH] IDE: improved renaming inherited components git-svn-id: trunk@10082 - --- designer/designer.pp | 77 ++++++++++++++--------------- designer/jitforms.pp | 13 ++++- ide/customformeditor.pp | 84 +++++++++++++++++++++++++++++--- ide/main.pp | 76 ++++++++++++++++++++++++++++- ideintf/formeditingintf.pas | 4 ++ lcl/include/customnotebook.inc | 3 +- lcl/interfaces/gtk/gtkwinapi.inc | 1 - 7 files changed, 205 insertions(+), 53 deletions(-) diff --git a/designer/designer.pp b/designer/designer.pp index 394867b440..0e759b4722 100644 --- a/designer/designer.pp +++ b/designer/designer.pp @@ -146,11 +146,11 @@ type function PaintControl(Sender: TControl; TheMessage: TLMPaint):boolean; function SizeControl(Sender: TControl; TheMessage: TLMSize):boolean; function MoveControl(Sender: TControl; TheMessage: TLMMove):boolean; - Procedure MouseDownOnControl(Sender: TControl; var TheMessage : TLMMouse); - Procedure MouseMoveOnControl(Sender: TControl; var TheMessage: TLMMouse); - Procedure MouseUpOnControl(Sender: TControl; var TheMessage:TLMMouse); - Procedure KeyDown(Sender: TControl; var TheMessage:TLMKEY); - Procedure KeyUp(Sender: TControl; var TheMessage:TLMKEY); + procedure MouseDownOnControl(Sender: TControl; var TheMessage : TLMMouse); + procedure MouseMoveOnControl(Sender: TControl; var TheMessage: TLMMouse); + procedure MouseUpOnControl(Sender: TControl; var TheMessage:TLMMouse); + procedure KeyDown(Sender: TControl; var TheMessage:TLMKEY); + procedure KeyUp(Sender: TControl; var TheMessage:TLMKEY); function HandleSetCursor(var TheMessage: TLMessage): boolean; // procedures for working with components and persistents @@ -1823,18 +1823,34 @@ function TDesigner.DoDeleteSelectedPersistents: boolean; var i: integer; APersistent: TPersistent; + AncestorRoot: TComponent; begin Result:=true; if (ControlSelection.Count=0) or (ControlSelection.SelectionForm<>Form) then exit; Result:=false; + // check if a component is the lookup root (can not be deleted) if (ControlSelection.LookupRootSelected) then begin if ControlSelection.Count>1 then MessageDlg(lisInvalidDelete, lisTheRootComponentCanNotBeDeleted, mtInformation, - [mbOk],0); + [mbCancel],0); exit; end; + // check if a selected component is inherited (can not be deleted) + for i:=0 to ControlSelection.Count-1 do begin + if not ControlSelection[i].IsTComponent then continue; + AncestorRoot:=TheFormEditor.GetAncestorLookupRoot( + TComponent(ControlSelection[i].Persistent)); + if AncestorRoot<>nil then begin + MessageDlg(lisInvalidDelete, + 'The component '+dbgsName(ControlSelection[i].Persistent) + +' is inherited from '+dbgsName(AncestorRoot)+'.'#13 + +'To delete an inherited component open the ancestor and delete it there.', + mtInformation, [mbCancel],0); + exit; + end; + end; // mark selected components for deletion for i:=0 to ControlSelection.Count-1 do MarkPersistentForDeletion(ControlSelection[i].Persistent); @@ -1842,16 +1858,19 @@ begin SelectOnlyThisComponent(FLookupRoot); // delete marked components Include(FFlags,dfDeleting); - if DeletingPersistent.Count=0 then exit; - while DeletingPersistent.Count>0 do begin - APersistent:=TPersistent(DeletingPersistent[DeletingPersistent.Count-1]); - //writeln('TDesigner.DoDeleteSelectedComponents A ',AComponent.Name,':',AComponent.ClassName,' ',DbgS(AComponent)); - RemovePersistentAndChilds(APersistent); - //writeln('TDesigner.DoDeleteSelectedComponents B ',DeletingPersistent.IndexOf(AComponent)); + try + if DeletingPersistent.Count=0 then exit; + while DeletingPersistent.Count>0 do begin + APersistent:=TPersistent(DeletingPersistent[DeletingPersistent.Count-1]); + //writeln('TDesigner.DoDeleteSelectedComponents A ',AComponent.Name,':',AComponent.ClassName,' ',DbgS(AComponent)); + RemovePersistentAndChilds(APersistent); + //writeln('TDesigner.DoDeleteSelectedComponents B ',DeletingPersistent.IndexOf(AComponent)); + end; + IgnoreDeletingPersistent.Clear; + finally + Exclude(FFlags,dfDeleting); + Modified; end; - IgnoreDeletingPersistent.Clear; - Exclude(FFlags,dfDeleting); - Modified; Result:=true; end; @@ -2086,42 +2105,18 @@ end; procedure TDesigner.ValidateRename(AComponent: TComponent; const CurName, NewName: string); - - {$IFDEF VER2_0_2} - procedure RaiseInvalidName(ConflictComponent: TComponent); - begin - raise EComponentError.Create(Format( - lisDesThereIsAlreadyAnotherComponentWithTheName, ['"', - ConflictComponent.Name, '"'])); - end; - -var - i: Integer; - CurComponent: TComponent; - {$ENDIF} begin // check if component is initialized if (CurName='') or (NewName='') or ((AComponent<>nil) and (csDestroying in AComponent.ComponentState)) then exit; - {$IFDEF VER2_0_2} - // check, if there is already such a component - for i:=0 to FLookupRoot.ComponentCount-1 do begin - CurComponent:=FLookupRoot.Components[i]; - //DebugLn('TDesigner.ValidateRename ',CurComponent.Name,' ',NewName); - if (CurComponent<>AComponent) - and (CompareText(CurComponent.Name,NewName)=0) then begin - RaiseInvalidName(CurComponent); - end; - end; - {$ENDIF} - // check if component is the LookupRoot if AComponent=nil then AComponent:=FLookupRoot; + // consistency check if CurName<>AComponent.Name then - DebugLn('WARNING: TDesigner.ValidateRename: OldComponentName="',CurName,'"'); + DebugLn('WARNING: TDesigner.ValidateRename: OldComponentName="',CurName,'" <> AComponent=',dbgsName(AComponent)); if Assigned(OnRenameComponent) then OnRenameComponent(Self,AComponent,NewName); end; diff --git a/designer/jitforms.pp b/designer/jitforms.pp index aecaf21e45..f7c0d0d606 100644 --- a/designer/jitforms.pp +++ b/designer/jitforms.pp @@ -148,7 +148,8 @@ type procedure DestroyJITComponent(Index: integer); function IndexOf(JITComponent: TComponent): integer; function Contains(JITComponent: TComponent): boolean; - function FindComponentByClassName(const AClassName: shortstring):integer; + function FindComponentByClassName(const AClassName: shortstring): integer; + function FindComponentByClass(AClass: TComponentClass): integer; function FindComponentByName(const AName: shortstring): integer; procedure GetUnusedNames(var ComponentName, ComponentClassName: shortstring); procedure AddNewMethod(JITComponent: TComponent; const AName: ShortString); @@ -613,6 +614,14 @@ begin dec(Result); end; +function TJITComponentList.FindComponentByClass(AClass: TComponentClass + ): integer; +begin + Result:=FJITComponents.Count-1; + while (Result>=0) and (Items[Result].ClassType<>AClass) do + dec(Result); +end; + function TJITComponentList.FindComponentByName(const AName:shortstring):integer; begin Result:=FJITComponents.Count-1; @@ -1337,7 +1346,7 @@ procedure TJITComponentList.ReaderAncestorNotFound(Reader: TReader; begin // ToDo: this is for custom form templates debugln('[TJITComponentList.ReaderAncestorNotFound] ComponentName='''+ComponentName - +''' Component='''+Component.Name+''''); + +''' Component='''+dbgsName(Component)+''''); end; procedure TJITComponentList.ReaderError(Reader: TReader; diff --git a/ide/customformeditor.pp b/ide/customformeditor.pp index 1b06af830b..7e7426934c 100644 --- a/ide/customformeditor.pp +++ b/ide/customformeditor.pp @@ -162,6 +162,8 @@ each control that's dropped onto the form function FindJITList(AComponent: TComponent): TJITComponentList; function FindJITListByClassName(const AComponentClassName: string ): TJITComponentList; + function FindJITListByClass(AComponentClass: TComponentClass + ): TJITComponentList; function GetDesignerForm(AComponent: TComponent): TCustomForm; override; function FindNonControlForm(LookupRoot: TComponent): TNonControlDesignerForm; function CreateNonControlForm(LookupRoot: TComponent): TNonControlDesignerForm; @@ -177,7 +179,9 @@ each control that's dropped onto the form procedure SaveHiddenDesignerFormProperties(AComponent: TComponent); function FindJITComponentByClassName(const AComponentClassName: string ): TComponent; - + function FindJITComponentByClass(AComponentClass: TComponentClass + ): TComponent; + // designers function DesignerCount: integer; override; function GetDesigner(Index: integer): TIDesigner; override; @@ -218,6 +222,10 @@ each control that's dropped onto the form ParentControl: TWinControl): TIComponentInterface; override; procedure SetComponentNameAndClass(CI: TIComponentInterface; const NewName, NewClassName: shortstring); + + // ancestors + function GetAncestorLookupRoot(AComponent: TComponent): TComponent; override; + function GetAncestorInstance(AComponent: TComponent): TComponent; override; // define properties procedure FindDefineProperty(const APersistentClassName, @@ -1079,6 +1087,17 @@ begin Result:=nil; end; +function TCustomFormEditor.FindJITListByClass(AComponentClass: TComponentClass + ): TJITComponentList; +begin + if JITFormList.FindComponentByClass(AComponentClass)>=0 then + Result:=JITFormList + else if JITNonFormList.FindComponentByClass(AComponentClass)>=0 then + Result:=JITNonFormList + else + Result:=nil; +end; + function TCustomFormEditor.GetDesignerForm(AComponent: TComponent ): TCustomForm; var @@ -1189,15 +1208,37 @@ end; function TCustomFormEditor.FindJITComponentByClassName( const AComponentClassName: string): TComponent; var - JITComponentList: TJITComponentList; i: LongInt; begin Result:=nil; - JITComponentList:=FindJITListByClassName(AComponentClassName); - if JITComponentList=nil then exit; - i:=JITComponentList.FindComponentByClassName(AComponentClassName); - if i<0 then exit; - Result:=JITComponentList[i]; + i:=JITFormList.FindComponentByClassName(AComponentClassName); + if i>=0 then begin + Result:=JITFormList[i]; + exit; + end; + i:=JITNonFormList.FindComponentByClassName(AComponentClassName); + if i>=0 then begin + Result:=JITNonFormList[i]; + exit; + end; +end; + +function TCustomFormEditor.FindJITComponentByClass( + AComponentClass: TComponentClass): TComponent; +var + i: LongInt; +begin + Result:=nil; + i:=JITFormList.FindComponentByClass(AComponentClass); + if i>=0 then begin + Result:=JITFormList[i]; + exit; + end; + i:=JITNonFormList.FindComponentByClass(AComponentClass); + if i>=0 then begin + Result:=JITNonFormList[i]; + exit; + end; end; function TCustomFormEditor.DesignerCount: integer; @@ -1521,6 +1562,35 @@ begin AComponent.Name:=NewName; end; +function TCustomFormEditor.GetAncestorLookupRoot(AComponent: TComponent + ): TComponent; +var + CurRoot: TComponent; + AncestorRoot: TComponent; +begin + Result:=nil; + if AComponent=nil then exit; + CurRoot:=AComponent.Owner; + if CurRoot=nil then exit; + repeat + // search in next ancestor + AncestorRoot:=GetAncestorInstance(CurRoot); + if AncestorRoot=nil then exit; + if AncestorRoot.FindComponent(AComponent.Name)=nil then exit; + // a better ancestor was found + Result:=AncestorRoot; + CurRoot:=AncestorRoot; + until false; +end; + +function TCustomFormEditor.GetAncestorInstance(AComponent: TComponent + ): TComponent; +begin + Result:=nil; + if (AComponent=nil) or (AComponent.ClassType=TComponent) then exit; + Result:=FindJITComponentByClass(TComponentClass(AComponent.ClassParent)); +end; + procedure TCustomFormEditor.FindDefineProperty( const APersistentClassName, AncestorClassName, Identifier: string; var IsDefined: boolean); diff --git a/ide/main.pp b/ide/main.pp index 4f22dcd7ca..750bd43e20 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -493,6 +493,8 @@ type {$ENDIF} FRebuildingCompilerGraphCodeToolsDefinesNeeded: boolean; + + FRenamingComponents: TFPList; // list of TComponents currently renaming protected procedure SetToolStatus(const AValue: TIDEToolStatus); override; function DoResetToolStatus(Interactive: boolean): boolean; @@ -11400,6 +11402,8 @@ var i: integer; NewClassName: string; BossResult: boolean; + AncestorRoot: TComponent; + s: String; procedure ApplyBossResult(const ErrorMsg: string); var @@ -11436,9 +11440,57 @@ var end; end; + + procedure RenameInheritedComponents(RenamedUnit: TUnitInfo; + Simulate: boolean); + var + UsedByDependency: TUnitComponentDependency; + DependingUnit: TUnitInfo; + InheritedComponent: TComponent; + DependingDesigner: TCustomForm; + begin + UsedByDependency:=ActiveUnitInfo.FirstUsedByComponent; + while UsedByDependency<>nil do begin + DependingUnit:=UsedByDependency.UsedByUnit; + if (DependingUnit.Component<>nil) + and (DependingUnit.Component.ClassParent=RenamedUnit.Component.ClassType) + then begin + // the root component inherits from the DependingUnit root component + InheritedComponent:= + DependingUnit.Component.FindComponent(AComponent.Name); + if InheritedComponent<>nil then begin + // inherited component found + if FRenamingComponents=nil then + FRenamingComponents:=TFPList.Create; + FRenamingComponents.Add(InheritedComponent); + try + DebugLn(['RenameInheritedComponents ',dbgsName(InheritedComponent),' Owner=',dbgsName(InheritedComponent.Owner)]); + if Simulate then begin + InheritedComponent.ValidateRename(InheritedComponent, + InheritedComponent.Name,NewName); + end else begin + InheritedComponent.Name:=NewName; + DependingDesigner:=GetDesignerFormOfSource(DependingUnit,false); + if DependingDesigner<>nil then + DependingUnit.Modified:=true; + end; + finally + if FRenamingComponents<>nil then begin + FRenamingComponents.Remove(InheritedComponent); + if FRenamingComponents.Count=0 then + FreeThenNil(FRenamingComponents); + end; + end; + end; + // rename recursively + RenameInheritedComponents(DependingUnit,Simulate); + end; + UsedByDependency:=UsedByDependency.NextUsedByDependency; + end; + end; begin - DebugLn('TMainIDE.OnDesignerRenameComponent Old=',AComponent.Name,':',AComponent.ClassName,' New=',NewName); + DebugLn('TMainIDE.OnDesignerRenameComponent Old=',AComponent.Name,':',AComponent.ClassName,' New=',NewName,' Owner=',dbgsName(AComponent.Owner)); if (not IsValidIdent(NewName)) or (NewName='') then raise Exception.Create(Format(lisComponentNameIsNotAValidIdentifier, ['"', Newname, '"'])); @@ -11446,12 +11498,31 @@ begin // this component was never added to the source. It is a new component. exit; end; + + if (FRenamingComponents<>nil) + and (FRenamingComponents.IndexOf(AComponent)>=0) then begin + // already validated + exit; + end; + BeginCodeTool(ADesigner,ActiveSrcEdit,ActiveUnitInfo,[ctfSwitchToFormSource]); ActiveUnitInfo:=Project1.UnitWithComponent(ADesigner.LookupRoot); if CodeToolBoss.IsKeyWord(ActiveUnitInfo.Source,NewName) then raise Exception.Create(Format(lisComponentNameIsKeyword, ['"', Newname, '"'] )); + // check ancestor component + AncestorRoot:=FormEditor1.GetAncestorLookupRoot(AComponent); + if AncestorRoot<>nil then begin + s:='The component '+dbgsName(AComponent) + +' is inherited from '+dbgsName(AncestorRoot)+'.'#13 + +'To rename an inherited component open the ancestor and rename it there.'; + raise EComponentError.Create(s); + end; + + // check inherited components + RenameInheritedComponents(ActiveUnitInfo,true); + if AComponent=ADesigner.LookupRoot then begin // rename owner component (e.g. the form) @@ -11489,6 +11560,9 @@ begin end else begin RaiseException('TMainIDE.OnDesignerRenameComponent internal error:'+AComponent.Name+':'+AComponent.ClassName); end; + + // rename inherited components + RenameInheritedComponents(ActiveUnitInfo,false); end; procedure TMainIDE.OnDesignerViewLFM(Sender: TObject); diff --git a/ideintf/formeditingintf.pas b/ideintf/formeditingintf.pas index 1dd78b6367..41a03aedf3 100644 --- a/ideintf/formeditingintf.pas +++ b/ideintf/formeditingintf.pas @@ -115,6 +115,10 @@ type ParentControl: TWinControl ): TIComponentInterface; virtual; abstract; + // ancestors + function GetAncestorLookupRoot(AComponent: TComponent): TComponent; virtual; abstract; + function GetAncestorInstance(AComponent: TComponent): TComponent; virtual; abstract; + // designers function DesignerCount: integer; virtual; abstract; property Designer[Index: integer]: TIDesigner read GetDesigner; diff --git a/lcl/include/customnotebook.inc b/lcl/include/customnotebook.inc index 4cf9f0f05c..611dec5c70 100644 --- a/lcl/include/customnotebook.inc +++ b/lcl/include/customnotebook.inc @@ -519,7 +519,8 @@ begin if not (pfAdded in APage.FFlags) then exit; Exclude(APage.FFlags,pfAdded); TWSCustomNotebookClass(WidgetSetClass).RemovePage(Self, APage.PageIndex); - APage.DestroyHandle; + if APage.HandleAllocated then + APage.DestroyHandle; end; end; diff --git a/lcl/interfaces/gtk/gtkwinapi.inc b/lcl/interfaces/gtk/gtkwinapi.inc index 323d888f96..8fe7e1e97c 100644 --- a/lcl/interfaces/gtk/gtkwinapi.inc +++ b/lcl/interfaces/gtk/gtkwinapi.inc @@ -5651,7 +5651,6 @@ end; function TGtkWidgetSet.GetSystemMetrics(nIndex: Integer): Integer; var P : Pointer; - ax,ay,ah,aw : gint; begin Assert(False, Format('Trace:> [TGtkWidgetSet.GetSystemMetrics] %d', [nIndex])); case nIndex of