mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-16 17:09:21 +02:00
IDE: designer: reading inline streams when putting components on a form
git-svn-id: trunk@15683 -
This commit is contained in:
parent
7d22d4856a
commit
6611e4c5c9
@ -138,13 +138,14 @@ type
|
|||||||
// some useful functions
|
// some useful functions
|
||||||
function GetItem(Index:integer):TComponent;
|
function GetItem(Index:integer):TComponent;
|
||||||
function OnFindGlobalComponent(const AName:AnsiString):TComponent;
|
function OnFindGlobalComponent(const AName:AnsiString):TComponent;
|
||||||
procedure InitReading(BinStream: TStream; var Reader: TReader;
|
procedure InitReading;
|
||||||
DestroyDriver: Boolean); virtual;
|
|
||||||
procedure CreateReader(BinStream: TStream; var Reader: TReader;
|
procedure CreateReader(BinStream: TStream; var Reader: TReader;
|
||||||
DestroyDriver: Boolean); virtual;
|
DestroyDriver: Boolean); virtual;
|
||||||
function DoCreateJITComponent(const NewComponentName, NewClassName,
|
function DoCreateJITComponent(const NewComponentName, NewClassName,
|
||||||
NewUnitName: shortstring; AncestorClass: TClass;
|
NewUnitName: shortstring; AncestorClass: TClass;
|
||||||
Visible: boolean):integer;
|
Visible: boolean):integer;
|
||||||
|
procedure ReadInlineComponent(var Component: TComponent;
|
||||||
|
ComponentClass: TComponentClass; Owner: TComponent);
|
||||||
procedure DoFinishReading; virtual;
|
procedure DoFinishReading; virtual;
|
||||||
procedure HandleException(E: Exception; const Context: string;
|
procedure HandleException(E: Exception; const Context: string;
|
||||||
out Action: TModalResult);
|
out Action: TModalResult);
|
||||||
@ -179,8 +180,9 @@ type
|
|||||||
const NewUnitName: ShortString);
|
const NewUnitName: ShortString);
|
||||||
// child components
|
// child components
|
||||||
function AddJITChildComponentFromStream(JITOwnerComponent: TComponent;
|
function AddJITChildComponentFromStream(JITOwnerComponent: TComponent;
|
||||||
BinStream: TStream; ComponentClass: TComponentClass;
|
BinStream: TStream; ComponentClass: TComponentClass;
|
||||||
ParentControl: TWinControl): TComponent;
|
ParentControl: TWinControl): TComponent;
|
||||||
|
procedure ReadInlineJITChildComponent(Component: TComponent);
|
||||||
public
|
public
|
||||||
property OnReaderError: TJITReaderErrorEvent
|
property OnReaderError: TJITReaderErrorEvent
|
||||||
read FOnReaderError write FOnReaderError;
|
read FOnReaderError write FOnReaderError;
|
||||||
@ -770,7 +772,8 @@ function TJITComponentList.AddJITComponentFromStream(BinStream: TStream;
|
|||||||
|
|
||||||
FCurReadStreamClass:=StreamClass;
|
FCurReadStreamClass:=StreamClass;
|
||||||
DestroyDriver:=false;
|
DestroyDriver:=false;
|
||||||
InitReading(AStream,Reader,DestroyDriver);
|
InitReading;
|
||||||
|
CreateReader(AStream,Reader,DestroyDriver);
|
||||||
{ $IFDEF VerboseJITForms}
|
{ $IFDEF VerboseJITForms}
|
||||||
DebugLn(['TJITComponentList.AddJITComponentFromStream.ReadStream Reading: FCurReadJITComponent=',DbgSName(FCurReadJITComponent),' StreamClass=',DbgSName(StreamClass)]);
|
DebugLn(['TJITComponentList.AddJITComponentFromStream.ReadStream Reading: FCurReadJITComponent=',DbgSName(FCurReadJITComponent),' StreamClass=',DbgSName(StreamClass)]);
|
||||||
{ $ENDIF}
|
{ $ENDIF}
|
||||||
@ -878,8 +881,7 @@ begin
|
|||||||
//DebugLn(dbgsName(CurReadJITComponent), ' FIND global component ', AName, ' ', dbgsName(Result));
|
//DebugLn(dbgsName(CurReadJITComponent), ' FIND global component ', AName, ' ', dbgsName(Result));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TJITComponentList.InitReading(BinStream: TStream;
|
procedure TJITComponentList.InitReading;
|
||||||
var Reader: TReader; DestroyDriver: Boolean);
|
|
||||||
begin
|
begin
|
||||||
FFlags:=FFlags-[jclAutoRenameComponents];
|
FFlags:=FFlags-[jclAutoRenameComponents];
|
||||||
FErrors.Clear;
|
FErrors.Clear;
|
||||||
@ -887,8 +889,6 @@ begin
|
|||||||
MyFindGlobalComponentProc:=@OnFindGlobalComponent;
|
MyFindGlobalComponentProc:=@OnFindGlobalComponent;
|
||||||
RegisterFindGlobalComponentProc(@MyFindGlobalComponent);
|
RegisterFindGlobalComponentProc(@MyFindGlobalComponent);
|
||||||
Application.FindGlobalComponentEnabled:=false;
|
Application.FindGlobalComponentEnabled:=false;
|
||||||
|
|
||||||
CreateReader(BinStream,Reader,DestroyDriver);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TJITComponentList.CreateReader(BinStream: TStream;
|
procedure TJITComponentList.CreateReader(BinStream: TStream;
|
||||||
@ -982,6 +982,90 @@ begin
|
|||||||
Result:=FJITComponents.Add(FCurReadJITComponent);
|
Result:=FJITComponents.Add(FCurReadJITComponent);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TJITComponentList.ReadInlineComponent(var Component: TComponent;
|
||||||
|
ComponentClass: TComponentClass; Owner: TComponent);
|
||||||
|
var
|
||||||
|
DestroyDriver: Boolean;
|
||||||
|
SubReader: TReader;
|
||||||
|
BinStream: TExtMemoryStream;
|
||||||
|
Ancestor: TComponent;
|
||||||
|
Abort: boolean;
|
||||||
|
Ancestors: TFPList;
|
||||||
|
AncestorStreams: TFPList;
|
||||||
|
i: Integer;
|
||||||
|
OldStreamClass: TClass;
|
||||||
|
begin
|
||||||
|
fCurReadChild:=Component;
|
||||||
|
fCurReadChildClass:=ComponentClass;
|
||||||
|
|
||||||
|
if Assigned(OnFindAncestors) then begin
|
||||||
|
Ancestors:=nil;
|
||||||
|
AncestorStreams:=nil;
|
||||||
|
OldStreamClass:=FCurReadStreamClass;
|
||||||
|
try
|
||||||
|
Abort:=false;
|
||||||
|
OnFindAncestors(Self,ComponentClass,Ancestors,AncestorStreams,Abort);
|
||||||
|
if Abort then begin
|
||||||
|
DebugLn(['TJITComponentList.ReadInlineComponent aborted reading ComponentClass=',DbgSName(ComponentClass)]);
|
||||||
|
raise EReadError.Create('TJITComponentList.ReadInlineComponent aborted reading ComponentClass='+DbgSName(ComponentClass));
|
||||||
|
end;
|
||||||
|
if Ancestors<>nil then begin
|
||||||
|
// read ancestor streams
|
||||||
|
Ancestor:=nil;
|
||||||
|
for i:=Ancestors.Count-1 downto 0 do begin
|
||||||
|
BinStream:=TExtMemoryStream(AncestorStreams[i]);
|
||||||
|
FCurReadStreamClass:=TComponent(Ancestors[i]).ClassType;
|
||||||
|
|
||||||
|
DebugLn(['TJITComponentList.ReadInlineComponent Has Stream: ',DbgSName(FCurReadStreamClass)]);
|
||||||
|
// create component
|
||||||
|
if Component=nil then begin
|
||||||
|
DebugLn(['TJITComponentList.ReadInlineComponent creating ',DbgSName(ComponentClass),' Owner=',DbgSName(Owner),' ...']);
|
||||||
|
// allocate memory without running the constructor
|
||||||
|
Component:=TComponent(ComponentClass.newinstance);
|
||||||
|
// set csDesigning
|
||||||
|
SetComponentDesignMode(Component,true);
|
||||||
|
// this is a streamed sub component => set csInline
|
||||||
|
SetComponentInlineMode(Component,true);
|
||||||
|
// now run the constructor
|
||||||
|
Component.Create(Owner);
|
||||||
|
end;
|
||||||
|
// read stream
|
||||||
|
fCurReadChild:=Component;
|
||||||
|
fCurReadChildClass:=ComponentClass;
|
||||||
|
SubReader:=nil;
|
||||||
|
DestroyDriver:=false;
|
||||||
|
try
|
||||||
|
CreateReader(BinStream,SubReader,DestroyDriver);
|
||||||
|
// The stream contains only the diff to the Ancestor instance,
|
||||||
|
// => give it the Ancestor instance
|
||||||
|
SubReader.Ancestor:=Ancestor;
|
||||||
|
SubReader.ReadRootComponent(Component);
|
||||||
|
finally
|
||||||
|
if SubReader<>nil then begin
|
||||||
|
if DestroyDriver then SubReader.Driver.Free;
|
||||||
|
SubReader.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
FCurReadStreamClass:=OldStreamClass;
|
||||||
|
|
||||||
|
// next
|
||||||
|
Ancestor:=TComponent(Ancestors[i]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Ancestors.Free;
|
||||||
|
if AncestorStreams<>nil then
|
||||||
|
for i:=0 to AncestorStreams.Count-1 do
|
||||||
|
TObject(AncestorStreams[i]).Free;
|
||||||
|
AncestorStreams.Free;
|
||||||
|
end;
|
||||||
|
FCurReadStreamClass:=OldStreamClass;
|
||||||
|
fCurReadChild:=Component;
|
||||||
|
fCurReadChildClass:=ComponentClass;
|
||||||
|
end;
|
||||||
|
//debugln(['[TJITComponentList.ReadInlineComponent] Class=',ComponentClass.ClassName,' Component=',dbgsName(Component)]);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TJITComponentList.DoFinishReading;
|
procedure TJITComponentList.DoFinishReading;
|
||||||
begin
|
begin
|
||||||
|
|
||||||
@ -1110,7 +1194,8 @@ begin
|
|||||||
FCurReadStreamClass:=nil;
|
FCurReadStreamClass:=nil;
|
||||||
try
|
try
|
||||||
DestroyDriver:=false;
|
DestroyDriver:=false;
|
||||||
InitReading(BinStream,Reader,DestroyDriver);
|
InitReading;
|
||||||
|
CreateReader(BinStream,Reader,DestroyDriver);
|
||||||
{$IFDEF VerboseJITForms}
|
{$IFDEF VerboseJITForms}
|
||||||
debugln('[TJITComponentList.AddJITChildComponentFromStream] B');
|
debugln('[TJITComponentList.AddJITChildComponentFromStream] B');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -1155,6 +1240,35 @@ begin
|
|||||||
Result:=NewComponent;
|
Result:=NewComponent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TJITComponentList.ReadInlineJITChildComponent(Component: TComponent);
|
||||||
|
var
|
||||||
|
Action: TModalResult;
|
||||||
|
begin
|
||||||
|
FCurReadStreamClass:=nil;
|
||||||
|
InitReading;
|
||||||
|
{ $IFDEF VerboseJITForms}
|
||||||
|
DebugLn(['TJITComponentList.ReadInlineJITChildComponent Reading: ',DbgSName(Component)]);
|
||||||
|
{ $ENDIF}
|
||||||
|
try
|
||||||
|
try
|
||||||
|
ReadInlineComponent(Component,TComponentClass(Component.ClassType),Component.Owner);
|
||||||
|
except
|
||||||
|
on E: Exception do begin
|
||||||
|
HandleException(E,'[TJITComponentList.ReadInlineJITChildComponent] ERROR reading inline stream'
|
||||||
|
+' of "'+DbgSName(Component)+'"',Action);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$IFDEF VerboseJITForms}
|
||||||
|
debugln('[TJITComponentList.ReadInlineJITChildComponent] Finish Reading ...');
|
||||||
|
{$ENDIF}
|
||||||
|
DoFinishReading;
|
||||||
|
finally
|
||||||
|
UnregisterFindGlobalComponentProc(@MyFindGlobalComponent);
|
||||||
|
Application.FindGlobalComponentEnabled:=true;
|
||||||
|
end;
|
||||||
|
FCurReadStreamClass:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
function TJITComponentList.CreateNewMethod(JITComponent: TComponent;
|
function TJITComponentList.CreateNewMethod(JITComponent: TComponent;
|
||||||
const AName: ShortString): TMethod;
|
const AName: ShortString): TMethod;
|
||||||
var
|
var
|
||||||
@ -1626,88 +1740,12 @@ end;
|
|||||||
|
|
||||||
procedure TJITComponentList.ReaderCreateComponent(Reader: TReader;
|
procedure TJITComponentList.ReaderCreateComponent(Reader: TReader;
|
||||||
ComponentClass: TComponentClass; var Component: TComponent);
|
ComponentClass: TComponentClass; var Component: TComponent);
|
||||||
{$IFDEF EnableTFrame}
|
|
||||||
var
|
|
||||||
DestroyDriver: Boolean;
|
|
||||||
SubReader: TReader;
|
|
||||||
BinStream: TExtMemoryStream;
|
|
||||||
Ancestor: TComponent;
|
|
||||||
Abort: boolean;
|
|
||||||
Ancestors: TFPList;
|
|
||||||
AncestorStreams: TFPList;
|
|
||||||
i: Integer;
|
|
||||||
OldStreamClass: TClass;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
begin
|
||||||
fCurReadChild:=Component;
|
fCurReadChild:=Component;
|
||||||
fCurReadChildClass:=ComponentClass;
|
fCurReadChildClass:=ComponentClass;
|
||||||
|
|
||||||
{$IFDEF EnableTFrame}
|
{$IFDEF EnableTFrame}
|
||||||
if Assigned(OnFindAncestors) then begin
|
ReadInlineComponent(Component,ComponentClass,Reader.Owner);
|
||||||
Ancestors:=nil;
|
|
||||||
AncestorStreams:=nil;
|
|
||||||
OldStreamClass:=FCurReadStreamClass;
|
|
||||||
try
|
|
||||||
Abort:=false;
|
|
||||||
OnFindAncestors(Self,ComponentClass,Ancestors,AncestorStreams,Abort);
|
|
||||||
if Abort then begin
|
|
||||||
DebugLn(['TJITComponentList.ReaderCreateComponent aborted reading ComponentClass=',DbgSName(ComponentClass)]);
|
|
||||||
raise EReadError.Create('TJITComponentList.ReaderCreateComponent aborted reading ComponentClass='+DbgSName(ComponentClass));
|
|
||||||
end;
|
|
||||||
if Ancestors<>nil then begin
|
|
||||||
// read ancestor streams
|
|
||||||
Ancestor:=nil;
|
|
||||||
for i:=Ancestors.Count-1 downto 0 do begin
|
|
||||||
BinStream:=TExtMemoryStream(AncestorStreams[i]);
|
|
||||||
FCurReadStreamClass:=TComponent(Ancestors[i]).ClassType;
|
|
||||||
|
|
||||||
DebugLn(['TJITComponentList.ReaderCreateComponent Has Stream: ',DbgSName(FCurReadStreamClass)]);
|
|
||||||
// create component
|
|
||||||
if Component=nil then begin
|
|
||||||
DebugLn(['TJITComponentList.ReaderCreateComponent creating ',DbgSName(ComponentClass),' Owner=',DbgSName(Reader.Owner),' ...']);
|
|
||||||
// allocate memory without running the constructor
|
|
||||||
Component:=TComponent(ComponentClass.newinstance);
|
|
||||||
// set csDesigning
|
|
||||||
SetComponentDesignMode(Component,true);
|
|
||||||
// this is a streamed sub component => set csInline
|
|
||||||
SetComponentInlineMode(Component,true);
|
|
||||||
// now run the constructor
|
|
||||||
Component.Create(Reader.Owner);
|
|
||||||
end;
|
|
||||||
// read stream
|
|
||||||
fCurReadChild:=Component;
|
|
||||||
fCurReadChildClass:=ComponentClass;
|
|
||||||
SubReader:=nil;
|
|
||||||
DestroyDriver:=false;
|
|
||||||
try
|
|
||||||
CreateReader(BinStream,SubReader,DestroyDriver);
|
|
||||||
// The stream contains only the diff to the Ancestor instance,
|
|
||||||
// => give it the Ancestor instance
|
|
||||||
SubReader.Ancestor:=Ancestor;
|
|
||||||
SubReader.ReadRootComponent(Component);
|
|
||||||
finally
|
|
||||||
if SubReader<>nil then begin
|
|
||||||
if DestroyDriver then SubReader.Driver.Free;
|
|
||||||
SubReader.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
FCurReadStreamClass:=OldStreamClass;
|
|
||||||
|
|
||||||
// next
|
|
||||||
Ancestor:=TComponent(Ancestors[i]);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
Ancestors.Free;
|
|
||||||
if AncestorStreams<>nil then
|
|
||||||
for i:=0 to AncestorStreams.Count-1 do
|
|
||||||
TObject(AncestorStreams[i]).Free;
|
|
||||||
AncestorStreams.Free;
|
|
||||||
end;
|
|
||||||
FCurReadStreamClass:=OldStreamClass;
|
|
||||||
fCurReadChild:=Component;
|
|
||||||
fCurReadChildClass:=ComponentClass;
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
//debugln(['[TJITComponentList.ReaderCreateComponent] Class=',ComponentClass.ClassName,' Component=',dbgsName(Component)]);
|
//debugln(['[TJITComponentList.ReaderCreateComponent] Class=',ComponentClass.ClassName,' Component=',dbgsName(Component)]);
|
||||||
end;
|
end;
|
||||||
|
@ -1537,8 +1537,17 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// read inline streams
|
||||||
|
if csInline in NewComponent.ComponentState then begin
|
||||||
|
JITList:=FindJITList(OwnerComponent);
|
||||||
|
if JITList=nil then
|
||||||
|
RaiseException('TCustomFormEditor.CreateComponent '+TypeClass.ClassName);
|
||||||
|
JITList.ReadInlineJITChildComponent(NewComponent);
|
||||||
|
end;
|
||||||
|
|
||||||
// create component interface
|
// create component interface
|
||||||
Temp := TComponentInterface.Create(NewComponent);
|
Temp := TComponentInterface.Create(NewComponent);
|
||||||
|
|
||||||
// calc parent
|
// calc parent
|
||||||
AParent:=nil;
|
AParent:=nil;
|
||||||
if ParentComponent is TControl then begin
|
if ParentComponent is TControl then begin
|
||||||
|
Loading…
Reference in New Issue
Block a user