Nevron Open Vision Documentation
Rich Text Editor / Document Model / Blocks / Advanced Block Layout
In This Topic
    Advanced Block Layout
    In This Topic

    In the previous topic, we discussed how to make block elements floating as well as how to instruct the layout of the control to position blocks relative to pages when the control uses a paging view. Those features closely mimic the HTML properties for block layout. One of the areas where HTML falls behind in terms of features compared to traditional text processing and page authoring programs is the ability to position blocks relative to pages as well as to specify how floating blocks should affect inline content when it enters an area occupied by a floating block. Those shortcomings in HTML are addressed in Nevron Rich Text.

    The following properties are applied only to blocks that do not have intrinsic positioning - this includes paragraphs, tables, group blocks, and shape blocks. Block positioning properties are not regarded for root blocks, sections, table rows and cells.
     Horizontal and Vertical Block Anchor

    By default all blocks present in the content are layout using the normal flow layout (with the exception of table cells). In this layout each block is positioned vertically after the previous block in the content tree. In many cases when you want to produce truly dynamic layouts this type of layout is not sufficient to address all the possible positions of the block. The HorizontalAnchor and VerticalAnchor properties of the block allow you to specify how the block is positioned horizontally and vertically.

    Horizontal Anchor

    The horizontal anchor controls how the block is positioned horizontally by defining a range of x coordinates which the block uses to position itself. The horizontal anchor is controlled from the HorizontalAnchor property which accepts values from the ENHorizontalAnchor enum. The following table lists the available options:

    ENHorizontalAnchor Description
    Flow Block uses normal flow. In this case the block is positioned horizontally relative to the containing block x range.
    Margin In this mode the block is positioned relatively to the margin of the page that contains the block.
    Page In this mode the block is positioned relatively to the page that contains the block.
    LeftMargin Specifies that the horizontal positioning shall be relative to the left margin of the page that contains the block.
    RightMargin Specifies that the horizontal positioning shall be relative to the right margin of the page.
    InsideMargin Specifies that the horizontal positioning shall be relative to the inside margin of the current page (the left margin on odd pages, right on even pages).
    OutsideMargin Specifies that the horizontal positioning shall be relative to the outside margin of the current page (the right margin on odd pages, left on even pages).
    Ancestor In this mode the block is positioned relatively to the first ancestor block that has the AllowAnchoredDescendantBlocks property set to true. In the absence of such block the block is positioned relatively to its root block.

    Vertical Anchor

    Similarly the vertical anchor defines a range of y values relative to which the block is positioned. It is controlled from the VerticalAnchor property accepting values from the ENVerticalAnchor enum:

    ENVerticalAnchor Description
    Flow Block uses normal flow. In this case the block is positioned vertically relative to the first previous block bottom with Flow vertical anchor.
    Margin In this mode the block is positioned relatively to the margin of the page that contains the block.
    Page In this mode the block is positioned relatively to the page that contains the block.
    TopMargin In this mode the block is positioned relatively to the top margin of the page that contains the block.
    BottomMargin In this mode the block is positioned relatively to the bottom margin of the page that contains the block.
    InsideMargin In this mode the block is positioned relatively to the inside margin of the page that contains the block (the top margin on odd pages, bottom on even pages).
    OutsideMargin In this mode the block is positioned relatively to the outside margin of the page that contains the block (the bottom margin on odd pages, left on even pages).
    Ancestor In this mode the block is positioned relatively to the first ancestor block top that has the AllowAnchoredDescendantBlocks property set to true. In the absence of such block the block is positioned relatively to its root block.

    The following code snippet shows how to place a block at the left top of the block containing page in print layout:

    Setting Block Horizontal and Vertical Anchors
    Copy Code
    someBlock.HorizontalAnchor = ENHorizontalAnchor.Page;
    someBlock.VerticalAnchor = ENVerticalAnchor.Page;
    
    Setting the vertical block anchor to Page or Ancestor removes the block from the flow. Subsequent blocks with vertical anchor flow will be layout against the first block with flow vertical anchor preceding this block.

     Horizontal and Vertical Block Alignment

    When you define the reference x and y ranges against which the block is positioned you can further specify how the block is aligned relative to those ranges. This is achieved from the HorizontalBlockAlignment and VerticalBlockAlignment properties.

    Horizontal Alignment

    The horizontal alignment is controlled from the HorizontalBlockAlignment property - it accepts values from the ENHorizontalBlockAlignment enum:

    ENHorizontalBlockAlignment Description
    Left The block is aligned to the left of the reference x range
    Center The block is centered relative to the reference x range
    Right The block is aligned to the right of the reference x range

    Vertical Alignment

    The vertical alignment is controlled from the VerticalBlockAlignment property - it accepts values from the ENVerticalBlockAlignment enum:

    ENVerticalBlockAlignment Description
    Top The block is aligned to the top of the reference y range
    Center The block is centered relative to the reference y range
    Bottom The block is aligned to the bottom of the reference y range

    The following code snippet shows how to center a block relative to the block containing page in print layout:

    Setting Block Horizontal and Vertical Alignment
    Copy Code
    someBlock.HorizontalAnchor = ENHorizontalAnchor.Page;
    someBlock.VerticalAnchor = ENVerticalAnchor.Page;
    someBlock.HorizontalBlockAlignment = ENHorizontalBlockAlignment.Center;
    someBlock.VerticalBlockAlignment = ENVerticalBlockAlignment.Center;
    
    Vertical block alignment is ignored in case the vertical block anchor is set to ENVerticalAnchor.Flow (which is the default).

     Horizontal and Vertical Offset

    After the block position is determined from the Anchor/Alignment properties you can further apply an additional offset in the horizontal and vertical direction using the XOffset and YOffset properties.

    Setting Block X and Y Offset
    Copy Code
    someBlock.XOffset = 10;
    someBlock.YOffset = 15;
    
     Wrap Mode

    The WrapMode property of the block allows you to specify whether the block will be removed from the flow and whether it will present an obstacle for inline content for other blocks that have inline content, which resides in the area occupied by the block. The following table lists the available options:

    ENWrapMode Description
    None The block does not use wrapping
    Before Block allows inline content to flow only before its left edge. Block is removed from the flow.
    After Block allows inline content to flow only after its right edge. Block is removed from the flow.
    Parallel Block allows inline content to flow before its left edge and after its right edge. Block is removed from the flow.
    Through Block allows inline content to flow inside its area. Block is removed from the flow.
    When the block vertical anchor is flow and you set a block wrap mode to Before, After or Parallel the block will choose a block position which does not overlap other floating blocks which also have vertical anchor flow.
     Common Tasks

    How to Implement Normal Left and Right floating blocks just like in HTML

    HTML allows blocks to float to the left or right side of the contain block. This is achieved with the following property configuration:

    HTML Float Mode Equivalent Settings
    Normal
    Setting Block Flow to Normal
    Copy Code
    // Normal
    someBlock.HorizontalAnchor = ENHorizontalAnchor.Flow;
    someBlock.HorizontalBlockAlignment = ENHorizontalBlockAlignment.Left;
    someBlock.VerticalAnchor = ENVerticalAnchor.Flow;
    someBlock.VerticalBlockAlignment = ENVerticalBlockAlignment.Top;
    someBlock.WrapMode = ENWrapMode.None;
    
    Left
    Setting Block Flow to Left
    Copy Code
    // Left
    someBlock.HorizontalAnchor = ENHorizontalAnchor.Flow;
    someBlock.HorizontalBlockAlignment = ENHorizontalBlockAlignment.Left;
    someBlock.VerticalAnchor = ENVerticalAnchor.Flow;
    someBlock.VerticalBlockAlignment = ENVerticalBlockAlignment.Top;
    someBlock.WrapMode = ENWrapMode.After;
    
    Right
    Setting Block Flow to Right
    Copy Code
    // Right
    someBlock.HorizontalAnchor = ENHorizontalAnchor.Flow;
    someBlock.HorizontalBlockAlignment = ENHorizontalBlockAlignment.Right;
    someBlock.VerticalAnchor = ENVerticalAnchor.Flow;
    someBlock.VerticalBlockAlignment = ENVerticalBlockAlignment.Top;
    someBlock.WrapMode = ENWrapMode.Before;
    

    How to Implement Relative Positioned Blocks like in HTML

    Relatively positioned blocks serve for two purposes - the first one is to act as anchors (or coordinate system parents) for absolutely positioned blocks and the second one is to be able to move a block relatively to its original flow position. In Nevron Text these two tasks are achieved as by setting the AllowAnchoredDescendantBlocks property to true and by modifying the XOffset and YOffset properties respectively.

    Setting Block Relative Position Properties
    Copy Code
    someBlock.AllowAnchoredDescendantBlocks = true;
    someBlock.XOffset = 10;
    someBlock.YOffset = -10;
    

    How to Implement Absolute Positioned Blocks like in HTML

    Absolutely positioned block in HTML can be aligned relative to the first parent block which uses either relative or absolute position. In Nevron Text absolutely positioned blocks are achieved by setting the AllowAnchoredDescendantBlocks property to true of the ancestor block relative to which you want to position the block and then modifying the horizontal and vertical block anchors. The following code snippet shows how to implement an absolutely positioned paragraph contained in a group block:

    Setting Block Relative Position Properties
    Copy Code
    // create a section
    NSection section = new NSection();
    
    NGroupBlock groupBlock = new NGroupBlock();
    groupBlock.PreferredHeight = new NMultiLength(ENMultiLengthUnit.Dip, 200);
    groupBlock.Border = NBorder.CreateFilledBorder(NColor.Black);
    groupBlock.BorderThickness = new NMargins(2);
    groupBlock.AllowAnchoredDescendantBlocks = true;
    
    // create an absolutely positioned paragraph
    NParagraph absolutePositionedParagraph = new NParagraph("Absolutely Positioned Paragraph");
    absolutePositionedParagraph.BackgroundFill = new NColorFill(ENNamedColor.Red);
    
    absolutePositionedParagraph.HorizontalAnchor = ENHorizontalAnchor.Ancestor;
    absolutePositionedParagraph.VerticalAnchor = ENVerticalAnchor.Ancestor;
    absolutePositionedParagraph.XOffset = 100;
    absolutePositionedParagraph.YOffset = 100;
    
    // create normal positioned paragraphs
    NParagraph normalPositionedParagraph1 = new NParagraph("Normal Positioned Paragraph 1");
    normalPositionedParagraph1.BackgroundFill = new NColorFill(ENNamedColor.Green);
    NParagraph normalPositionedParagraph2 = new NParagraph("Normal Positioned Paragraph 2");
    normalPositionedParagraph2.BackgroundFill = new NColorFill(ENNamedColor.Green);
    
    // add them to the group block
    groupBlock.Blocks.Add(normalPositionedParagraph1);
    groupBlock.Blocks.Add(absolutePositionedParagraph);
    groupBlock.Blocks.Add(normalPositionedParagraph2);
    
    section.Blocks.Add(groupBlock);
    
    m_RichText.Content.Sections.Clear();
    m_RichText.Content.Sections.Add(section);
    

    This code produces the following image:

    Notice how the absolutely positioned paragraph is taken out of the flow. This leads to the second normal flow paragraph (normalPositionedParagraph2) in the block to be adjacent to the first one (normalPositionedParagraph1). Also when using a horizontal anchor different from ENHorizontalAnchor.Flow, the block width will be computed based on the desired width instead of the parent content width, just like in HTML.

    See Also