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

📄 uicnodes.pas

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

Copyright (C) 2006-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 UICNodes;

{Contains the most basic classes to represent the COM - the Commment Object
 Model (for those not recognizing this, its name is based on DOM - Document
 Object Model as used in XML, but specially now also used in web browsers for
 any HTML-page, there it is accessible by JavaScript (the correct name is
 ~[linkExtern
   http://www.ecma-international.org/publications/standards/Ecma-262.htm
   ECMAScript]), i.e. navigatable (nodes are selectable) and changable (this
 includes of course also reading values)).

 ~[linkClass TICNode] is the base class of all nodes. Even more interesting
 is ~[linkClass TICNCompound], which is the base class of all nodes containing
 other nodes. The COM is - like any DOM - a hierarchical tree of nodes. So the
 real content will mostly be contained in nodes of classes not descending from
 TICNCompound (the leaves), while the structure will be expressed by nodes of
 classes decending from it.

 I tried doing something like this a once or twice before. I failed (well, not
 really, but I stopped) because of the complexity in handling and creating this
 kind of nodes. ~[linkClass TICNodeOwner] is therefore the central class of
 this implementation of a DOM-like structure. The real problem with handling a
 DOM is creating the nodes, adding them, and - especially - in freeing them. In
 garbage collected languages/environments like JavaScript this is no problem.
 If a node is no longer used and unhooked from the DOM tree, it will
 automatically be freed. In Delphi this has to be done manually. This is also
 true specifically when handling an error.~[br]
 In order not to clutter up the whole source code with additional error
 handling to free nodes, I used this VCL-like approach. Each node is registered
 with a special object of class ~[linkClass TICNodeOwner] when it is created,
 that will take care of freeing it. In case of an error the node will still
 ~[em loiter] around and not be directly freed, but at least there will be a
 reference to it, so it can be finally freed. Additionally an error will always
 abort the generating of the COM, or more generally of the documentation. So
 all nodes should be freed soon after the error.~[br]
 In the VCL almost any component (those descending from ~[code TComponent]) can
 be used as an owner, although in practice all components are owned by the form
 they are placed on. In this COM only a bigger comment object, of
 ~[linkClass TICDocComment] or its descendant ~[linkClass TICSimpleComment],
 owns all the nodes in contains by means of an object of TICNodeOwner. This
 simplifies the nodes (and lessens their memory consumption - a lot of nodes
 will be created).

 The COM is currently immutable. That means it can't be changed after is has
 been created. A new, changed copy of the whole tree has to be created instead.
 This is valid not only for the structure but also for the content of each
 node.

 The tree of nodes can also be processed by implementing a descendant of
 ~[link TICVisitor] and calling the root node's ~[link TICNode.Visit Visit]
 method with an instance of that class. This implements simply the ~[em visitor
 pattern].
}


interface

uses Windows, Classes,
     UPascalConsts, UBaseIdents,
     UImages,
     UComments;

type
  //the base class of all nodes in the ~[link UICNodes COM]
  TICNode = class;


   { * * *  ***  * * *  ***   TICNodeOwner   ***  * * *  ***  * * *  }

  {Manages the nodes of the ~[link UICNodes COM], i.e. frees them when they are
   no longer needed. When a new node is created an owner object has always to
   be specified and the node adds/registers itself to the owner object.~[br]
   This way, no node can be lost, even in the event of an error. So instead of
   clubbering the code with error handling in order to make sure all nodes are
   freed in any circumstance, only a reference of an object of this class has
   to be passed to the constructor. When a node should be added to another
   ~[linkClass TICNCompound node] (via ~[link TICNCompound.AppendNode])
   generally the new parent's ~[link TICNode.Owner owner] should be specified.
  ~see TICNode }
  TICNodeOwner = class
  private
    //the list of owned nodes
    FList: TList;

    //Gets one of the nodes owned by this object.
//    function GetNode(Index: Integer): TICNode;
  public
    //Creates the object to manages nodes of the COM.
    constructor Create;
    //Frees this object and all owned nodes.
    destructor Destroy; override;

    //Adds a node to the object (it'll add itself) so it will be freed.
    procedure AddNode(Node: TICNode);

    //Removes a node so it is no longer owned.
//    procedure RemoveNode(Node: TICNode);
    //Frees a node and removes it from this object's list.
//    procedure FreeNode(Node: TICNode);

      //Returns the number of owned nodes.
//    function Count: Integer;
//    property Nodes[Index: Integer]: TICNode read GetNode; default;
  end;










   { * * *  ***  * * *  ***   TICNode   ***  * * *  ***  * * *  }


  //abstract class of objects to be called for each node - a visitor of the
  //~[link UICNodes COM] tree
  TICVisitor = class;

  //class type of classes of nodes in the ~[link UICNodes COM]
  TICNodeClass = class of TICNode;


  {The abstract base class of all nodes in the ~[link UICNodes COM].~[br]
   All descendants are either descendants of the sub-class
   ~[linkClass TICSimpleNode] or ~[linkClass TICNCompound] (see there for
   diagrams of the class hierarchy).

   When created a reference to an ~[link TICNodeOwner owner] has to be
   specified. It will take care of freeing the node, it should not be freed
   manually.

   All nodes are immutable after they have been created. If something has to be
   changed a new copy of the whole COM tree incorporating the changes has to be
   created. Maybe this will change in the future, but not for some time.
  ~see TICNodeOwner
  ~see TICSimpleNode
  ~see TICNCompound }
  TICNode = class
  private
    //the object owning the node, which will free it
    FOwner: TICNodeOwner;
  protected
    //Clones the content of the node to the specified (new) node.
    procedure CloneTo(Node: TICNode); virtual;

    //Creates a new (empty) node.
    constructor Create(Owner: TICNodeOwner); virtual;
  public

    //Clones the node.
    function Clone(Owner: TICNodeOwner): TICNode;

    {Visits the node and all its children (if it has some).
    ~param Visitor the visitor whose methods should be called for each node }
    procedure Visit(Visitor: TICVisitor); virtual; abstract;

//    function AsPlainText: String; virtual; //? abstract;

    property Owner: TICNodeOwner read FOwner;
//    property ParentNode: TICNCompound read FParentNode;
  end;






   { * * *  ***  * * *  ***   TICSimpleNode   ***  * * *  ***  * * *  }


  {The abstract base class of all simple nodes which contain no other nodes
   (AKA leaves in a tree).

   ~[diagram TICSimpleNode.tree
             /layout=post /size=8 /margin=5 /members /ShowFile=False]
  ~see TICNCompound }
  TICSimpleNode = class(TICNode)
  end;



   { * * *  ***  * * *  ***   TICNText   ***  * * *  ***  * * *  }


  {The class for simple texts in the ~[link UICNodes COM]. All it contains is
   the text. The text may be formatted by the parent nodes.~[br]
   ~[linkClass TICNCompound] contains directly the method
   ~[link TICNCompound.AppendText AppendText] to create and append a node for a
   text to a compound node. }
  TICNText = class(TICSimpleNode)
  private
    //the text represented by this node
    FText: String;
  protected
    //Clones the content of the node to the specified (new) node.
    procedure CloneTo(Node: TICNode); override;
  public
    //Creates a node representing the specified text.
    constructor CreateText(Owner: TICNodeOwner; const Text: String);

    //Visits the node.
    procedure Visit(Visitor: TICVisitor); override;

    property Text: String read FText;
  end;



   { * * *  ***  * * *  ***   TICNRawText   ***  * * *  ***  * * *  }

  {The class for raw text/data that should be inserted unchanged into the
   documentation. It will not be quoted for the format and should therefore be
   format-specific. }
  TICNRawText = class(TICSimpleNode)
  private
    //the text/data represented by this node
    FRawText: String;
  protected
    //Clones the content of the node to the specified (new) node.
    procedure CloneTo(Node: TICNode); override;
  public
    //Creates a node representing the specified text/data.
    constructor CreateRawText(Owner: TICNodeOwner; const RawText: String);

    //Visits the node.
    procedure Visit(Visitor: TICVisitor); override;

    property RawText: String read FRawText;
  end;




   { * * *  ***  * * *  ***   TICNBreak   ***  * * *  ***  * * *  }

  //the kind of break to be inserted in the documentation;
  //~feature a possible addition would be a visible separator like a <hr> tag in
  //         HTML
  TICBreakStyle = (
                   //inserts a line break,
                   //i.e. end the current line and starts a new one
                   icbsLineBreak,
                   //inserts a paragraph break,
                   //i.e. end the current paragraph and starts a new one;
                   //this may be interpreted in some formats as ending the
                   //current line and inserting an additional empty line
                   icbsParagraphBreak);

  {The class for some kind of delimiter in the text/break/vertical spacing. }
  TICNBreak = class(TICSimpleNode)
  private
    //the kind of the delimiter
    FBreakStyle: TICBreakStyle;
  protected
    //Clones the content of the node to the specified (new) node.
    procedure CloneTo(Node: TICNode); override;
  public
    //Creates a node representing the specified delimiter in the text.
    constructor CreateBreak(Owner: TICNodeOwner; BreakStyle: TICBreakStyle);

    //Visits the node.
    procedure Visit(Visitor: TICVisitor); override;

    property BreakStyle: TICBreakStyle read FBreakStyle;
  end;









   { * * *  ***  * * *  ***   TICNCompound   ***  * * *  ***  * * *  }


  {The base class of all nodes which contain other nodes. This class is not
   abstract although its use should be limited in order to not increase the
   complexity of the ~[link UICNodes COM].

   ~[diagram TICNCompound.tree
             /layout=post /size=8 /margin=5 /members /ShowFile=False]
  ~see TICSimpleNode }
  TICNCompound = class(TICNode)
  private
    //the list of child nodes within this node
    FChildren: TList;

    //Returns one of the children of this node.
    function GetChild(Index: Integer): TICNode;
  protected
    //Clones the content of the node to the specified (new) node.
    procedure CloneTo(Node: TICNode); override;

    //Creates this node and the list of child nodes.
    constructor Create(Owner: TICNodeOwner); override;
  public
    //Creates this compound node.
    constructor CreateCompound(Owner: TICNodeOwner);
    //Frees this node and the list of child nodes.
    destructor Destroy; override;


    //Clones all children of this node to the specified (new) node.
    procedure CloneChildrenTo(Parent: TICNCompound);

    //Appends the node to the list of children of this node.
    procedure AppendNode(Node: TICNode);

⌨️ 快捷键说明

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