Aspose::Words::CommentRangeEnd class

CommentRangeEnd class

Denotes the end of a region of text that has a comment associated with it. To learn more, visit the Working with Comments documentation article.

class CommentRangeEnd : public Aspose::Words::Node,
                        public Aspose::Words::IDisplaceableByCustomXml,
                        public Aspose::Words::INodeWithAnnotationId

Methods

MethodDescription
Accept(System::SharedPtr<Aspose::Words::DocumentVisitor>) overrideAccepts a visitor.
Clone(bool)Creates a duplicate of the node.
CommentRangeEnd(const System::SharedPtr<Aspose::Words::DocumentBase>&, int32_t)Initializes a new instance of this class.
get_CustomNodeId() constSpecifies custom node identifier.
virtual get_Document() constGets the document to which this node belongs.
get_Id() constSpecifies the identifier of the comment to which this region is linked to.
virtual get_IsComposite()Returns true if this node can contain other nodes.
get_NextNode() const
get_NextSibling()Gets the node immediately following this node.
get_NodeType() const overrideReturns CommentRangeEnd.
get_ParentNode()Gets the immediate parent of this node.
get_PreviousSibling()Gets the node immediately preceding this node.
get_PrevNode() const
get_Range()Returns a Range object that represents the portion of a document that is contained in this node.
GetAncestor(Aspose::Words::NodeType)Gets the first ancestor of the specified NodeType.
GetAncestorOf()
virtual GetText()Gets the text of this node and of all its children.
GetType() const override
Is(const System::TypeInfo&) const override
IsAncestorNode(const System::SharedPtr<Aspose::Words::Node>&)
NextPreOrder(const System::SharedPtr<Aspose::Words::Node>&)Gets next node according to the pre-order tree traversal algorithm.
static NodeTypeToString(Aspose::Words::NodeType)A utility method that converts a node type enum value into a user friendly string.
PreviousPreOrder(const System::SharedPtr<Aspose::Words::Node>&)Gets the previous node according to the pre-order tree traversal algorithm.
Remove()Removes itself from the parent.
set_CustomNodeId(int32_t)Setter for Aspose::Words::Node::get_CustomNodeId.
set_Id(int32_t)Setter for Aspose::Words::CommentRangeEnd::get_Id.
set_NextNode(const System::SharedPtr<Aspose::Words::Node>&)
set_PrevNode(const System::SharedPtr<Aspose::Words::Node>&)
SetParent(const System::SharedPtr<Aspose::Words::Node>&)
ToString(Aspose::Words::SaveFormat)Exports the content of the node into a string in the specified format.
ToString(const System::SharedPtr<Aspose::Words::Saving::SaveOptions>&)Exports the content of the node into a string using the specified save options.
static Type()

Remarks

To create a comment anchored to a region of text, you need to create a Comment and then create CommentRangeStart and CommentRangeEnd and set their identifiers to the same Id value.

CommentRangeEnd is an inline-level node and can only be a child of Paragraph.

Examples

Shows how print the contents of all comments and their comment ranges using a document visitor.

void CreateCommentsAndPrintAllInfo()
{
    auto doc = MakeObject<Document>();

    auto newComment = MakeObject<Comment>(doc);
    newComment->set_Author(u"VDeryushev");
    newComment->set_Initial(u"VD");
    newComment->set_DateTime(System::DateTime::get_Now());

    newComment->SetText(u"Comment regarding text.");

    // Add text to the document, warp it in a comment range, and then add your comment.
    SharedPtr<Paragraph> para = doc->get_FirstSection()->get_Body()->get_FirstParagraph();
    para->AppendChild(MakeObject<CommentRangeStart>(doc, newComment->get_Id()));
    para->AppendChild(MakeObject<Run>(doc, u"Commented text."));
    para->AppendChild(MakeObject<CommentRangeEnd>(doc, newComment->get_Id()));
    para->AppendChild(newComment);

    // Add two replies to the comment.
    newComment->AddReply(u"John Doe", u"JD", System::DateTime::get_Now(), u"New reply.");
    newComment->AddReply(u"John Doe", u"JD", System::DateTime::get_Now(), u"Another reply.");

    PrintAllCommentInfo(doc->GetChildNodes(NodeType::Comment, true));
}

static void PrintAllCommentInfo(SharedPtr<NodeCollection> comments)
{
    auto commentVisitor = MakeObject<ExComment::CommentInfoPrinter>();

    // Iterate over all top-level comments. Unlike reply-type comments, top-level comments have no ancestor.
    std::function<bool(SharedPtr<Node> c)> haveNoAncestor = [](SharedPtr<Node> c)
    {
        return (System::ExplicitCast<Comment>(c))->get_Ancestor() == nullptr;
    };

    for (auto comment : System::IterateOver<Comment>(comments->LINQ_Where(haveNoAncestor)))
    {
        // First, visit the start of the comment range.
        auto commentRangeStart = System::ExplicitCast<CommentRangeStart>(comment->get_PreviousSibling()->get_PreviousSibling()->get_PreviousSibling());
        commentRangeStart->Accept(commentVisitor);

        // Then, visit the comment, and any replies that it may have.
        comment->Accept(commentVisitor);

        for (const auto& reply : System::IterateOver<Comment>(comment->get_Replies()))
        {
            reply->Accept(commentVisitor);
        }

        // Finally, visit the end of the comment range, and then print the visitor's text contents.
        auto commentRangeEnd = System::ExplicitCast<CommentRangeEnd>(comment->get_PreviousSibling());
        commentRangeEnd->Accept(commentVisitor);

        std::cout << commentVisitor->GetText() << std::endl;
    }
}

class CommentInfoPrinter : public DocumentVisitor
{
public:
    CommentInfoPrinter() : mVisitorIsInsideComment(false), mDocTraversalDepth(0)
    {
        mBuilder = MakeObject<System::Text::StringBuilder>();
        mVisitorIsInsideComment = false;
    }

    String GetText()
    {
        return mBuilder->ToString();
    }

    VisitorAction VisitRun(SharedPtr<Run> run) override
    {
        if (mVisitorIsInsideComment)
        {
            IndentAndAppendLine(String(u"[Run] \"") + run->get_Text() + u"\"");
        }

        return VisitorAction::Continue;
    }

    VisitorAction VisitCommentRangeStart(SharedPtr<CommentRangeStart> commentRangeStart) override
    {
        IndentAndAppendLine(String(u"[Comment range start] ID: ") + commentRangeStart->get_Id());
        mDocTraversalDepth++;
        mVisitorIsInsideComment = true;

        return VisitorAction::Continue;
    }

    VisitorAction VisitCommentRangeEnd(SharedPtr<CommentRangeEnd> commentRangeEnd) override
    {
        mDocTraversalDepth--;
        IndentAndAppendLine(String(u"[Comment range end] ID: ") + commentRangeEnd->get_Id() + u"\n");
        mVisitorIsInsideComment = false;

        return VisitorAction::Continue;
    }

    VisitorAction VisitCommentStart(SharedPtr<Comment> comment) override
    {
        IndentAndAppendLine(
            String::Format(u"[Comment start] For comment range ID {0}, By {1} on {2}", comment->get_Id(), comment->get_Author(), comment->get_DateTime()));
        mDocTraversalDepth++;
        mVisitorIsInsideComment = true;

        return VisitorAction::Continue;
    }

    VisitorAction VisitCommentEnd(SharedPtr<Comment> comment) override
    {
        mDocTraversalDepth--;
        IndentAndAppendLine(u"[Comment end]");
        mVisitorIsInsideComment = false;

        return VisitorAction::Continue;
    }

private:
    bool mVisitorIsInsideComment;
    int mDocTraversalDepth;
    SharedPtr<System::Text::StringBuilder> mBuilder;

    void IndentAndAppendLine(String text)
    {
        for (int i = 0; i < mDocTraversalDepth; i++)
        {
            mBuilder->Append(u"|  ");
        }

        mBuilder->AppendLine(text);
    }
};

See Also