PageHeaders.vb
''
'' This code is part of Document Solutions for PDF demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text

'' Demonstrates a simple way to generate left/centered/right aligned page headers and footers.
Public Class PageHeaders

    '' The document being generated:
    Private _doc As GcPdfDocument

    '' Utility method to draw a part of a page header or footer.
    '' Parameters:
    '' - text: The part's text.
    '' - tf: The text format to use.
    '' - pageIdx: The page index.
    '' - header: True if this is a header, false if a footer.
    '' - horzAlign: Horizontal alignment (left/center/right).
    Private Sub RenderHeader(ByVal text As String, ByVal tf As TextFormat, ByVal pageIdx As Integer, ByVal header As Boolean, ByVal horzAlign As TextAlignment)
        Dim page = _doc.Pages(pageIdx)
        Dim tl = New TextLayout(72) With {.Resolution = page.Graphics.Resolution}
        tl.MaxWidth = page.Size.Width
        tl.MaxHeight = page.Size.Height
        '' 1" margins, adjust as needed:
        tl.MarginLeft = 72
        tl.MarginRight = 72
        '' 1/3" spacing above top/below bottom header, adjust as needed:
        tl.MarginTop = 72 / 3
        tl.MarginBottom = tl.MarginTop
        '' Vertical alignment:
        tl.ParagraphAlignment = If(header, ParagraphAlignment.Near, ParagraphAlignment.Far)
        '' Horizontal alignment:
        tl.TextAlignment = horzAlign
        tl.Append(text, tf)
        '' NOTE: if some part of a header or footer is static, we could cache the corresponding TextLayout
        '' object and save some cycles by just drawing that cached TextLayout on each page w/out anything else:
        tl.PerformLayout(True)
        '' Draw the header at (0,0) (header located by margins and alignment):
        page.Graphics.DrawTextLayout(tl, PointF.Empty)
    End Sub

    '' The main program.
    Function CreatePDF(ByVal stream As Stream) As Integer
        _doc = New GcPdfDocument()
        Dim page = _doc.NewPage()
        '' Add a note about flipping landscape:
        Dim noteRect = Util.AddNote(
                "We flip page orientation in this sample only to show that these page headers can adapt to the changing page size.",
                page)
        ''
        '' Prepare a TextLayout with some long text and print it (see PaginatedText for details):
        Dim tl = page.Graphics.CreateTextLayout()
        tl.DefaultFormat.Font = StandardFonts.Times
        tl.DefaultFormat.FontSize = 12
        tl.MaxWidth = _doc.PageSize.Width
        tl.MaxHeight = _doc.PageSize.Height
        tl.MarginAll = tl.Resolution
        tl.MarginTop = noteRect.Bottom + 18
        '' Add sample text:
        tl.Append(Util.LoremIpsum(20))
        '' Calculate glyphs and perform layout (see also PerformLayout call in the loop below):
        tl.PerformLayout(True)
        '' In a loop, split and render the text:
        While True
            Dim rest As TextLayout = Nothing
            Dim splitResult = tl.Split(Nothing, rest)
            page.Graphics.DrawTextLayout(tl, PointF.Empty)
            If splitResult <> SplitResult.Split Then
                Exit While
            End If
            tl = rest
            tl.MarginTop = tl.Resolution
            page = _doc.Pages.Add()
            '' For sample sake, toggle page orientation:
            page.Landscape = Not _doc.Pages(_doc.Pages.Count - 2).Landscape
            '' Update layout size to reflect the new page orientation:
            tl.MaxWidth = page.Size.Width
            tl.MaxHeight = page.Size.Height
            '' Because we changed layout size, we must perform layout again -
            '' but can do it without recalculating glyphs:
            tl.PerformLayout(False)
        End While
        '' Render the headers in a separate loop (so that we can provide 'Page X of Y' header):
        Dim tf = New TextFormat() With {.Font = StandardFonts.Helvetica, .FontSize = 10, .ForeColor = Color.Gray}
        Dim now = Util.TimeNow().ToString("u")
        For pageIdx = 0 To _doc.Pages.Count - 1
            RenderHeader(now, tf, pageIdx, True, TextAlignment.Leading)
            RenderHeader("Easy Page Headers Sample", tf, pageIdx, True, TextAlignment.Center)
            RenderHeader($"Page {pageIdx + 1} of {_doc.Pages.Count}", tf, pageIdx, True, TextAlignment.Trailing)
            RenderHeader("Page footer - left", tf, pageIdx, False, TextAlignment.Leading)
            RenderHeader("DsPdf", tf, pageIdx, False, TextAlignment.Center)
            RenderHeader("Page footer - right", tf, pageIdx, False, TextAlignment.Trailing)
        Next
        ''
        '' Done:
        _doc.Save(stream)
        Return _doc.Pages.Count
    End Function
End Class