Does de NewImplSource from IOTAModuleCreator automatically "shows" the new unit on the IDE?

144 views Asked by At

I'm trying to implement an IDE Wizard with ToolsApi and using the GExperts FAQ (http://www.gexperts.org/examples/GXModuleCreator.pas) as reference.

Although the bpl compiles, the unit doesn't shows up on the IDE. I'm Using Delphi 10.3.2 Rio.

unit ModuleCreator;

interface

uses
  SysUtils, Windows, Dialogs, ToolsAPI;

type
  TJIdeWizardSourceFile = class(TInterfacedObject, IOTAFile)
  private
    FSource: string;
  public
    function GetSource: string;
    function GetAge: TDateTime;
    constructor Create(const Source: string);
  end;

  TJIdeWizardModuleCreator = class(TInterfacedObject, IOTACreator, IOTAModuleCreator)
  public
    // IOTACreator
    function GetCreatorType: string;
    function GetExisting: Boolean;
    function GetFileSystem: string;
    function GetOwner: IOTAModule;
    function GetUnnamed: Boolean;
    // IOTAModuleCreator
    function GetAncestorName: string;
    function GetImplFileName: string;
    function GetIntfFileName: string;
    function GetFormName: string;
    function GetMainForm: Boolean;
    function GetShowForm: Boolean;
    function GetShowSource: Boolean;
    function NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
    function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
    function NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
    procedure FormCreated(const FormEditor: IOTAFormEditor);
  end;

implementation

{ TJIdeWizardModuleCreator }

procedure TJIdeWizardModuleCreator.FormCreated(const FormEditor: IOTAFormEditor);
begin
  //
end;

function TJIdeWizardModuleCreator.GetAncestorName: string;
begin
  Result := 'Form';
end;

function TJIdeWizardModuleCreator.GetCreatorType: string;
begin
  Result := sUnit;
end;

function TJIdeWizardModuleCreator.GetExisting: Boolean;
begin
  Result := False;
end;

function TJIdeWizardModuleCreator.GetFileSystem: string;
begin
  Result := '';
end;

function TJIdeWizardModuleCreator.GetFormName: string;
begin
  Result := '';
end;

function TJIdeWizardModuleCreator.GetImplFileName: string;
begin
  Result := '';
end;

function TJIdeWizardModuleCreator.GetIntfFileName: string;
begin
  Result := '';
end;

function TJIdeWizardModuleCreator.GetMainForm: Boolean;
begin
  Result := False;
end;

function TJIdeWizardModuleCreator.GetOwner: IOTAModule;
var
  ModuleServices: IOTAModuleServices;
  Module: IOTAModule;
  NewModule: IOTAModule;
begin
  // You may prefer to return the project group's ActiveProject instead
  Result := nil;
  ModuleServices := (BorlandIDEServices as IOTAModuleServices);
  Module := ModuleServices.CurrentModule;

  if Module <> nil then
  begin
    if Module.QueryInterface(IOTAProject, NewModule) = S_OK then
      Result := NewModule

    else if Module.OwnerModuleCount > 0 then
    begin
      NewModule := Module.OwnerModules[0];
      if NewModule <> nil then
        if NewModule.QueryInterface(IOTAProject, Result) <> S_OK then
          Result := nil;
    end;
  end;
end;

function TJIdeWizardModuleCreator.GetShowForm: Boolean;
begin
  Result := True;
end;

function TJIdeWizardModuleCreator.GetShowSource: Boolean;
begin
  Result := True;
end;

function TJIdeWizardModuleCreator.GetUnnamed: Boolean;
begin
  Result := True;
end;

function TJIdeWizardModuleCreator.NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
begin
  Result := nil;
end;

function TJIdeWizardModuleCreator.NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
begin
  // or Result := nil; for the default unit
  Result := nil;
end;

function TJIdeWizardModuleCreator.NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
begin
  Result := nil;
end;

{ TJIdeWizardSourceFile }

constructor TJIdeWizardSourceFile.Create(const Source: string);
begin
  FSource := Source;
end;

function TJIdeWizardSourceFile.GetAge: TDateTime;
begin
  Result := -1;
end;

function TJIdeWizardSourceFile.GetSource: string;
begin
  result := FSource;
end;

end.

Here is an example of how I´m calling the method "NewImplSource" from IOTAModuleCreator

  procedure TfrmMapearObjetoRelacional.btnSimpleORMDaoClick(Sender: TObject);
  var
    _Mod: TJIdeWizardModuleCreator;
    _Str: string;
  begin
    _Mod := TJIdeWizardModuleCreator.Create;
    try
      _Str := _Mod.NewImplSource('unit1','','');
      ShowMessage(_Str);
    finally
      FreeAndNil(_Mod);
    end;
  end;
2

There are 2 answers

3
MartynA On

If you don't have any luck debugging this in a second instance of the IDE like I suggested in a project, I think you should consider changing your code do follow the way I go about implementing something like this.

  1. I implement the OTA interface of interest on a small form. Although the form is, in principle, unnecessary, it is very useful to give a visual sign that the thing's working and there is actually quite a lot of debugging you can do without having to resort to the second-IDE-instance business. You can build quite a lot of debugging facilities into the form by placing a small TMemo on it and using it as a logging facility to record what it does. And, of course, the form can have a MainMenu or whatever to invoke various of the OTA interface's methods to check that they do what they are supposed to do.

  2. The form shouldn't be autocreated. Instead, create and call .Show on it in the `Initialization' section of the form's unit and Free it in its Finalization section.

  3. Once you've compiled the .Dpk containing the form, install it in the IDE using Install Packages.

I always write OTA stuff in a form like this and very rarely get into any major problems that need the second-IDE-instance to investigate and resolve.

Good luck!

0
Leo Bruno On

The answer for the question is YES it does.

The problem was that one should not call "NewImplSource" directly.

In order for it to work, it should be called based on the result from "GetCreatorType" inside the "IOTAModuleCreator" Constructor.

for instance:

  procedure TJModuleCreatorWizard.Execute;
  begin
    (BorlandIDEServices as IOTAModuleServices).CreateModule(TJModuleCreator.Create);
  end;

Where "TJModuleCreator" implements IOTAModuleCreator interface.

Martyn, thak you very much for your assistance, in fact I was able to figure it out by simplifying the scenario as you suggested on your answer.