NumberedList.vb
''
'' This code is part of GrapeCity Documents for PDF samples.
'' Copyright (c) GrapeCity, Inc. All rights reserved.
''
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Drawing

'' Demonstrates how paragraphs of text can be rendered as a numbered list in GcPdf.
'' The method of rendering pages of text in this sample is taken from the PaginatedText
'' sample. See also TextRendering.
Public Class NumberedList
    '' Encapsulate page layout constants used in the sample:
    Private Structure Layout
        Public Shared Margin As Single = 72.0F
        Public Shared ListOffset As Single = 24.0F
    End Structure

    '' Utility method which pre-pends numbers to all paragraphs in a TextLayout.
    Private Sub AddBullets(ByVal g As GcGraphics, ByVal pt As PointF, ByVal tl As TextLayout, ByRef itemNo As Integer)
        Dim tlBullet = New TextLayout()
        tlBullet.DefaultFormat.Font = StandardFonts.Times
        tlBullet.DefaultFormat.FontSize = 12
        For Each line In tl.Lines
            If (line.FirstLineInParagraph) Then
                tlBullet.Clear()
                tlBullet.Append($"{itemNo})")
                itemNo += 1
                tlBullet.PerformLayout(True)
                g.DrawTextLayout(tlBullet, New PointF(pt.X, pt.Y + line.Position + line.LineGap))
            End If
        Next
    End Sub

    '' Main entry point:
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Dim ip = New PointF(Layout.Margin, Layout.Margin)

        '' Use TextLayout.MarginLeft to reserve space for list numbers/bullets:
        Dim tl = New TextLayout() With {
            .MaxWidth = doc.PageSize.Width - Layout.Margin * 2,
            .MaxHeight = doc.PageSize.Height - Layout.Margin * 2,
            .ParagraphSpacing = 8,
            .MarginLeft = Layout.ListOffset
        }
        tl.DefaultFormat.Font = StandardFonts.Times

        '' Add 20 paragraphs of text that will render as a numbered list of 20 items:
        tl.Append(Util.LoremIpsum(20, 1, 6))
        '' Perform layout:
        tl.PerformLayout(True)
        '' Use split options to provide widow/orphan control:
        Dim tso = New TextSplitOptions(tl)
        tso.MinLinesInFirstParagraph = 2
        tso.MinLinesInLastParagraph = 2
        '' In a loop, split and render the text (see PaginatedText),
        '' and add list numbers:
        Dim itemNo = 1
        While (True)
            '' 'rest' will accept the text that did not fit:
            Dim rest As TextLayout = Nothing
            Dim splitResult = tl.Split(tso, rest)
            Dim g = doc.Pages.Add().Graphics
            g.DrawTextLayout(tl, ip)
            AddBullets(g, ip, tl, itemNo)
            If splitResult <> SplitResult.Split Then
                Exit While
            End If
            tl = rest
        End While
        ''
        '' Done:
        doc.Save(stream)
        Return doc.Pages.Count
    End Function
End Class