Browse Source

* Fixed ancestor handling (bug ID 11067)

git-svn-id: trunk@10588 -
michael 17 years ago
parent
commit
d5eec67b53
2 changed files with 106 additions and 7 deletions
  1. 4 1
      rtl/objpas/classes/classesh.inc
  2. 102 6
      rtl/objpas/classes/writer.inc

+ 4 - 1
rtl/objpas/classes/classesh.inc

@@ -1239,7 +1239,7 @@ type
     FDestroyDriver: Boolean;
     FRootAncestor: TComponent;
     FPropPath: String;
-    FAncestorList: TList;
+    FAncestors: TFPList;
     FAncestorPos: Integer;
     FChildPos: Integer;
     FOnFindAncestor: TFindAncestorEvent;
@@ -1247,11 +1247,14 @@ type
     FOnWriteStringProperty:TReadWriteStringPropertyEvent;
     procedure AddToAncestorList(Component: TComponent);
     procedure WriteComponentData(Instance: TComponent);
+    Procedure DetermineAncestor(Component: TComponent);
+    procedure DoFindAncestor(Component : TComponent);
   protected
     procedure SetRoot(ARoot: TComponent); override;
     procedure WriteBinary(AWriteData: TStreamProc);
     procedure WriteProperty(Instance: TPersistent; PropInfo: Pointer);
     procedure WriteProperties(Instance: TPersistent);
+    procedure WriteChildren(Component: TComponent);
     function CreateDriver(Stream: TStream; BufSize: Integer): TAbstractObjectWriter; virtual;
   public
     constructor Create(ADriver: TAbstractObjectWriter);

+ 102 - 6
rtl/objpas/classes/writer.inc

@@ -402,7 +402,7 @@ end;
 // Used as argument for calls to TComponent.GetChildren:
 procedure TWriter.AddToAncestorList(Component: TComponent);
 begin
-  FAncestorList.Add(Component);
+  FAncestors.Add(Component);
 end;
 
 procedure TWriter.DefineProperty(const Name: String;
@@ -495,25 +495,121 @@ begin
   WriteListEnd;
 end;
 
+procedure TWriter.DetermineAncestor(Component : TComponent);
+
+Var
+  S : String;
+  I : Integer;
+  C : TComponent; 
+
+begin
+  // Should be set only when we write an inherited with children.
+  
+  if Not Assigned(FAncestors) then
+    exit;
+  FAncestor:=nil;
+  S:=UpperCase(Component.Name);
+  I:=0;
+  While (FAncestor=Nil) and (I<FAncestors.Count) do
+    begin
+    C:=TComponent(FAncestors[i]);
+    if (S=UpperCase(C.Name)) then
+      FAncestor:=C;
+    Inc(I);
+    end;
+end;
+
+procedure TWriter.DoFindAncestor(Component : TComponent);
+
+Var
+  C : TComponent;
+
+begin
+  if Assigned(FOnFindAncestor) then
+    if (Ancestor=Nil) or (Ancestor is TComponent) then
+      begin
+      C:=TComponent(Ancestor);
+      FOnFindAncestor(Self,Component,Component.Name,C,FRootAncestor);
+      Ancestor:=C;
+      end;
+end;
+
 procedure TWriter.WriteComponent(Component: TComponent);
+
 var
   i : integer;
+  SA : TPersistent;
+  SR : TComponent;
+begin
+  SR:=FRoot;
+  SA:=FAncestor;
+  Try
+    Component.FComponentState:=Component.FComponentState+[csWriting];
+    Try
+      // Possibly set ancestor.
+      DetermineAncestor(Component);
+      DoFindAncestor(Component); // Mainly for IDE when a parent form had an ancestor renamed...
+      // Will call WriteComponentData.
+      Component.WriteState(Self);
+      FDriver.EndList;
+    Finally
+      Component.FComponentState:=Component.FComponentState-[csWriting];
+    end;
+  Finally
+    FAncestor:=SA;
+    FRoot:=SR;
+  end;
+end;
+
+procedure TWriter.WriteChildren(Component : TComponent);
+
+Var
+  SRoot, SRootA : TComponent;
+  SList : TFPList;
 begin
-  Component.FComponentState:=Component.FComponentState+[csWriting];
-  Component.WriteState(Self);
-  Component.GetChildren(@WriteComponent,Root);
-  FDriver.EndList;
-  Component.FComponentState:=Component.FComponentState-[csWriting];
+  // Write children list. 
+  // While writing children, the ancestor environment must be saved
+  // This is recursive...
+  SRoot:=FRoot;
+  SRootA:=FRootAncestor;
+  SList:=FAncestors;
+  try
+    FAncestors:=Nil;
+    if csInline in Component.ComponentState then
+       FRoot:=Component;
+    if (FAncestor is TComponent) then
+       begin
+       FAncestors:=TFPList.Create;
+       if csInline in TComponent(FAncestor).ComponentState then
+         FRootAncestor := TComponent(FAncestor);
+       TComponent(FAncestor).GetChildren(@AddToAncestorList,FRootAncestor);
+       end;
+    try
+      Component.GetChildren(@WriteComponent, FRoot);
+    Finally
+      FreeAndNil(FAncestors);
+    end;    
+  finally
+    FAncestors:=Slist;
+    FRoot:=SRoot;
+    FRootAncestor:=SRootA;
+  end;
 end;
 
 procedure TWriter.WriteComponentData(Instance: TComponent);
 var Dummy: Integer;
     Flags: TFilerFlags;
 begin
+  Dummy:=0;
   Flags := [];
+  If Assigned(FAncestor) then
+    Flags:=[ffInherited];
   FDriver.BeginComponent(Instance,Flags, Dummy);
   WriteProperties(Instance);
   WriteListEnd;
+  // Needs special handling of ancestor.
+  If not IgnoreChildren then
+    WriteChildren(Instance);
 end;
 
 procedure TWriter.WriteDescendent(ARoot: TComponent; AAncestor: TComponent);