OTA - Implementing a Form Creator

Implementing an IOTAModuleCreator is similar to the implementation of an IOTAProjectCreator. The IOTACreator interface implementation is the same except there are new Creator Types available for default Module creation. These have the same limitation and issues and in the Project Creator.

IOTACreator = interface(IUnknown)
  ['{6EDB9B9E-F57A-11D1-AB23-00C04FB16FB3}']
  function GetCreatorType: string;
  function GetExisting: Boolean;
  function GetFileSystem: string;
  function GetOwner: IOTAModule;
  function GetUnnamed: Boolean;
end;

IOTAModuleCreator = interface(IOTACreator)
  ['{6EDB9B9A-F57A-11D1-AB23-00C04FB16FB3}']
  function GetAncestorName: string;
  function GetImplFileName: string;
  function GetIntfFileName: string;
  function GetFormName: string;
  function GetMainForm: Boolean;
  function GetShowForm: Boolean;
  function GetShowSource: Boolean;
  function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
  function NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
  procedure FormCreated(const FormEditor: IOTAFormEditor);

  property AncestorName: string read GetAncestorName;
  property FormName: string read GetFormName;
  property ImplFileName: string read GetImplFileName;
  property IntfFileName: string read GetIntfFileName;
  property MainForm: Boolean read GetMainForm;
  property ShowForm: Boolean read GetShowForm;
  property ShowSource: Boolean read GetShowSource;
  end;

 

IOTACreator


function IOTACreator.GetCreatorType: string;

  This method informs the IDE as to what type of project you would like to create. The valid choices are:

  • sForm - Creates a default Form (Later version of Delphi create a Form using multi-platform units)

  • sUnit - Creates a default Unit.
  • sText - Creates a text file

  Note here you should not return an Empty String.  Then in the NewImplSource method you have the option to return an IOTAFile.

function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;

  Returning an IOTAFile is how you define your own contents of the file.

If using a later version of Delphi the predefined constants will create a cross platform Module. For instance creating a sForm will cause the code to contain the QDialogs unit instead of the Dialogs unit, meaning that for cases where the Wizard needs to support Win32 only you will be returning an empty string and creating your own IOTAFile with the source code.


function IOTACreator.GetExisting: Boolean;

  This method informs the IDE if the module is existing. Typically when creating a new object the object does not exist so the normal return value is False. The catch here is a object may have multiple Owner Modules so I am assuming that a "creation" in this case means the object exists and it is now a shared resource between more than one Module. I have not seen an example of this in my testing.

There is one pitfall to this. If you look at the IOTAModuleCreator.GetImplFileName method it appears that you could use this method to tell the IDE that the file does not exist and to create the it using the file name returned in the other method. This does not work. By doing this you are creating a cooperation of methods across interfaces (IOTACreator and IOTAModuleCreator) which should not be (and is not) done. See IOTAModuleCreator.GetImplFileName for more information.

For a Module the only time this is valid to have True is if you currently have a valid Project Module handle to return in IOTACreator.GetOwner.


function IOTACreator.GetFileSystem: string;

  Returns the IDString of the FileSystem to use for this module source. File Systems are an advanced topic that are more suited for IDE Editor enhancements. Typically an empty string is returned.


function IOTACreator.GetOwner: IOTAModule;

  Returns the Module that will be the owner of the new object being created. For example if the object being created is a Form then the owner would be the Project. If the object being created is a Project Module then the owner would be the Project Group.


function IOTACreator.GetUnnamed: Boolean;

  By returning true the IDE will show the Save As.. dialog box when the user tries to save the object for the first time.


 

IOTAModuleCreator


function GetAncestorName: string;

  Returns the Ancestor that the Form will be derived from. If you return an empty string the IDE will substitute the default name for the ancestor of the particular Creator Type.

  For instance in the following snippet of code the Ancestor name is "Form".

  TForm1 = class(TForm)
  end;

  This means you have control over what Form class your Form Creator descends from. The make a decedent of TDataModule you would return

  Result := 'DataModule';

from this method. The same hold for any custom TForms that are registered with the IDE. This is a very powerful and useful method.

  In the NewImplSource and NewIntfSource methods this will be the name that is passed in the AncestorIdent parameter.

Notice you do not include the leading "T". This is a convention not a rule and the implementer is not required to start types with a leading "T".



function GetImplFileName: string;

  Return a fully qualified file name of the implementation source that already exists. This is exactly like the IOTAProjectCreator.GetFileName method with the same warnings. Similar to this:

Useless Error

Delphi and C++Builder. Implementation (Impl) and Interface (Intf) do not correspond to the similarly named sections of a Delphi unit. In this method the file that is returned should be a fully compilable file in Delphi. The difference is in C++Builder where it needs an interface file as well.

You can not use this method to suggest a name for the new Module, it is only valid if the Module is to be associated with a file that already exists. It may not necessarily mean the file is on the disk depending on what type of file system is returned, although this is pure speculation as I have never tried it.

To summarize

  • Only use the defined constants if you want to create default projects where the IDE creates the code.

  • If you want to define the code through an IOTAFile then return an empty string in this method.

  • If using a later version of Delphi the predefined constants will create a cross platform Module. For instance creating a sForm will cause the code to contain the QDialogs unit instead of the Dialogs unit, meaning that for cases where the Wizard needs to support Win32 only you will be returning an empty string and creating your own IOTAFile with the source code.



function GetIntfFileName: string;

  Return a fully qualified file name of the interface source that already exists. The same warning that are discussed in GetImplFileName apply.

C++Builder Only. Implementation (Impl) and Interface (Intf), do not correspond to the similarly named sections of a Delphi unit.

You can not use this method to suggest a name for the new Module, it is only valid if the Module is to be associated with a file that already exists. It may not necessarily mean the file is on the disk depending on what type of file system is returned, although this is pure speculation as I have never tried it.



function GetFormName: string;

  Returns the name that will be used for the Form. If you return an empty string the IDE will substitute the default name for the particular Creator Type

  For instance in the following snippet of code the Form name is "Form1".

  TForm1 = class(TForm)
  end;

  In the NewImplSource and NewIntfSource methods this will be the name that is passed in the FormIdent parameter.

Notice you do not include the leading "T". This is a convention not a rule and the implementer is not required to start types with a leading "T".



function GetMainForm: Boolean;

  If this is to be the main top level form for the application then return True, if it is a secondary form or one that is to be creating dynamically return false.



function GetShowForm: Boolean;

  When the IDE creates the Form there are two items that it can show, one is the source code for the file and the other is the actual Form that can be designed. This is the flag to inform the IDE if it should show the actual Form to the user.


function GetShowSource: Boolean;

  When the IDE creates the Form there are two items that it can show, one is the source code for the file and the other is the actual Form that can be designed. This is the flag to inform the IDE if it should show the source code to the user.


function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;

  This is where the source for the Form is added. Again if you are using a standard Creator Type return a nil, see IOTACreator.GetCreatorType, if GetCreatorType is returning an empty string you must return a valid IOTAFile interface or you will get an AV.

  For a default Form Module the parameters could be:

  • ModuleIdent = Unit1

  • FormIdent = Form1
  • AncestorIdent = Form

  For a default Unit Module the parameters could be:

  • ModuleIdent = Unit1

  • FormIdent = nil
  • AncestorIdent = nil

  The actual source code is not written in the method. It is done indirectly in IOTAFile.GetSource implementation.

It is best to design your IOTAFile implementation such that the ModuleIdent, FormIdent, AncestorIdent parameters can be passed on to the File object.

In later versions of Delphi the default implementation of sForm will create a cross platform Form using the "Q" units, for instance QDialogs. To create a pure Win32 Form you must implement your own IOTAFile.


function NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;

C++Builder Only

  This is where the source for the interface is added. Again if you are using a standard Creator Type return a nil, see IOTACreator.GetCreatorType, if GetCreatorType is returning an empty string you must return a valid IOTAFile interface or you will get an AV.

  The actual source code is not written in the method. It is done indirectly in IOTAFile.GetSource implementation.

It is best to design your IOTAFile implementation such that the ModuleIdent, FormIdent, AncestorIdent parameters can be passed on to the File object.

In later versions of Delphi the default implementation of sForm will create a cross platform Form using the "Q" units, for instance QDialogs. To create a pure Win32 Form you must implement your own IOTAFile.


procedure FormCreated(const FormEditor: IOTAFormEditor);

  Called after the Form Module has been created. Notice the object has been created and a valid IOTAFormEditor is sent as a parameter. Here components may be added to to Form using the interface.


Once the Form Creator is implemented the Form File need attention.

 


mustangpeak.net

  Last Modified on: