📄 uicbasegeneratorvisitor.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 + -