HierarchicalTable.vb
''
'' This code is part of Document Solutions for Imaging demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.Drawing
Imports System.IO
Imports System.Numerics
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Layout
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' This example shows how to draw a table with hierarchical data,
'' using the GrapeCity.Documents.Drawing.TableRenderer and related classes.
Public Class HierarchicalTable
    Public Function GenerateImage(
        ByVal pixelSize As Size,
        ByVal dpi As Single,
        ByVal opaque As Boolean,
        Optional ByVal sampleParams As String() = Nothing) As GcBitmap

        Dim bmp = New GcBitmap(pixelSize.Width, pixelSize.Height, opaque, dpi, dpi)
        Using g = bmp.CreateGraphics(Color.White)
            g.Transform = Matrix3x2.CreateScale(1.6F)
            DrawTable(g, pixelSize.Width, pixelSize.Height)
            g.Transform = Matrix3x2.Identity
        End Using
        Return bmp
    End Function

    Private Class Range
        Public ReadOnly Property ValueLow As Double
        Public ReadOnly Property DeltaLow As Double
        Public ReadOnly Property ValueHigh As Double
        Public ReadOnly Property DeltaHigh As Double

        Public Sub New(valueLow As Double, deltaLow As Double, valueHigh As Double, deltaHigh As Double)
            Me.ValueLow = valueLow
            Me.DeltaLow = deltaLow
            Me.ValueHigh = valueHigh
            Me.DeltaHigh = deltaHigh
        End Sub
    End Class

    Private Class Scope
        Public ReadOnly Property Ntrials As Integer
        Public ReadOnly Property AD As Range
        Public ReadOnly Property [AS] As Range
        Public ReadOnly Property NR As Range
        Public ReadOnly Property RA As Range
        Public ReadOnly Property AV As Range

        Public Sub New(ntrials As Integer, ad As Range, [as] As Range, nr As Range, ra As Range, av As Range)
            Me.Ntrials = ntrials
            Me.AD = ad
            Me.[AS] = [as]
            Me.NR = nr
            Me.RA = ra
            Me.AV = av
        End Sub
    End Class

    Private Shared ReadOnly Data As Scope() = New Scope() {
        New Scope(20, New Range(50.5, 3.2, 74.8, 4.9), New Range(50.4, 3.6, 74.9, 6.8),
            New Range(50.3, 2.7, 75.2, 6.5), New Range(49.9, 2.6, 74.8, 6.6), New Range(50.3, 3.0, 74.9, 6.2)),
        New Scope(60, New Range(50.3, 4.5, 75.1, 4.5), New Range(50.8, 4.1, 75.6, 6.5),
            New Range(50.7, 3.4, 75.7, 5.7), New Range(49.5, 2.9, 74.7, 5.9), New Range(50.3, 3.7, 75.3, 5.6)),
        New Scope(100, New Range(52.6, 4.7, 75.9, 4.8), New Range(50.3, 4.6, 75.6, 5.9),
            New Range(51.1, 4.1, 75.3, 5.4), New Range(49.8, 3.3, 74.9, 5.3), New Range(51.9, 4.2, 75.4, 5.4)),
        New Scope(140, New Range(51.7, 5.3, 75.8, 7.0), New Range(49.8, 5.7, 75.4, 6.8),
            New Range(51.4, 4.4, 75.6, 5.6), New Range(49.5, 3.5, 74.6, 6.2), New Range(50.6, 4.7, 75.4, 6.4)),
        New Scope(180, New Range(51.5, 8.4, 76.2, 9.5), New Range(52.2, 6.6, 74.9, 7.0),
            New Range(52.0, 4.9, 75.7, 6.4), New Range(50.7, 4.2, 74.8, 6.3), New Range(51.6, 6.0, 75.4, 7.3))
    }

    Private Shared Sub DrawTable(g As GcGraphics, pageWidth As Single, pageHeight As Single)
        Dim host = New LayoutHost()
        Dim view = host.CreateView(pageWidth, pageHeight)

        Dim rt = view.CreateRect()
        rt.AnchorTopLeft(Nothing, 36, 36)

        Dim scopeCount = Data.Length

        Dim ta = New TableRenderer(g,
            rt, FixedTableSides.TopLeft,
            rowCount:=12,
            columnCount:=scopeCount + 2,
            gridLineColor:=Color.Black,
            gridLineWidth:=1,
            rowMinHeight:=20)

        '' Thicker width for some grid lines:
        ta.SetVerticalGridLineWidth(2, 3F)
        For i = 0 To 12 Step 2
            ta.SetHorizontalGridLineWidth(i, 3F)
        Next

        Dim fmt = New TextFormat() With
            {
                .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "NotoSerif-Regular.ttf")),
                .FontSize = 16,
                .FontSizeInGraphicUnits = True
            }

        ta.AddCell(0, 0, 2, 2)
        ta.AddCell(New CellStyle() With
            {
                .TextAlignment = TextAlignment.Center,
                .CreateTextLayout = Function(gr As GcGraphics, style As CellStyle, dat As Object)
                                         Dim tl = gr.CreateTextLayout()
                                         tl.Append("|", fmt)
                                         tl.Append("N", New TextFormat(fmt) With {.FontItalic = True})
                                         tl.Append("trials", New TextFormat(fmt) With {.FontItalic = True, .Subscript = True})
                                         tl.Append("|", fmt)
                                         Return tl
                                     End Function
            }, 0, 2, 1, scopeCount, Nothing)

        Dim cs = New CellStyle() With
            {
                .PaddingLeftRight = 10,
                .TextAlignment = TextAlignment.Center,
                .ParagraphAlignment = ParagraphAlignment.Center,
                .FixedWidth = False,
                .TextFormat = fmt
            }

        '' Add a rotated cell:
        ta.AddCell(New CellStyle(cs) With
            {
                .PaddingTopBottom = 10,
                .RotationAngle = 270
            }, 2, 0, 8, 1, "Subject")

        '' Assign a style to DefaultCellStyle to avoid passing
        '' it to each call of the AddCell method:
        ta.DefaultCellStyle = cs

        ta.AddCell(2, 1, 2, 1, "AD")
        ta.AddCell(4, 1, 2, 1, "AS")
        ta.AddCell(6, 1, 2, 1, "NR")
        ta.AddCell(8, 1, 2, 1, "RA")
        ta.AddCell(10, 0, 2, 2, "Average:")

        For i = 0 To scopeCount - 1
            Dim sc = Data(i)
            Dim ci = i + 2
            ta.AddCell(1, ci, sc.Ntrials.ToString())
            ta.AddCell(2, ci, $"{sc.AD.ValueLow:n1} ± {sc.AD.DeltaLow:n1}")
            ta.AddCell(3, ci, $"{sc.AD.ValueHigh:n1} ± {sc.AD.DeltaHigh:n1}")
            ta.AddCell(4, ci, $"{sc.[AS].ValueLow:n1} ± {sc.[AS].DeltaLow:n1}")
            ta.AddCell(5, ci, $"{sc.[AS].ValueHigh:n1} ± {sc.[AS].DeltaHigh:n1}")
            ta.AddCell(6, ci, $"{sc.NR.ValueLow:n1} ± {sc.NR.DeltaLow:n1}")
            ta.AddCell(7, ci, $"{sc.NR.ValueHigh:n1} ± {sc.NR.DeltaHigh:n1}")
            ta.AddCell(8, ci, $"{sc.RA.ValueLow:n1} ± {sc.RA.DeltaLow:n1}")
            ta.AddCell(9, ci, $"{sc.RA.ValueHigh:n1} ± {sc.RA.DeltaHigh:n1}")
            ta.AddCell(10, ci, $"{sc.AV.ValueLow:n1} ± {sc.AV.DeltaLow:n1}")
            ta.AddCell(11, ci, $"{sc.AV.ValueHigh:n1} ± {sc.AV.DeltaHigh:n1}")
        Next

        '' Add a special background to every other row:
        ta.DefaultCellStyle = New CellStyle() With
            {
                .FillColor = Color.FromArgb(233, 240, 222),
                .Background = True
            }
        For i = 3 To 11 Step 2
            ta.AddCell(i, 2, 1, scopeCount)
        Next

        ta.Render()
    End Sub
End Class