[CONNECT Update 17 C#] Navigating a TextBlock

TextBlock Class

From the DgnPlatformNet help document: In the TextBlock DOM, this is the master object that represents a piece of text as a whole, and is the primary high-level object used to deal with multi-line, formatted text (and is also generally recommended for any text, regardless of complexity). As described in the Text module documentation, TextBlock consists of a DOM (Document Object Model). Elements of the DOM include Paragraph and Run objects. Internally, lines are also computed, but only affect layout, and are not directly exposed.

Where is the Text module documentation?

Navigating the Components of a TextBlock

I'm writing an example AddIn using C# and the DgnPlatformNet API.  I want to pick a text element, then show its text content.  However, I'm having trouble interpreting the TextBlock API and its component classes.  Unfortunately, examples are rare.

From an element that contains text I can get a TextBlock.  I want to enumerate its components to see their content.  What are the navigable components of a TextBlock?  There are carets, runs and paragraphs.  Which of those contains a string obtained from the text element?

Some of the API seems incomplete.  For example, the ParagraphIterator: An STL iterator-like wrapper around Caret, that allows you to easily iterate paragraphs. See notes on Caret as to why this is helpful.  That gives me a Paragraph enumerator: In the TextBlock DOM, a collection of lines and runs.  But Paragraph doesn't provide any method to obtain a line or run, so how is that supposed to work?

Parents
  • Hi ,

    Where is the Text module documentation?

    My modified version of those few words (to clarify) would be: Text (help module) documentation.

    Indicating to look to the "Text" help topic for an Overview of the Text (many forms) leading into the TextBlock API relationship details.

    The following are a few .NET unit tests I found, where you will need to modify any calls to Assert directly or simply ignore or handle each method or result accordingly.

    Code Snip: CreateTextElementTest

    public void CreateTextElementTest()
    {
    
        //Create a text block.
        TextBlock textBlock = new TextBlock(m_tbProps, m_pProps, m_runProps, m_defaultModel);
        textBlock.AppendText("Simple Text");
    
        //CREATE text element.
        TextElement textElement = (TextElement)TextHandlerBase.CreateElement(null, textBlock);
        Assert.AreEqual(StatusInt.Success, textElement.AddToModel());
    }

    Code Snip: CreateTextElementFromTextBlock

    /// <summary>
    /// Helper method for creating text element.
    /// </summary>
    /// <param name="model"></param>
    /// <param name="textBlock"></param>
    protected string CreateTextElementFromTextBlock(ref DgnModel model, ref TextBlock textBlock)
    {
        //CREATE text element.
        TextHandlerBase textElement = TextHandlerBase.CreateElement(null, textBlock);
        Assert.IsNotNull(textElement);
        Assert.AreEqual(true, textElement.IsTextElement);
    
        return (textElement.GetTextPart(textElement.GetTextPartIds (new TextQueryOptions()) [0])).ToString();
    }

    Code Snip: TextElement_CRUD_Test

    public void TextElement_CRUD_Test()
    {
    
        //Create a text block.
        TextBlock textBlock = new TextBlock (m_tbProps, m_pProps, m_runProps, m_defaultModel);
        textBlock.AppendText("Simple Text");
    
        //CREATE text element.
        TextElement textElement = (TextElement)TextHandlerBase.CreateElement(null, textBlock);
        textElement.AddToModel();
        Assert.IsNotNull(textElement);
        Assert.AreEqual(true, textElement.IsTextElement);
        Assert.AreEqual("Text", textElement.TypeName);
    
        //READ: We know this model contains a single text element.
        {
            //Read from current element.
            foreach (TextPartId tId in textElement.GetTextPartIds (new TextQueryOptions()))
            {
                TextBlock tBlock = textElement.GetTextPart(tId);
                Assert.IsNotNull(tBlock);
                Assert.AreEqual ("Simple Text", tBlock.ToString ());
            }
        }
    
        {
            //Read from model.
            foreach (Element element in m_defaultModel.GetGraphicElements())
            {
                if (element.TypeName.Equals("Text"))
                {
                    TextElement textEeh = (TextElement)element;
                    foreach (TextPartId tId in textEeh.GetTextPartIds (new TextQueryOptions()))
                    {
                        TextBlock tBlock = textEeh.GetTextPart(tId);
                        Assert.IsNotNull(tBlock);
                        Assert.AreEqual ("Simple Text", tBlock.ToString ());
                    }
                }
                else
                    Assert.Fail("This model should contain only one text element");
            }
        }
    
        //UPDATE text.
        TextEdit tEdit = textElement.AsTextEdit();
    
        TextPartIdCollection textParts = tEdit.GetTextPartIds (new TextQueryOptions());
        Assert.AreEqual(1, textParts.Count);
        TextPartId partId = textParts[0]; //We have confirmed that it contains one text part id.
        TextBlock textBlock2 = tEdit.GetTextPart(partId);
        Assert.AreEqual(false, textBlock2.IsEmpty);
        textBlock2.Remove(textBlock2.CreateStartCaret(), textBlock2.CreateEndCaret());
        Assert.AreEqual(true, textBlock2.IsEmpty);
        textBlock2.AppendText("This is updated text");
        Assert.AreEqual(false, textBlock2.IsEmpty);
        Assert.AreEqual(TextReplaceStatus.Success, tEdit.ReplaceTextPart(partId, textBlock2));
        tEdit.ReplaceInModel(textElement);
        Assert.AreEqual(StatusInt.Success, m_dgnFile.ProcessChanges(DgnSaveReason.ApplicationInitiated));
    
        //READ again: We know this model contains a single text element.
        {
            //Read from current element.
            foreach (TextPartId tId in tEdit.GetTextPartIds (new TextQueryOptions()))
            {
                TextBlock tBlock = tEdit.GetTextPart(tId);
                Assert.IsNotNull(tBlock);
                Assert.AreEqual ("This is updated text", tBlock.ToString ());
            }
        }
    
        {
            //Read from model.
            foreach (Element element in m_defaultModel.GetGraphicElements())
            {
                if (element.TypeName.Equals("Text"))
                {
                    TextElement textEeh = (TextElement)element;
                    foreach (TextPartId tId in textEeh.GetTextPartIds (new TextQueryOptions()))
                    {
                        TextBlock tBlock = textEeh.GetTextPart(tId);
                        Assert.IsNotNull(tBlock);
                        Assert.AreEqual ("This is updated text", tBlock.ToString ());
                    }
                }
                else
                    Assert.Fail("This model should contain only one text element");
            }
        }
    
        TextElement elemToDelete = null;
    
        //Read from model.
        foreach (Element element in m_defaultModel.GetGraphicElements())
        {
            if (element.TypeName.Equals("Text"))
            {
                elemToDelete = (TextElement)element;
            }
        }
    
        //We are sure that a text element exist in model.
        Assert.IsNotNull(elemToDelete);
    
        //DELETE:
        Assert.AreEqual(StatusInt.Success, textElement.DeleteFromModel());
        Assert.AreEqual(StatusInt.Success, m_dgnFile.ProcessChanges(DgnSaveReason.ApplicationInitiated));
    
    }

    Let me know if you need something more.

    HTH,
    Bob



  • The following are a few .NET unit tests I found

    Thanks, but those are mostly about text creation, apart from one or two uses of text parts to find a simple text string.

    A type 17 text element is easy to navigate, because it contains a single string, which TextBlock.ToString() provides.  I'm asking for hints about navigating a more complex type 7 text element, such as a text node that contains multiple text elements...

    Line 1
    Line 2
    Line 3

    Or has different text styles for concatenated strings...

    Word 1 Word 2 Word 3

    (You can create either of the above using MicroStation's text editor)

    For example...

    • How do I get a run or paragraph for Line 2 or Word 3
    • How do I find the text style applied to Word 2?
    • How do I get the origin of text elements Line 1, Line 2 and Line 3?

     
    Regards, Jon Summers
    LA Solutions

Reply
  • The following are a few .NET unit tests I found

    Thanks, but those are mostly about text creation, apart from one or two uses of text parts to find a simple text string.

    A type 17 text element is easy to navigate, because it contains a single string, which TextBlock.ToString() provides.  I'm asking for hints about navigating a more complex type 7 text element, such as a text node that contains multiple text elements...

    Line 1
    Line 2
    Line 3

    Or has different text styles for concatenated strings...

    Word 1 Word 2 Word 3

    (You can create either of the above using MicroStation's text editor)

    For example...

    • How do I get a run or paragraph for Line 2 or Word 3
    • How do I find the text style applied to Word 2?
    • How do I get the origin of text elements Line 1, Line 2 and Line 3?

     
    Regards, Jon Summers
    LA Solutions

Children
No Data