⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uicbasegeneratorvisitor.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
字号:
{  JADD - Just Another DelphiDoc: Documentation from Delphi Source Code

Copyright (C) 2007-2008   Gerold Veith

This file is part of JADD - Just Another DelphiDoc.

DelphiDoc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.

DelphiDoc 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.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
}


unit UICBaseGeneratorVisitor;

{Contains the base class of the visitors of the ~[link UICNodes COM]-hierarchy
 to transform them into the documentation as needed by the generators.
}

interface

uses Windows, Classes,
     UImages,
     UBaseIdents,
     UDiagram,
     UGenerationMessages,
     UMakeDoc, 
     UICNodes,
     UICCommentDoc;

type

  {An abstract base visitor of the ~[link UICNodes COM]-hierarchy, its
   specialized sub-classes are used by the generators to write the COM to a
   file in their format. This base class only implements the creation and
   inserting of diagrams into the documentation. }
  TICBaseGeneratorVisitor = class(TICVisitor)
  private
    //the generator for which the visitor transforms the documentation;
    //sub-classes may introduce an additional field of a more specific type to
    //reference the generator, generally called FGenerator
    FBaseGenerator: TICCommentDoc;


    //the number of diagrams generated so far
    //(only used to create a unique file name for the diagram)
    FDiagramIndex: Integer;

    //map of the message IDs of the diagram creator to the generator
    FDiagramMessageMap: TMessageDescriptionMap;
    //map of links (to the classes or files) inside the diagram
    FDiagramLinks: TImageLinkList;



    //Called when a message is generated by the creator of diagrams.
    procedure DiagramCreatorMessage(Message: TGeneratorMessage;
                                    Sender: TMakeDoc; var AddToList: Boolean);
    //Adds all boxes of the diagram as links for the image of the diagram.
    procedure AddDiagramLinks(TheClass: TRecordType; TheFile: TPascalFile;
                              Position, Size: TPoint);


    //Creates the actual diagram with the specified parameters.
    procedure CreateDiagram(Parameters: TStrings);


  protected

    //Draws the created diagram on a bitmap and writes it with the generator.
    procedure DrawDiagram(Diagram: TDiagram; DiagramIndex: Integer); virtual;

    //Writes the created diagram.
    procedure WriteDiagram(const DiagramCode: String;
                           ImageSize: TPoint); virtual;

    {Called for each manual link to an identifier or file with a not empty
     text.
    ~param Node the node of a link to an identifier or file with some text }
    procedure LinkIdentifierWithText(Node: TICNLinkIdentifier); virtual;
                                                                abstract;



    property DiagramLinks: TImageLinkList read FDiagramLinks;
  public
    //Creates the visitor and saves the reference on its generator.
    constructor Create(BaseGenerator: TICCommentDoc);
    //Frees the visitor and the list of links in the diagrams.
    destructor Destroy; override;

    //Resets the attributes to ready the visitor for a new generation.
    procedure ResetForNewGeneration; virtual;



    //Called for each manual link to an identifier or file.
    procedure LinkIdentifier(Node: TICNLinkIdentifier;
                             var VisitChildren: Boolean); override;

    //Called for each node representing a diagram of classes or files.
    procedure Diagram(Parameters: TStrings); override;


//    property BaseGenerator: TICCommentDoc read FBaseGenerator
//                                          write FBaseGenerator;
  end;






implementation

uses SysUtils, Graphics,
     UPascalConsts,
     UDocumentationTexts,
     UDiagramCreator;




{Creates the visitor and saves the reference on its generator.
~param BaseGenerator the generator for which the COM should be written }
constructor TICBaseGeneratorVisitor.Create(BaseGenerator: TICCommentDoc);
begin
 inherited Create;                        //create the object

 FBaseGenerator := BaseGenerator;         //save the reference

 FDiagramLinks := TImageLinkList.Create;  //create list for links in diagrams
end;

{Frees the visitor and the list of links in the diagrams. }
destructor TICBaseGeneratorVisitor.Destroy; 
begin
 FDiagramLinks.Free;                      //free list of links inside diagrams

 inherited Destroy;                       //free the visitor
end;





{Resets the attributes to ready the visitor for a new generation. }
procedure TICBaseGeneratorVisitor.ResetForNewGeneration;
begin
 SetLength(FDiagramMessageMap, 0);    //diagram messages not registered yet
 FDiagramLinks.Clear;                 //no links in a (the next) diagram

 FDiagramIndex := 0;                  //no diagrams created yet
end;














{Called for each manual link to an identifier or file.
~param Node          the node of a link to an identifier or file
~param VisitChildren out: whether the children of the node (the link text)
                     should also be visited; default is True }
procedure TICBaseGeneratorVisitor.LinkIdentifier(Node: TICNLinkIdentifier;
                                                 var VisitChildren: Boolean);

 {Writes an entry in the path of the link target.
 ~param Identifier the identifier to link to, if it is not a file
 ~param TheFile    the file to link to, if it is not an identifier }
 procedure WriteEntry(Identifier: TIdentifier; TheFile: TPascalFile);
 begin
  //is not documented?
  if FBaseGenerator.DoNotDocumentIdentifier(Identifier, TheFile) then
   if Assigned(Identifier) then               //just write text of the entry
    Text(Identifier.Name)
   else
    Text(TheFile.InternalFileName)
  else
   LinkTo(Identifier, TheFile);               //write link to it
 end;

var       i              :Integer;       //counter through the path
begin
 VisitChildren := False;                 //will be visited manually
 if Node.NoChildren then                 //no text of the link specified?
  begin
   if Length(Node.PathLinks) <> 0 then     //target specified as a path?
    //for each entry in the path
    for i := Low(Node.PathLinks) to High(Node.PathLinks) do
     begin
      if i <> 0 then                            //not the first
       Text('.');                                 //write the separator
      if Node.PathLinks[i] is TPascalFile then  //write the entry
       WriteEntry(nil, TPascalFile(Node.PathLinks[i]))
      else
       WriteEntry(TIdentifier(Node.PathLinks[i]), nil)
     end
   else
    WriteEntry(Node.Identifier, Node.TheFile); //write the only entry
  end
 else
  LinkIdentifierWithText(Node);            //write the link on the text
end;










{Called when a message is generated by the creator of diagrams.
 Is of type: ~[link TGeneratorMessageEvent].
~param Message   the generated message
~param Sender    the generator generating the message while generating
~param AddToList whether the message should be added to the list, default is
                 True }
procedure TICBaseGeneratorVisitor.DiagramCreatorMessage(
                                                    Message: TGeneratorMessage;
                                                    Sender: TMakeDoc;
                                                    var AddtoList: Boolean);
begin
 AddToList := False;           //don't save the message in the diagram creator

 Assert(Message.MessageID > 0);
 Assert(Message.MessageID < Length(FDiagramMessageMap));
 Assert(FDiagramMessageMap[Message.MessageID] > 0);
 //add the message with the mapped ID
 FBaseGenerator.AddPositionMessage(FDiagramMessageMap[Message.MessageID],
                                   Message.MessageNumber, Message.Message)
end;

{Adds all boxes of the diagram as links for the image of the diagram.
 Is of type ~[link UDiagram.TForEachGetBoxPositionsRecallProc].
~param TheClass the class of the box, if it is not a file diagram
~param TheFile  the file of the box
~param Position the position of the box
~param Size     the size of the box }
procedure TICBaseGeneratorVisitor.AddDiagramLinks(TheClass: TRecordType;
                                                  TheFile: TPascalFile;
                                                  Position, Size: TPoint);
var       Data           :TImageLinkData; //new data to add it to the list
begin
 Data.IsAll := False;                     //assign the values

 Data.Position.TopLeft := Position;       //get rectangle of box for the link
 Data.Position.Right := Position.x + Size.x;
 Data.Position.Bottom := Position.y + Size.y;

 Data.ExternLink := False;                //not an external link
 Data.LinkTarget := '';                   //not a manual link

 Data.Kind := ilkIdentifier;              //link to the class or file
 Data.Identifier := TheClass;
 Data.ToFile := TheFile;

 if Assigned(TheClass) then               //box depicts a class?
  begin
   //add link to the class (not to the file)
   Data.ToFile := nil;
   Data.AlternativeText := RecordKindNames[TheClass.Kind] + ' ' +
                           TheClass.Name;
  end
 else
  //add link to the file
  Data.AlternativeText := FileTypeNames[TheFile.FileType] + ' ' +
                          TheFile.InternalFileName;
 FDiagramLinks.Add(Data);                 //and add it to the list
end;


{Creates the actual diagram with the specified parameters. ~[diagram ]
~param Parameters the parameters to create the diagram }
procedure TICBaseGeneratorVisitor.CreateDiagram(Parameters: TStrings);
var       DiagGen        :TDiagramCreator; //the creator of the diagram
begin
 DiagGen := TDiagramCreator.Create;        //create generator of the diagram
 try
   //register all message and save the map of the message IDs
   FDiagramMessageMap := DiagGen.RegisterAllMessagesTo(FBaseGenerator);
   //will add all messages of the creator to the original generator
   DiagGen.OnMessage := DiagramCreatorMessage;
   //filter identifier by the original generator
   DiagGen.FilterGenerator := FBaseGenerator;
   DiagGen.Files := FBaseGenerator.Files;
   DiagGen.StartFile := FBaseGenerator.CommentFile;

   //create diagram with the parameters
   DiagGen.CreateDiagram(Parameters);

   if not DiagGen.Diagram.IsEmpty then    //diagram is not empty?
    begin
     Inc(FDiagramIndex);                    //get new index for the diagram

     FDiagramLinks.Clear;
     DiagGen.Diagram.GetBoxPositions(AddDiagramLinks); //save all links

     DrawDiagram(DiagGen.Diagram, FDiagramIndex);      //draw the diagram

     FDiagramLinks.Clear;                   //empty list of links inside it
    end
   else
    //don't include the diagram
    FBaseGenerator.AddPositionMessage(FBaseGenerator.ICCommentDocMessagesID,
                                      Ord(cdmkDiagramIsEmpty),
                                      'The diagram is empty!');

 finally
  DiagGen.Free;                           //free creator of the diagram and
  SetLength(FDiagramMessageMap, 0);       //clear the map of the message IDs
 end;
end;



{Draws the created diagram on a bitmap and writes it with the generator.
~param Diagram      the created diagram to save as an image
~param DiagramIndex the number of diagrams generated so far, used to create a
                    unique (file) name for the diagram }
procedure TICBaseGeneratorVisitor.DrawDiagram(Diagram: TDiagram;
                                              DiagramIndex: Integer);
var       Bitmap         :TBitmap;         //the image of the diagram
          ImageCode      :String;          //the internal code for the diagram
          ImageSize      :TPoint;          //the size of the diagram
begin
 Bitmap := TBitmap.Create;                 //create bitmap for the diagram
 try
   Diagram.DrawWholeDiagram(Bitmap);       //draw diagram on bitmap

   //show image of the diagram in the documentation
   ImageCode := FBaseGenerator.WriteImage(False, False, Point(0, 0), Bitmap,
                                          Format('Diagram%d.bmp', 
                                                 [DiagramIndex]),
                                          FDiagramLinks,
                                          DocumentationTexts[dtDiagramHint].T);

   ImageSize.x := Bitmap.Width;            //save size of the image
   ImageSize.y := Bitmap.Height;
 finally
  Bitmap.Free;                             //free the bitmap
 end;

 WriteDiagram(ImageCode, ImageSize);       //insert diagram into documentation
end;


{Writes the created diagram. Has to be overridden in the sub-classes to
 actually write the diagram into the documentation.
~param DiagramCode the code as returned by ~[link FBaseGenerator].~[link
                   TICCommentDoc.WriteImage WriteImage]
~param ImageSize   the dimensions of the diagram in pixels }
procedure TICBaseGeneratorVisitor.WriteDiagram(const DiagramCode: String;
                                               ImageSize: TPoint);
begin
 //should not be called, has either to be overridden, or Diagram has to be
 //overridden to prevent CreateDiagram and in turn this method to be called
 Assert(False);
end;



{Called for each node representing a diagram of classes or files.
~param Parameters the parameters to create the diagram }
procedure TICBaseGeneratorVisitor.Diagram(Parameters: TStrings);
begin
 CreateDiagram(Parameters);            //create and insert the diagram
end;


end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -