IDE: implemented registering custom component base classes for designer

git-svn-id: trunk@10458 -
This commit is contained in:
mattias 2007-01-16 18:28:15 +00:00
parent 4716bded24
commit 52796d556e
16 changed files with 453 additions and 57 deletions

9
.gitattributes vendored
View File

@ -1044,6 +1044,15 @@ examples/componentstreaming/componentstreaming.lpr svneol=native#text/plain
examples/componentstreaming/mainunit.lfm svneol=native#text/plain examples/componentstreaming/mainunit.lfm svneol=native#text/plain
examples/componentstreaming/mainunit.lrs svneol=native#text/plain examples/componentstreaming/mainunit.lrs svneol=native#text/plain
examples/componentstreaming/mainunit.pas svneol=native#text/plain examples/componentstreaming/mainunit.pas svneol=native#text/plain
examples/designerbaseclass/README.txt svneol=native#text/plain
examples/designerbaseclass/customcomponentclass.pas svneol=native#text/plain
examples/designerbaseclass/designbaseclassdemopkg.lpk svneol=native#text/plain
examples/designerbaseclass/designbaseclassdemopkg.pas svneol=native#text/plain
examples/designerbaseclass/example/demo1.lpi svneol=native#text/plain
examples/designerbaseclass/example/demo1.lpr svneol=native#text/plain
examples/designerbaseclass/example/unit1.lfm svneol=native#text/plain
examples/designerbaseclass/example/unit1.lrs svneol=native#text/plain
examples/designerbaseclass/example/unit1.pas svneol=native#text/plain
examples/dlgform.pp svneol=native#text/pascal examples/dlgform.pp svneol=native#text/pascal
examples/easter/about.lfm svneol=native#text/plain examples/easter/about.lfm svneol=native#text/plain
examples/easter/about.lrs svneol=native#text/pascal examples/easter/about.lrs svneol=native#text/pascal

View File

@ -22,9 +22,13 @@
Abstract: Abstract:
JITForm - just-in-time form. JITForm - just-in-time form.
This unit contains some of the dirtiest hacks in the lazarus IDE.
Nevertheless they work for year on all platforms and make many things
much easier.
Forms are the most common resources/design items in the IDE, hence the name. Forms are the most common resources/design items in the IDE, hence the name.
Of course any TComponent descendant can be editid but naming it Why the tricks: Of course any TComponent descendant can be edited
'JITComponent' would confuse new developers. but naming it 'JITComponent' would confuse new developers.
Because the IDE does wild things with forms and datamodules, like creating Because the IDE does wild things with forms and datamodules, like creating
an own class for each opened form/datamodule and dynamically creating an own class for each opened form/datamodule and dynamically creating

View File

@ -77,12 +77,10 @@ type
TJITComponentList = class(TPersistentWithTemplates) TJITComponentList = class(TPersistentWithTemplates)
private private
FComponentPrefix: string;
FCurUnknownClass: string; FCurUnknownClass: string;
FCurUnknownProperty: string; FCurUnknownProperty: string;
FErrors: TLRPositionLinks; FErrors: TLRPositionLinks;
FOnPropertyNotFound: TJITPropertyNotFoundEvent; FOnPropertyNotFound: TJITPropertyNotFoundEvent;
procedure SetComponentPrefix(const AValue: string);
protected protected
FCurReadErrorMsg: string; FCurReadErrorMsg: string;
FCurReadJITComponent:TComponent; FCurReadJITComponent:TComponent;
@ -178,8 +176,6 @@ type
property CurReadErrorMsg: string read FCurReadErrorMsg; property CurReadErrorMsg: string read FCurReadErrorMsg;
property CurUnknownProperty: string read FCurUnknownProperty; property CurUnknownProperty: string read FCurUnknownProperty;
property CurUnknownClass: string read FCurUnknownClass; property CurUnknownClass: string read FCurUnknownClass;
property ComponentPrefix: string read FComponentPrefix
write SetComponentPrefix;
property Errors: TLRPositionLinks read FErrors; property Errors: TLRPositionLinks read FErrors;
end; end;
@ -190,7 +186,6 @@ type
private private
function GetItem(Index: integer): TForm; function GetItem(Index: integer): TForm;
public public
constructor Create;
function IsJITForm(AComponent: TComponent): boolean; function IsJITForm(AComponent: TComponent): boolean;
property Items[Index:integer]: TForm read GetItem; default; property Items[Index:integer]: TForm read GetItem; default;
end; end;
@ -200,7 +195,6 @@ type
TJITNonFormComponents = class(TJITComponentList) TJITNonFormComponents = class(TJITComponentList)
public public
constructor Create;
function IsJITNonForm(AComponent: TComponent): boolean; function IsJITNonForm(AComponent: TComponent): boolean;
end; end;
@ -339,7 +333,7 @@ type
end; end;
var var
TComponentValidateRenameOffset: LongInt; TComponentValidateRenameOffset: LongInt = 0;
procedure TComponentWithOverrideValidateRename.ValidateRename( procedure TComponentWithOverrideValidateRename.ValidateRename(
AComponent: TComponent; const CurName, NewName: string); AComponent: TComponent; const CurName, NewName: string);
@ -543,7 +537,6 @@ end;
constructor TJITComponentList.Create; constructor TJITComponentList.Create;
begin begin
inherited Create; inherited Create;
FComponentPrefix:='Form';
FJITComponents:=TList.Create; FJITComponents:=TList.Create;
FErrors:=TLRPositionLinks.Create; FErrors:=TLRPositionLinks.Create;
end; end;
@ -633,11 +626,15 @@ end;
procedure TJITComponentList.GetUnusedNames( procedure TJITComponentList.GetUnusedNames(
var ComponentName,ComponentClassName:shortstring); var ComponentName,ComponentClassName:shortstring);
var a:integer; var a:integer;
ComponentPrefix: String;
begin begin
a:=1; a:=1;
ComponentPrefix:=ComponentClassName;
if ComponentPrefix[1] in ['t','T'] then
ComponentPrefix:=copy(ComponentPrefix,2,length(ComponentPrefix));
repeat repeat
ComponentName:=ComponentPrefix+IntToStr(a); ComponentName:=ComponentPrefix+IntToStr(a);
ComponentClassName:='T'+ComponentPrefix+IntToStr(a); ComponentClassName:='T'+ComponentName;
inc(a); inc(a);
until (FindComponentByName(ComponentName)<0) until (FindComponentByName(ComponentName)<0)
and (FindComponentByClassName(ComponentClassName)<0); and (FindComponentByClassName(ComponentClassName)<0);
@ -1003,12 +1000,6 @@ begin
Result.Code:=NewCode; Result.Code:=NewCode;
end; end;
procedure TJITComponentList.SetComponentPrefix(const AValue: string);
begin
if FComponentPrefix=AValue then exit;
FComponentPrefix:=AValue;
end;
function TJITComponentList.CreateNewJITClass(ParentClass: TClass; function TJITComponentList.CreateNewJITClass(ParentClass: TClass;
const NewClassName, NewUnitName: ShortString): TClass; const NewClassName, NewUnitName: ShortString): TClass;
// Create a new class (vmt, virtual method table, field table and typeinfo) // Create a new class (vmt, virtual method table, field table and typeinfo)
@ -1081,7 +1072,7 @@ begin
then then
raise Exception.Create('CreateNewClass new aligned TypeData'); raise Exception.Create('CreateNewClass new aligned TypeData');
// set TypeData (PropCount is the total number of properties) // set TypeData (PropCount is the total number of properties, including ancestors)
NewTypeData^.ClassType:=TClass(NewVMT); NewTypeData^.ClassType:=TClass(NewVMT);
NewTypeData^.ParentInfo:=ParentClass.ClassInfo; NewTypeData^.ParentInfo:=ParentClass.ClassInfo;
NewTypeData^.PropCount:=GetTypeData(NewTypeData^.ParentInfo)^.PropCount; NewTypeData^.PropCount:=GetTypeData(NewTypeData^.ParentInfo)^.PropCount;
@ -1094,7 +1085,7 @@ begin
Pointer(NewVMT+vmtMethodStart)^, Pointer(NewVMT+vmtMethodStart)^,
vmtTailSize); vmtTailSize);
// override 'ValidateRename' for TComponent descendents // override 'ValidateRename' for TComponent descendants
if ParentClass.InheritsFrom(TComponent) then begin if ParentClass.InheritsFrom(TComponent) then begin
Pointer(Pointer(NewVMT+TComponentValidateRenameOffset)^):= Pointer(Pointer(NewVMT+TComponentValidateRenameOffset)^):=
@TComponentWithOverrideValidateRename.ValidateRename; @TComponentWithOverrideValidateRename.ValidateRename;
@ -1424,12 +1415,6 @@ end;
{ TJITForms } { TJITForms }
constructor TJITForms.Create;
begin
inherited Create;
FComponentPrefix:='Form';
end;
function TJITForms.IsJITForm(AComponent: TComponent): boolean; function TJITForms.IsJITForm(AComponent: TComponent): boolean;
begin begin
Result:=(AComponent<>nil) and (AComponent is TForm) Result:=(AComponent<>nil) and (AComponent is TForm)
@ -1443,12 +1428,6 @@ end;
{ TJITNonFormComponents } { TJITNonFormComponents }
constructor TJITNonFormComponents.Create;
begin
inherited Create;
FComponentPrefix:='DataModule';
end;
function TJITNonFormComponents.IsJITNonForm(AComponent: TComponent): boolean; function TJITNonFormComponents.IsJITNonForm(AComponent: TComponent): boolean;
begin begin
Result:=(AComponent<>nil) and (not (AComponent is TForm)) Result:=(AComponent<>nil) and (not (AComponent is TForm))

View File

@ -0,0 +1,11 @@
This demonstrates how to add a new component base class for the designer.
Normally the IDE knows only TForm and TDataModule as base classes.
All components that can be designed in the IDE must descend form one of these
classes.
Quick start:
Install the package DesignBaseClassDemoPkg in the IDE and restart it.
Then open the project example/demo1.lpi

View File

@ -0,0 +1,93 @@
{
*****************************************************************************
* *
* This file is part of the Lazarus Component Library (LCL) *
* *
* See the file COPYING.modifiedLGPL, included in this distribution, *
* for details about the copyright. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*****************************************************************************
Author: Mattias Gaertner
Abtract:
Registers a new designer base class (like TForm or TDataModul) in the IDE.
}
unit CustomComponentClass;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LCLProc, Forms, FormEditingIntf;
type
{ TMyComponentClass }
TMyComponentClass = class(TComponent)
private
FDemoProperty: integer;
protected
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
public
constructor Create(TheOwner: TComponent); override;
published
property DemoProperty: integer read FDemoProperty write FDemoProperty;
end;
procedure Register;
implementation
procedure Register;
begin
FormEditingHook.RegisterDesignerBaseClass(TMyComponentClass);
end;
{ TMyComponentClass }
procedure TMyComponentClass.GetChildren(Proc: TGetChildProc; Root: TComponent);
// this method is called by TWriter to retrieve the child components to write
var
I: Integer;
OwnedComponent: TComponent;
begin
DebugLn(['TMyComponentClass.GetChildren ComponentCount=',ComponentCount]);
inherited GetChildren(Proc, Root);
if Root = Self then begin
for I := 0 to ComponentCount - 1 do
begin
OwnedComponent := Components[I];
if not OwnedComponent.HasParent then Proc(OwnedComponent);
end;
end;
end;
constructor TMyComponentClass.Create(TheOwner: TComponent);
// init the component with an IDE resource
begin
DebugLn(['TMyComponentClass.Create ',DbgSName(TheOwner)]);
GlobalNameSpace.BeginWrite;
try
inherited Create(TheOwner);
if (ClassType <> TMyComponentClass) and not (csDesigning in ComponentState)
then begin
if not InitResourceComponent(Self, TDataModule) then begin
raise EResNotFound.Create('Resource missing for class '+ClassName);
end;
end;
finally
GlobalNameSpace.EndWrite;
end;
end;
end.

View File

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<CONFIG>
<Package Version="2">
<Name Value="DesignBaseClassDemoPkg"/>
<CompilerOptions>
<Version Value="5"/>
<SearchPaths>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<CodeGeneration>
<Generate Value="Faster"/>
</CodeGeneration>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Files Count="2">
<Item1>
<Filename Value="customcomponentclass.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="CustomComponentClass"/>
</Item1>
<Item2>
<Filename Value="README.txt"/>
<Type Value="Text"/>
</Item2>
</Files>
<Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="2">
<Item1>
<PackageName Value="IDEIntf"/>
</Item1>
<Item2>
<PackageName Value="FCL"/>
<MinVersion Major="1" Valid="True"/>
</Item2>
</RequiredPkgs>
<UsageOptions>
<UnitPath Value="$(PkgOutDir)"/>
</UsageOptions>
<PublishOptions>
<Version Value="2"/>
<IgnoreBinaries Value="False"/>
</PublishOptions>
</Package>
</CONFIG>

View File

@ -0,0 +1,21 @@
{ This file was automatically created by Lazarus. Do not edit!
This source is only used to compile and install the package.
}
unit DesignBaseClassDemoPkg;
interface
uses
CustomComponentClass, LazarusPackageIntf;
implementation
procedure Register;
begin
RegisterUnit('CustomComponentClass', @CustomComponentClass.Register);
end;
initialization
RegisterPackage('DesignBaseClassDemoPkg', @Register);
end.

View File

@ -0,0 +1,66 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<PathDelim Value="/"/>
<Version Value="5"/>
<General>
<SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/>
<IconPath Value="./"/>
<TargetFileExt Value=""/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="LCL"/>
</Item1>
<Item2>
<PackageName Value="DesignBaseClassDemoPkg"/>
<MinVersion Valid="True"/>
</Item2>
</RequiredPackages>
<Units Count="2">
<Unit0>
<Filename Value="demo1.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="Demo1"/>
</Unit0>
<Unit1>
<Filename Value="unit1.pas"/>
<ComponentName Value="MyComponent1"/>
<IsPartOfProject Value="True"/>
<ResourceFilename Value="unit1.lrs"/>
<UnitName Value="Unit1"/>
</Unit1>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="5"/>
<CodeGeneration>
<Generate Value="Faster"/>
</CodeGeneration>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</CONFIG>

View File

@ -0,0 +1,16 @@
program Demo1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, Unit1, DesignBaseClassDemoPkg;
begin
Application.Initialize;
Application.Run;
end.

View File

@ -0,0 +1,10 @@
object MyComponent1: TMyComponent1
left = 302
top = 594
object OpenDialog1: TOpenDialog
Title = 'Open existing file'
FilterIndex = 0
left = 91
top = 87
end
end

View File

@ -0,0 +1,7 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TMyComponent1','FORMDATA',[
'TPF0'#13'TMyComponent1'#12'MyComponent1'#4'left'#3'.'#1#3'top'#3'R'#2#0#11'T'
+'OpenDialog'#11'OpenDialog1'#5'Title'#6#18'Open existing file'#11'FilterInde'
+'x'#2#0#4'left'#2'['#3'top'#2'W'#0#0#0
]);

View File

@ -0,0 +1,57 @@
{
*****************************************************************************
* *
* This file is part of the Lazarus Component Library (LCL) *
* *
* See the file COPYING.modifiedLGPL, included in this distribution, *
* for details about the copyright. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*****************************************************************************
Author: Mattias Gaertner
Important:
Before you open the designer of this unit, you must install the package
DesignBaseClassDemoPkg, because it registers the TMyComponentClass.
Read the README.txt.
Abstract:
When you open the designer, you can see the property 'DemoProperty' in the
Object Inspector. This property ws inherited from TMyComponentClass.
}
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
CustomComponentClass;
type
{ TMyComponent1 }
TMyComponent1 = class(TMyComponentClass)
OpenDialog1: TOpenDialog;
private
{ private declarations }
public
{ public declarations }
end;
var
MyComponent1: TMyComponent1;
implementation
initialization
{$I unit1.lrs}
end.

View File

@ -117,6 +117,7 @@ each control that's dropped onto the form
FObj_Inspector: TObjectInspector; FObj_Inspector: TObjectInspector;
FDefineProperties: TAVLTree;// tree of TDefinePropertiesCacheItem FDefineProperties: TAVLTree;// tree of TDefinePropertiesCacheItem
FStandardDefinePropertiesRegistered: Boolean; FStandardDefinePropertiesRegistered: Boolean;
FDesignerBaseClasses: TFPList; // list of TComponentClass
function GetPropertyEditorHook: TPropertyEditorHook; function GetPropertyEditorHook: TPropertyEditorHook;
function FindDefinePropertyNode(const APersistentClassName: string function FindDefinePropertyNode(const APersistentClassName: string
): TAVLTreeNode; ): TAVLTreeNode;
@ -131,11 +132,12 @@ each control that's dropped onto the form
Instance: TPersistent; var PropName: string; IsPath: boolean; Instance: TPersistent; var PropName: string; IsPath: boolean;
var Handled, Skip: Boolean); var Handled, Skip: Boolean);
function GetDesignerBaseClasses(Index: integer): TComponentClass; override;
procedure OnDesignerMenuItemClick(Sender: TObject); virtual; procedure OnDesignerMenuItemClick(Sender: TObject); virtual;
function FindNonControlFormNode(LookupRoot: TComponent): TAVLTreeNode; function FindNonControlFormNode(LookupRoot: TComponent): TAVLTreeNode;
public public
JITFormList: TJITForms;// designed forms JITFormList: TJITForms;// designed forms
JITNonFormList: TJITNonFormComponents;// designed data modules JITNonFormList: TJITNonFormComponents;// designed custom components like data modules
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
@ -226,6 +228,11 @@ each control that's dropped onto the form
// ancestors // ancestors
function GetAncestorLookupRoot(AComponent: TComponent): TComponent; override; function GetAncestorLookupRoot(AComponent: TComponent): TComponent; override;
function GetAncestorInstance(AComponent: TComponent): TComponent; override; function GetAncestorInstance(AComponent: TComponent): TComponent; override;
function RegisterDesignerBaseClass(AClass: TComponentClass): integer; override;
function DesignerBaseClassCount: Integer; override;
procedure UnregisterDesignerBaseClass(AClass: TComponentClass); override;
function IndexOfDesignerBaseClass(AClass: TComponentClass): integer; override;
function FindDesignerBaseClassByName(const AClassName: shortstring): TComponentClass; override;
// define properties // define properties
procedure FindDefineProperty(const APersistentClassName, procedure FindDefineProperty(const APersistentClassName,
@ -288,6 +295,12 @@ each control that's dropped onto the form
property Target: TPersistent read FTarget; property Target: TPersistent read FTarget;
end; end;
const
StandardDesignerBaseClasses: array[1..2] of TComponentClass = (
Forms.TForm,
{$IFNDEF UseFCLDataModule}Forms.{$ENDIF}TDataModule
);
function CompareComponentInterfaces(Data1, Data2: Pointer): integer; function CompareComponentInterfaces(Data1, Data2: Pointer): integer;
@ -782,12 +795,18 @@ end;
{ TCustomFormEditor } { TCustomFormEditor }
constructor TCustomFormEditor.Create; constructor TCustomFormEditor.Create;
var
l: Integer;
begin begin
inherited Create; inherited Create;
FComponentInterfaces := TAVLTree.Create(@CompareComponentInterfaces); FComponentInterfaces := TAVLTree.Create(@CompareComponentInterfaces);
FNonControlForms:=TAVLTree.Create(@CompareNonControlDesignerForms); FNonControlForms:=TAVLTree.Create(@CompareNonControlDesignerForms);
FSelection := TPersistentSelectionList.Create; FSelection := TPersistentSelectionList.Create;
FDesignerBaseClasses:=TFPList.Create;
for l:=Low(StandardDesignerBaseClasses) to High(StandardDesignerBaseClasses)
do
FDesignerBaseClasses.Add(StandardDesignerBaseClasses[l]);
JITFormList := TJITForms.Create; JITFormList := TJITForms.Create;
JITFormList.OnReaderError:=@JITListReaderError; JITFormList.OnReaderError:=@JITListReaderError;
JITFormList.OnPropertyNotFound:=@JITListPropertyNotFound; JITFormList.OnPropertyNotFound:=@JITListPropertyNotFound;
@ -811,6 +830,7 @@ begin
end; end;
FreeAndNil(JITFormList); FreeAndNil(JITFormList);
FreeAndNil(JITNonFormList); FreeAndNil(JITNonFormList);
FreeAndNil(FDesignerBaseClasses);
FreeAndNil(FComponentInterfaces); FreeAndNil(FComponentInterfaces);
FreeAndNil(FSelection); FreeAndNil(FSelection);
FreeAndNil(FNonControlForms); FreeAndNil(FNonControlForms);
@ -1440,6 +1460,12 @@ Begin
end end
else begin else begin
// non TControl // non TControl
if CompWidth<=0 then CompWidth:=50;
if CompHeight<=0 then CompHeight:=50;
if CompLeft<0 then
CompLeft:=Max(1,Min(250,Screen.Width-CompWidth-50));
if CompTop<0 then
CompTop:=Max(1,Min(250,Screen.Height-CompHeight-50));
with LongRec(Temp.Component.DesignInfo) do begin with LongRec(Temp.Component.DesignInfo) do begin
Lo:=word(Min(32000,CompLeft)); Lo:=word(Min(32000,CompLeft));
Hi:=word(Min(32000,CompTop)); Hi:=word(Min(32000,CompTop));
@ -1591,6 +1617,51 @@ begin
Result:=FindJITComponentByClass(TComponentClass(AComponent.ClassParent)); Result:=FindJITComponentByClass(TComponentClass(AComponent.ClassParent));
end; end;
function TCustomFormEditor.RegisterDesignerBaseClass(AClass: TComponentClass
): integer;
begin
if AClass=nil then
RaiseGDBException('TCustomFormEditor.RegisterDesignerBaseClass');
Result:=FDesignerBaseClasses.IndexOf(AClass);
if Result<0 then
Result:=FDesignerBaseClasses.Add(AClass)
end;
function TCustomFormEditor.DesignerBaseClassCount: Integer;
begin
Result:=FDesignerBaseClasses.Count;
end;
procedure TCustomFormEditor.UnregisterDesignerBaseClass(AClass: TComponentClass
);
var
l: Integer;
begin
for l:=Low(StandardDesignerBaseClasses) to High(StandardDesignerBaseClasses)
do
if StandardDesignerBaseClasses[l]=AClass then
RaiseGDBException('TCustomFormEditor.UnregisterDesignerBaseClass');
FDesignerBaseClasses.Remove(AClass);
end;
function TCustomFormEditor.IndexOfDesignerBaseClass(AClass: TComponentClass
): integer;
begin
Result:=FDesignerBaseClasses.IndexOf(AClass);
end;
function TCustomFormEditor.FindDesignerBaseClassByName(
const AClassName: shortstring): TComponentClass;
var
i: Integer;
begin
for i:=FDesignerBaseClasses.Count-1 downto 0 do begin
Result:=DesignerBaseClasses[i];
if CompareText(Result.ClassName,AClassName)=0 then exit;
end;
Result:=nil;
end;
procedure TCustomFormEditor.FindDefineProperty( procedure TCustomFormEditor.FindDefineProperty(
const APersistentClassName, AncestorClassName, Identifier: string; const APersistentClassName, AncestorClassName, Identifier: string;
var IsDefined: boolean); var IsDefined: boolean);
@ -1630,6 +1701,7 @@ var
function GetDefinePersistent(const AClassName: string): Boolean; function GetDefinePersistent(const AClassName: string): Boolean;
var var
APersistentClass: TPersistentClass; APersistentClass: TPersistentClass;
AncestorClass: TComponentClass;
begin begin
Result:=false; Result:=false;
@ -1663,12 +1735,11 @@ var
end; end;
// try default classes // try default classes
if (APersistent=nil) and (CompareText(AClassName,'TDataModule')=0) then if (APersistent=nil) then begin
begin AncestorClass:=FindDesignerBaseClassByName(AClassName);
if not CreateTempPersistent(TDataModule) then exit; if AncestorClass<>nil then begin
end; if not CreateTempPersistent(AncestorClass) then exit;
if (APersistent=nil) and (CompareText(AClassName,'TForm')=0) then begin end;
if not CreateTempPersistent(TForm) then exit;
end; end;
Result:=true; Result:=true;
@ -1793,14 +1864,14 @@ var
JITComponentList: TJITComponentList; JITComponentList: TJITComponentList;
begin begin
JITComponentList:=TJITComponentList(Sender); JITComponentList:=TJITComponentList(Sender);
aCaption:='Error reading '+JITComponentList.ComponentPrefix; aCaption:='Error reading '+JITComponentList.ClassName;
aMsg:=''; aMsg:='';
DlgType:=mtError; DlgType:=mtError;
Buttons:=[mbCancel]; Buttons:=[mbCancel];
HelpCtx:=0; HelpCtx:=0;
with JITComponentList do begin with JITComponentList do begin
aMsg:=aMsg+ComponentPrefix+': '; aMsg:=aMsg+ClassName+': ';
if CurReadJITComponent<>nil then if CurReadJITComponent<>nil then
aMsg:=aMsg+CurReadJITComponent.Name+':'+CurReadJITComponent.ClassName aMsg:=aMsg+CurReadJITComponent.Name+':'+CurReadJITComponent.ClassName
else else
@ -1876,6 +1947,12 @@ begin
'" IsPath=',BoolToStr(IsPath)); '" IsPath=',BoolToStr(IsPath));
end; end;
function TCustomFormEditor.GetDesignerBaseClasses(Index: integer
): TComponentClass;
begin
Result:=TComponentClass(FDesignerBaseClasses[Index]);
end;
function TCustomFormEditor.GetPropertyEditorHook: TPropertyEditorHook; function TCustomFormEditor.GetPropertyEditorHook: TPropertyEditorHook;
begin begin
Result:=Obj_Inspector.PropertyEditorHook; Result:=Obj_Inspector.PropertyEditorHook;

View File

@ -4924,7 +4924,7 @@ begin
case Result of case Result of
mrAbort: exit; mrAbort: exit;
mrOk: mrOk:
begin if AncestorUnitInfo<>nil then begin
Result:=DoSaveUnitComponentToBinStream(AncestorUnitInfo, Result:=DoSaveUnitComponentToBinStream(AncestorUnitInfo,
AncestorBinStream); AncestorBinStream);
if Result<>mrOk then exit; if Result<>mrOk then exit;
@ -5212,18 +5212,12 @@ var
end; end;
function TryRegisteredClasses(out TheModalResult: TModalResult): boolean; function TryRegisteredClasses(out TheModalResult: TModalResult): boolean;
var
APersistentClass: TPersistentClass;
begin begin
Result:=false; Result:=false;
APersistentClass:=Classes.GetClass(AComponentClassName); AComponentClass:=
if APersistentClass=nil then exit; FormEditor1.FindDesignerBaseClassByName(AComponentClassName);
if not APersistentClass.InheritsFrom(TComponent) then exit; if AComponentClass<>nil then begin
AComponentClass:=TComponentClass(APersistentClass); DebugLn(['TMainIDE.DoLoadComponentDependencyHidden.TryRegisteredClasses found: ',AComponentClass.ClassName]);
if AComponentClass.InheritsFrom(TForm)
or AComponentClass.InheritsFrom(TDataModule) then begin
// at the moment the designer only supports descendants
// of TForm and TDataModule
TheModalResult:=mrOk; TheModalResult:=mrOk;
Result:=true; Result:=true;
end; end;
@ -5259,7 +5253,10 @@ begin
if TryUnit(ComponentUnitInfo.Filename,Result,false) then exit; if TryUnit(ComponentUnitInfo.Filename,Result,false) then exit;
end; end;
// then search in used units // then try registered classes
if TryRegisteredClasses(Result) then exit;
// finally search in used units
UsedUnitFilenames:=nil; UsedUnitFilenames:=nil;
try try
if not CodeToolBoss.FindUsedUnitFiles(AnUnitInfo.Source,UsedUnitFilenames) if not CodeToolBoss.FindUsedUnitFiles(AnUnitInfo.Source,UsedUnitFilenames)
@ -5294,9 +5291,6 @@ begin
UsedUnitFilenames.Free; UsedUnitFilenames.Free;
end; end;
// finally try registered classes
if TryRegisteredClasses(Result) then exit;
Result:=QuestionDlg(lisCodeTemplError, Format( Result:=QuestionDlg(lisCodeTemplError, Format(
lisUnableToFindTheUnitOfComponentClass, ['"', AComponentClassName, '"']), lisUnableToFindTheUnitOfComponentClass, ['"', AComponentClassName, '"']),
mtError, [mrCancel, lisCancelLoadingThisComponent, mtError, [mrCancel, lisCancelLoadingThisComponent,

View File

@ -88,6 +88,7 @@ type
TAbstractFormEditor = class TAbstractFormEditor = class
protected protected
function GetDesignerBaseClasses(Index: integer): TComponentClass; virtual; abstract;
function GetDesigner(Index: integer): TIDesigner; virtual; abstract; function GetDesigner(Index: integer): TIDesigner; virtual; abstract;
public public
// components // components
@ -118,6 +119,12 @@ type
// ancestors // ancestors
function GetAncestorLookupRoot(AComponent: TComponent): TComponent; virtual; abstract; function GetAncestorLookupRoot(AComponent: TComponent): TComponent; virtual; abstract;
function GetAncestorInstance(AComponent: TComponent): TComponent; virtual; abstract; function GetAncestorInstance(AComponent: TComponent): TComponent; virtual; abstract;
function RegisterDesignerBaseClass(AClass: TComponentClass): integer; virtual; abstract;
function DesignerBaseClassCount: Integer; virtual; abstract;
property DesignerBaseClasses[Index: integer]: TComponentClass read GetDesignerBaseClasses;
procedure UnregisterDesignerBaseClass(AClass: TComponentClass); virtual; abstract;
function IndexOfDesignerBaseClass(AClass: TComponentClass): integer; virtual; abstract;
function FindDesignerBaseClassByName(const AClassName: shortstring): TComponentClass; virtual; abstract;
// designers // designers
function DesignerCount: integer; virtual; abstract; function DesignerCount: integer; virtual; abstract;

View File

@ -406,7 +406,6 @@ const
procedure InternalInit; procedure InternalInit;
var var
c: TClipboardType; c: TClipboardType;
cr: TCursor;
begin begin
gtk_handler_quark := g_quark_from_static_string('gtk-signal-handlers'); gtk_handler_quark := g_quark_from_static_string('gtk-signal-handlers');