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

📄 uvectorgraphics.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:
begin
 Assert(not Files.IsEmpty);

 inherited Create;                  //create the object

 FFiles := Files;                   //save the parameters
 FFormatHandler := FormatHandler;
 FURLCallBack := URLCallBack;
end;

{Frees the drawer of diagrams and the drawing object. }
destructor TVectorFileDrawer.Destroy;
begin
 FFormatHandler.Free;               //free the drawing object

 inherited Destroy;                 //free this object
end;


{Calculates the size of all the boxes of files in the diagram. This is done by
 ascertaining the biggest size of the file names and adding a margin.
~result the needed size for the boxes }
function TVectorFileDrawer.CalculateBoxSize: TSize;
var      i                :Integer;      //counter through all files
         TextSize         :TSize;        //size of the names of the files
begin
 //let the format handler prepare itself for measuring the text sizes
 FFormatHandler.PrepareTextMeasuring;
 try
   Result.cx := 0;                       //maximum size of all names of files;
   Result.cy := 0;                       //empty so far
   for i := 0 to FFiles.Count - 1 do     //for each file
    begin                                  //get size of its name
     TextSize := FFormatHandler.GetTextExtent(FFiles[i].InternalFileName);
     if TextSize.cx > Result.cx then       //and get the maximum
      Result.cx := TextSize.cx;
     if TextSize.cy > Result.cy then
      Result.cy := TextSize.cy;
    end;
   Inc(Result.cx, 10);                   //add a margin of 5 pixels
   Inc(Result.cy, 10);                   //on each side
 finally
  FFormatHandler.EndTextMeasuring;       //shut down the text measuring again
 end;
end;




{Draws all files on the image. }
procedure TVectorFileDrawer.DrawFiles;

 //Draws the arrows showing the usage between the file and other files.
 procedure DrawUse(SPos: TPoint; List: TStrings; BoldArrows: Boolean;
                   OrgFile: TPascalFile); forward;

 //Calculates the position of all used files.
 procedure CalcUnits(List: TStrings); forward;
 //Sets the position of the next file to be drawn.
 procedure CalcFilePos(Index: Cardinal; CountPerColumn: Integer = 0); forward;


var       Files           :PPascalFile;        //list of the files
          Positions       :PPoint;             //positions of the files


 {Draws the arrows showing the usage between the file and other files.
 ~param SPos       position of the file to draw arrows from
 ~param List       a list of used files
 ~param BoldArrows whether bold arrows should be used to indicate usage in the
                   implementation part
 ~param OrgFile    the file to print the usage of (to recognize self-usage) }
 procedure DrawUse(SPos: TPoint; List: TStrings; BoldArrows: Boolean;
                   OrgFile: TPascalFile);

  {Draws an arrow from the source point of the file to this destination,
   modifying the positions for better clarity.
  ~param Dest the destination point to draw the arrow to }
  procedure DrawArrowTo(Dest: TPoint);
  var       Src        :TPoint;     //the modified source point of the arrow
            Part       :Extended;   //which part of the arrow is its arrowhead
            Arr1, Arr2 :TPoint;     //points of the arrowhead
            Tmp        :Integer;    //helper for calculating Arr1 and Arr2
  begin
   Src := SPos;                       //use original source point

   if Src.y < Dest.y then             //if files not in same column
    Inc(Src.y, FBoxSize.cy)             //draw from one side to the other
   else
    if Src.y > Dest.y then
     Inc(Dest.y, FBoxSize.cy)
    else
     begin
      Inc(Src.y, FBoxSize.cy div 3);    //else displace arrows a bit
      Inc(Dest.y, FBoxSize.cy * 2 div 3);
     end;

   if Src.x < Dest.x then             //same for horizontal position
    Inc(Src.x, FBoxSize.cx)
   else
    if Src.x > Dest.x then
     Inc(Dest.X, FBoxSize.cx)
    else
     begin
      Inc(Src.x, FBoxSize.cx div 3);
      Inc(Dest.x, FBoxSize.cx * 2 div 3);
     end;

   if (Src.x <> Dest.x) or (Src.y <> Dest.y) then //arrow not empty?
    begin
     Part := (FBoxSize.cy * 3 div 4) /        //calculate portion of arrowhead
             Sqrt(Sqr(Src.x - Dest.x) + Sqr(Src.y - Dest.y));
                                              //calculate position on arrow
     Arr1.x := Round(Part * Src.x + (1 - Part) * Dest.x);
     Arr1.y := Round(Part * Src.y + (1 - Part) * Dest.y);
     Arr2 := Arr1;


     Tmp := Arr1.x;                           //now move both arrowhead points
     Dec(Arr1.x, Arr1.y - Dest.y);             //orthographic/upright
     Inc(Arr1.y, Tmp - Dest.x);

     Inc(Arr2.x, Arr2.y - Dest.y);
     Dec(Arr2.y, Tmp - Dest.x);

     //draw the arrow
     FFormatHandler.DrawArrow(Src, Dest, Arr1, Arr2, BoldArrows);
    end;
  end;

 var       i        :Integer;               //counter through the files
           Item     :TPascalFile;           //each file
           FRunner  :PPascalFile;           //runner through list of files
           DPos     :PPoint;                //position to draw the file
 begin
  for i := 0 to List.Count - 1 do           //for each file
   begin
    Item := TPascalFile(List.Objects[i]);     //get it
    if Assigned(Item) and (Item <> OrgFile) then //if not used by itself
     begin
      FRunner := Files;
      DPos := Positions;
      while (FRunner^ <> Item) do                 //search file to get its
       begin                                      //position
        Inc(DPos);
        Inc(FRunner);
       end;
      DrawArrowTo(DPos^);                         //draw arrow to its position
     end;
   end;
 end;

 {Calculates the position of all used files.
 ~param List the list of files to position }
 procedure CalcUnits(List: TStrings);
 var       i        :Integer;            //counter through the files
           Item     :TPascalFile;        //each file in the list
           FRunner  :PPascalFile;        //runner through list of all files
 begin
  for i := 0 to List.Count - 1 do        //for each file
   begin
    Item := TPascalFile(List.Objects[i]);  //get it
    if Assigned(Item) then                 //if assigned
     begin
      FRunner := Files;
      while (FRunner^ <> Item) do            //search in the list
       Inc(FRunner);
      //draw file by its index in the list
      CalcFilePos((Cardinal(FRunner) - Cardinal(Files)) div SizeOf(FRunner^));
     end;
   end;
 end;



 var       CanvasSize      :TSize;       //size of used canvas for the figure
           NextUnit        :TPoint;      //position of the next file to draw



 {Sets the position of the next file to be drawn.
 ~param Index          index of the file in the list
 ~param CountPerColumn number of files in a column; 0: as many as fit }
 procedure CalcFilePos(Index: Cardinal; CountPerColumn: Integer = 0);
 var       PositionP  :PPoint;     //position of the file
 begin
  PositionP := Positions;
  Inc(PositionP, Index);           //get position
  if PositionP.x = -1 then         //file not yet positioned?
   begin
    //center file if number given
    if (CountPerColumn <> 0) and (NextUnit.y = 0) then
     NextUnit.y := (CanvasSize.cy + FBoxSize.cy) div CountPerColumn div 2;

    PositionP^ := NextUnit;          //save position of file

    if CountPerColumn = 0 then       //normal list(/block) of files?
     begin
      Inc(NextUnit.y, FBoxSize.cy * 4); //next position
      if NextUnit.y > CanvasSize.cy then //end of page reached?
       begin
        NextUnit.y := 0;                   //start next column
        Inc(NextUnit.x, FBoxSize.cx * 2);
       end;
     end
    else
     Inc(NextUnit.y, FBoxSize.cy * 4); //go to next "centered" position
   end;
 end;


var       FilesPerColumn  :Cardinal;     //number of files fitting in a column
          Count           :Cardinal;     //number of files in the list
          FRunner         :PPascalFile;  //runner through the list of files
          i               :Cardinal;     //general counter through the files
          C               :Cardinal;     //number of project files
          CPC             :Cardinal;     //number of project files in a column
          PRunner         :PPoint;       //runner through the positions
begin
 Count := FFiles.Count;            //get number of files
 //create buffer of positions of files
 GetMem(Positions, SizeOf(Positions^) * Count);
 try
   FillChar(Positions^, SizeOf(Positions^) * Count, $FF); //set positions to -1

                                   //create buffer of files
   GetMem(Files, SizeOf(Files^) * Count);
   try
     FRunner := Files;
     for i := 0 to Count - 1 do    //fill buffer with files
      begin
       FRunner^ := FFiles.GetFile(i);
       Inc(FRunner);
      end;

     NextUnit.x := 0;              //start printing of files at top left
     NextUnit.y := 0;


     C := 0;                       //count all project files
     FRunner := Files;
     for i := 0 to Count - 1 do    //for each file
      begin
       if FRunner^.FileType <> sftUnit then //if not a unit
        Inc(C);                               //add number
       Inc(FRunner);
      end;


     //get number of files per column, creating figure approximately with the
     //same height as the width
     FilesPerColumn := Round(Sqrt(Count - C) + 0.3);
     if C > FilesPerColumn then
      FilesPerColumn := C;

     //set height of the figure
     CanvasSize.cy := (FilesPerColumn - 1) * (Cardinal(FBoxSize.cy) * 4);


     if C <> 0 then                //project files parsed?
      begin
       if C < FilesPerColumn then    //fit in one column?
        CPC := C                       //use this column completely
       else
        CPC := 0;                      //center all files

       FRunner := Files;
       for i := 0 to Count - 1 do    //for each (project) file
        begin
         if FRunner^.FileType <> sftUnit then //is a project file?
          begin
           CalcFilePos(i, CPC);                 //calculate its position

           if NextUnit.y = 0 then               //column ended?
            begin
             //subtract processed files
             if C > FilesPerColumn then
              Dec(C, FilesPerColumn)
             else
              C := 0;
             //center rest of files if they fit in one column
             if C < FilesPerColumn then
              CPC := C
             else
              CPC := 0;
            end;
          end;
         Inc(FRunner);                        //next file
        end;

       if NextUnit.y <> 0 then                 //not in a new column?
        begin
         NextUnit.y := 0;                        //start new column
         Inc(NextUnit.x, FBoxSize.cx * 2);
        end;

       FRunner := Files;
       for i := 0 to Count - 1 do              //for each (project) file
        begin
         if FRunner^.FileType <> sftUnit then    //is a project file?
          begin
           //calculate position of all used files in interface and
           //implementation, i.e. all units of the project
           CalcUnits(FRunner^.UsedUnitList[fpInterface]);
           CalcUnits(FRunner^.UsedUnitList[fpMain]);
          end;
         Inc(FRunner);                           //next file
        end;

       if NextUnit.y <> 0 then                 //not a new column?
        begin
         NextUnit.y := 0;                        //start a new column
         Inc(NextUnit.x, FBoxSize.cx * 2);
        end;
      end;

     for i := 0 to Count - 1 do              //for any other file
      CalcFilePos(i);                          //calculate its position


     CanvasSize.cx := NextUnit.x;            //set width of figure
     if NextUnit.y = 0 then                  //if new column has been started
      Dec(CanvasSize.cx, FBoxSize.cx * 2);     //subtract it



     //prepare the drawer object to draw the diagram
     FFormatHandler.InitImageObjects(CanvasSize.cx + FBoxSize.cx + 1,
                                     CanvasSize.cy + FBoxSize.cy,
                                 'Figure of the Interdependency of the Files');
     try
       FRunner := Files;
       PRunner := Positions;
       for i := 0 to Count - 1 do            //for each file
        begin
         //draw arrows showing usage of other units in the interface and
         DrawUse(PRunner^, FRunner^.UsedUnitList[fpInterface],
                 FRunner^.FileType <> sftUnit, FRunner^);
         DrawUse(PRunner^, FRunner^.UsedUnitList[fpMain],  //in implementation
                 True, FRunner^);

         Inc(FRunner);                         //next file
         Inc(PRunner);                         //and next position
        end;

       FRunner := Files;
       PRunner := Positions;
       for i := 0 to Count - 1 do            //for each file
        begin
         //if links should be included
         if Assigned(FURLCallBack) then
          //get the link target and set it
          FFormatHandler.SetNextTextBoxesLinkTarget(FURLCallBack(FRunner^));

⌨️ 快捷键说明

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