Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.Windows.Forms
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Composition
Imports Nexamas.UI.Controls
Imports Nexamas.UI.General
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    Partial Public NotInheritable Class MASTreeGrid

#Region "Rendering"

        Protected Overrides Sub Render(canvas As SKCanvas,
                                       ctx As MASThemeContext,
                                       pixelBounds As SKRect)
            If canvas Is Nothing OrElse ctx Is Nothing Then Return
            If pixelBounds.Width <= 1.0F OrElse pixelBounds.Height <= 1.0F Then Return

            Dim dpi As Single = PixelSnap.SafeDpi(ctx.Dpi)
            _lastDpi = dpi
            Dim bounds As SKRect = PixelSnap.SnapRect(pixelBounds, dpi)
            If bounds.Width <= 1.0F OrElse bounds.Height <= 1.0F Then Return

            Dim responsiveProfile As MASResponsiveLayoutProfile = MASResponsiveLayoutResolver.FromTheme(ctx, bounds, SizeIntent, MASTreeGridLayoutPlan.Thresholds)
            Dim plan As MASTreeGridLayoutPlan = MASTreeGridLayoutPlan.Create(responsiveProfile)
            _lastDpi = plan.Dpi

            _primitives.DrawCardSurface(canvas, ctx, bounds, dpi, Me.ArchitectureContract, MASCardVisualStyle.Secondary)
            _contentRect = PixelSnap.SnapRect(Inset(bounds, plan.ContentInsetPx), dpi)
            If _contentRect.Width <= 1.0F OrElse _contentRect.Height <= 1.0F Then Return

            _rowHits.Clear()
            Dim isRtl As Boolean = MASTreeGridPolicy.ResolveRightToLeft()
            Dim accent As SKColor = MASTreeGridPolicy.ResolveAccentColor(ctx)
            If plan.ShowHeader Then DrawHeader(canvas, ctx, _contentRect, plan, accent, isRtl)
            DrawGrid(canvas, ctx, _contentRect, plan, accent, isRtl)
            If plan.ShowFooter Then DrawFooter(canvas, ctx, _contentRect, plan, isRtl)
        End Sub

        Private Sub DrawHeader(canvas As SKCanvas,
                               ctx As MASThemeContext,
                               content As SKRect,
                               plan As MASTreeGridLayoutPlan,
                               accent As SKColor,
                               isRtl As Boolean)
            Dim dpi As Single = plan.Dpi
            Dim header As New SKRect(content.Left, content.Top, content.Right, content.Top + plan.HeaderHeightPx)
            Dim align As TypographyTextPrimitives.TextAlign = If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, _title, header, dpi, MASTypography.MASTextStyle.Title, MASTreeGridPolicy.ResolvePrimaryTextColor(ctx), align, False)

            If Not plan.ShowHeaderSummary Then Return
            Dim summaryWidth As Single = Math.Min(plan.SummaryWidthPx, header.Width * 0.48F)
            Dim summaryRect As SKRect = If(isRtl,
                                           New SKRect(header.Left, header.Top, header.Left + summaryWidth, header.Bottom),
                                           New SKRect(header.Right - summaryWidth, header.Top, header.Right, header.Bottom))
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, SummaryText, summaryRect, dpi, MASTypography.MASTextStyle.Micro, MASTreeGridPolicy.ResolveMutedTextColor(ctx), If(isRtl, TypographyTextPrimitives.TextAlign.Left, TypographyTextPrimitives.TextAlign.Right), False)
        End Sub

        Private Sub DrawGrid(canvas As SKCanvas,
                             ctx As MASThemeContext,
                             content As SKRect,
                             plan As MASTreeGridLayoutPlan,
                             accent As SKColor,
                             isRtl As Boolean)
            Dim dpi As Single = plan.Dpi
            Dim top As Single = content.Top + plan.HeaderHeightPx + plan.HeaderGapPx
            Dim bottom As Single = content.Bottom - plan.FooterHeightPx - plan.FooterGapPx
            _gridRect = PixelSnap.SnapRect(New SKRect(content.Left, top, content.Right, bottom), dpi)
            If _gridRect.Width <= 1.0F OrElse _gridRect.Height <= 1.0F Then Return

            Using fill As New SKPaint()
                fill.IsAntialias = True
                fill.Style = SKPaintStyle.Fill
                fill.Color = accent.WithAlpha(TreeGridTokens.GridFillAlpha)
                canvas.DrawRoundRect(_gridRect, TreeGridTokens.GridRadiusDip * dpi, TreeGridTokens.GridRadiusDip * dpi, fill)
            End Using

            Using stroke As New SKPaint()
                stroke.IsAntialias = True
                stroke.Style = SKPaintStyle.Stroke
                stroke.StrokeWidth = Math.Max(1.0F, dpi)
                stroke.Color = accent.WithAlpha(TreeGridTokens.GridStrokeAlpha)
                canvas.DrawRoundRect(_gridRect, TreeGridTokens.GridRadiusDip * dpi, TreeGridTokens.GridRadiusDip * dpi, stroke)
            End Using

            Dim headerRect As New SKRect(_gridRect.Left, _gridRect.Top, _gridRect.Right, _gridRect.Top + plan.GridHeaderHeightPx)
            DrawColumnHeaders(canvas, ctx, headerRect, plan, accent, isRtl)

            Dim rowsRect As New SKRect(_gridRect.Left + plan.GridInnerInsetPx,
                                       headerRect.Bottom + plan.GridInnerInsetPx,
                                       _gridRect.Right - plan.GridInnerInsetPx,
                                       _gridRect.Bottom - plan.GridInnerInsetPx)
            DrawRows(canvas, ctx, rowsRect, plan, accent, isRtl)
        End Sub

        Private Sub DrawColumnHeaders(canvas As SKCanvas,
                                      ctx As MASThemeContext,
                                      headerRect As SKRect,
                                      plan As MASTreeGridLayoutPlan,
                                      accent As SKColor,
                                      isRtl As Boolean)
            Dim dpi As Single = plan.Dpi
            Using fill As New SKPaint()
                fill.IsAntialias = True
                fill.Style = SKPaintStyle.Fill
                fill.Color = accent.WithAlpha(TreeGridTokens.HeaderFillAlpha)
                canvas.DrawRoundRect(headerRect, TreeGridTokens.GridRadiusDip * dpi, TreeGridTokens.GridRadiusDip * dpi, fill)
            End Using

            Dim labelRect As SKRect = GetLabelColumnRect(headerRect, dpi, isRtl)
            Dim align As TypographyTextPrimitives.TextAlign = If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, TreeGridTokens.LabelHeaderText, InsetHorizontal(labelRect, TreeGridTokens.CellPaddingDip * dpi), dpi, MASTypography.MASTextStyle.Micro, MASTreeGridPolicy.ResolveMutedTextColor(ctx), align, False)

            Dim valueRects As List(Of SKRect) = GetVisibleValueColumnRects(headerRect, labelRect, dpi, isRtl, plan.MaxVisibleValueColumns)
            For i As Integer = 0 To valueRects.Count - 1
                Dim columnIndex As Integer = _leftColumnIndex + i
                If columnIndex >= _columns.Count Then Continue For
                Dim header As String = _columns(columnIndex).Header
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, header, InsetHorizontal(valueRects(i), TreeGridTokens.CellPaddingDip * dpi), dpi, MASTypography.MASTextStyle.Micro, MASTreeGridPolicy.ResolveMutedTextColor(ctx), align, False)
                DrawVerticalDivider(canvas, valueRects(i), dpi, accent, isRtl)
            Next
        End Sub

        Private Sub DrawRows(canvas As SKCanvas,
                             ctx As MASThemeContext,
                             rowsRect As SKRect,
                             plan As MASTreeGridLayoutPlan,
                             accent As SKColor,
                             isRtl As Boolean)
            Dim dpi As Single = plan.Dpi
            NormalizeViewState()
            Dim visibleRows As List(Of VisibleTreeGridRow) = BuildVisibleRows()
            If visibleRows.Count = 0 Then
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, TreeGridTokens.EmptyTreeText, rowsRect, dpi, MASTypography.MASTextStyle.Body, MASTreeGridPolicy.ResolveMutedTextColor(ctx).WithAlpha(TreeGridTokens.EmptyTextAlpha), TypographyTextPrimitives.TextAlign.Center, False)
                Return
            End If
            Dim rowHeight As Single = plan.RowHeightPx
            Dim rowGap As Single = plan.RowGapPx
            Dim labelRectTemplate As SKRect = GetLabelColumnRect(rowsRect, dpi, isRtl)
            Dim valueRectsTemplate As List(Of SKRect) = GetVisibleValueColumnRects(rowsRect, labelRectTemplate, dpi, isRtl, plan.MaxVisibleValueColumns)
            Dim maxRowsFromSpace As Integer = Math.Max(1, CInt(Math.Floor((rowsRect.Height + rowGap) / (rowHeight + rowGap))))
            _rowViewportCapacity = Math.Max(1, Math.Min(plan.MaxVisibleRows, maxRowsFromSpace))
            _topRowIndex = EnsureVisibleRowIndex(FindVisibleIndex(_selectedRowKey, visibleRows), _topRowIndex, visibleRows.Count, _rowViewportCapacity)
            Dim maxRows As Integer = Math.Min(_rowViewportCapacity, visibleRows.Count - _topRowIndex)
            If maxRows <= 0 Then Return

            For visualIndex As Integer = 0 To maxRows - 1
                Dim rowIndex As Integer = _topRowIndex + visualIndex
                Dim item As VisibleTreeGridRow = visibleRows(rowIndex)
                Dim top As Single = rowsRect.Top + CSng(visualIndex) * (rowHeight + rowGap)
                Dim rowRect As SKRect = PixelSnap.SnapRect(New SKRect(rowsRect.Left, top, rowsRect.Right, top + rowHeight), dpi)
                DrawRow(canvas, ctx, rowRect, labelRectTemplate, valueRectsTemplate, dpi, accent, isRtl, item)
            Next

            DrawSelectionMotionOverlay(canvas, rowsRect, visibleRows, rowHeight, rowGap, dpi, accent, isRtl)
        End Sub

        Private Sub DrawRow(canvas As SKCanvas,
                            ctx As MASThemeContext,
                            rowRect As SKRect,
                            labelTemplate As SKRect,
                            valueTemplates As List(Of SKRect),
                            dpi As Single,
                            accent As SKColor,
                            isRtl As Boolean,
                            item As VisibleTreeGridRow)
            Dim row As TreeGridRowState = item.Row
            Dim selected As Boolean = String.Equals(row.Key, _selectedRowKey, StringComparison.Ordinal)
            If selected AndAlso IsSelectionMotionEndpoint(row.Key) Then selected = False
            Dim hovered As Boolean = String.Equals(row.Key, _hoverRowKey, StringComparison.Ordinal)
            Dim pressed As Boolean = String.Equals(row.Key, _pressedRowKey, StringComparison.Ordinal)
            Dim editing As Boolean = String.Equals(row.Key, _editingRowKey, StringComparison.Ordinal)
            Dim fillColor As SKColor = SKColors.Transparent
            If selected Then fillColor = accent.WithAlpha(TreeGridTokens.RowSelectedAlpha)
            If editing Then fillColor = accent.WithAlpha(TreeGridTokens.RowEditingAlpha)
            If hovered Then fillColor = accent.WithAlpha(TreeGridTokens.RowHoverAlpha)
            If pressed Then fillColor = accent.WithAlpha(TreeGridTokens.RowPressedAlpha)
            If fillColor.Alpha > 0 Then
                Using fill As New SKPaint()
                    fill.IsAntialias = True
                    fill.Style = SKPaintStyle.Fill
                    fill.Color = fillColor
                    canvas.DrawRoundRect(rowRect, TreeGridTokens.RowRadiusDip * dpi, TreeGridTokens.RowRadiusDip * dpi, fill)
                End Using
            End If

            If selected OrElse editing Then
                Using stroke As New SKPaint()
                    stroke.IsAntialias = True
                    stroke.Style = SKPaintStyle.Stroke
                    stroke.StrokeWidth = Math.Max(1.0F, dpi)
                    stroke.Color = accent.WithAlpha(If(editing, CByte(210), CByte(150)))
                    canvas.DrawRoundRect(rowRect, TreeGridTokens.RowRadiusDip * dpi, TreeGridTokens.RowRadiusDip * dpi, stroke)
                End Using
                Dim marker As SKRect = If(isRtl,
                                          New SKRect(rowRect.Right - 4.0F * dpi, rowRect.Top + 7.0F * dpi, rowRect.Right - 2.0F * dpi, rowRect.Bottom - 7.0F * dpi),
                                          New SKRect(rowRect.Left + 2.0F * dpi, rowRect.Top + 7.0F * dpi, rowRect.Left + 4.0F * dpi, rowRect.Bottom - 7.0F * dpi))
                Using markerPaint As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(If(editing, CByte(245), CByte(225)))}
                    canvas.DrawRoundRect(marker, 2.0F * dpi, 2.0F * dpi, markerPaint)
                End Using
            End If

            Dim labelRect As New SKRect(labelTemplate.Left, rowRect.Top, labelTemplate.Right, rowRect.Bottom)

            Dim indent As Single = CSng(item.Depth) * TreeGridTokens.TreeIndentDip * dpi
            Dim expanderSize As Single = TreeGridTokens.ExpanderSizeDip * dpi
            Dim expanderLeft As Single = If(isRtl, labelRect.Right - TreeGridTokens.CellPaddingDip * dpi - indent - expanderSize, labelRect.Left + TreeGridTokens.CellPaddingDip * dpi + indent)
            Dim expanderRect As SKRect = PixelSnap.SnapRect(New SKRect(expanderLeft, rowRect.MidY - expanderSize * 0.5F, expanderLeft + expanderSize, rowRect.MidY + expanderSize * 0.5F), dpi)
            DrawTreeDepthGuide(canvas, labelRect, item.Depth, dpi, accent, isRtl)
            If row.Children.Count > 0 Then DrawExpander(canvas, expanderRect, dpi, accent, row.Expanded, isRtl)

            Dim textStart As Single = expanderSize + 6.0F * dpi
            Dim textRect As SKRect
            If isRtl Then
                textRect = New SKRect(labelRect.Left + TreeGridTokens.CellPaddingDip * dpi, labelRect.Top, expanderRect.Left - 6.0F * dpi, labelRect.Bottom)
            Else
                textRect = New SKRect(expanderRect.Right + 6.0F * dpi, labelRect.Top, labelRect.Right - TreeGridTokens.CellPaddingDip * dpi, labelRect.Bottom)
            End If
            If row.Children.Count = 0 Then
                If isRtl Then
                    textRect = New SKRect(labelRect.Left + TreeGridTokens.CellPaddingDip * dpi, labelRect.Top, labelRect.Right - TreeGridTokens.CellPaddingDip * dpi - indent, labelRect.Bottom)
                Else
                    textRect = New SKRect(labelRect.Left + TreeGridTokens.CellPaddingDip * dpi + indent + textStart, labelRect.Top, labelRect.Right - TreeGridTokens.CellPaddingDip * dpi, labelRect.Bottom)
                End If
            End If
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, row.Label, textRect, dpi, MASTypography.MASTextStyle.Body, MASTreeGridPolicy.ResolvePrimaryTextColor(ctx), If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)

            For i As Integer = 0 To valueTemplates.Count - 1
                Dim valueRect As New SKRect(valueTemplates(i).Left, rowRect.Top, valueTemplates(i).Right, rowRect.Bottom)
                Dim valueColumnIndex As Integer = _leftColumnIndex + i
                Dim valueText As String = String.Empty
                If valueColumnIndex >= 0 AndAlso valueColumnIndex < row.Values.Count Then valueText = row.Values(valueColumnIndex)
                DrawValuePresentation(canvas, ctx, valueRect, valueText, dpi, accent, isRtl)
                DrawVerticalDivider(canvas, valueRect, dpi, accent, isRtl)
            Next

            _rowHits.Add(New TreeGridRowHit(row.Key, rowRect, expanderRect))
        End Sub


        Private Function ResolveSelectionMotionRowRect(rowKey As String,
                                                       rowsRect As SKRect,
                                                       visibleRows As List(Of VisibleTreeGridRow),
                                                       rowHeight As Single,
                                                       rowGap As Single,
                                                       dpi As Single) As SKRect
            If String.IsNullOrWhiteSpace(rowKey) OrElse visibleRows Is Nothing OrElse visibleRows.Count = 0 Then Return SKRect.Empty
            Dim rowIndex As Integer = FindVisibleIndex(rowKey, visibleRows)
            If rowIndex < _topRowIndex OrElse rowIndex >= _topRowIndex + Math.Max(1, _rowViewportCapacity) Then Return SKRect.Empty
            Dim visualIndex As Integer = rowIndex - _topRowIndex
            Dim top As Single = rowsRect.Top + CSng(visualIndex) * (rowHeight + rowGap)
            Return PixelSnap.SnapRect(New SKRect(rowsRect.Left, top, rowsRect.Right, top + rowHeight), dpi)
        End Function

        Private Sub DrawSelectionMotionOverlay(canvas As SKCanvas,
                                               rowsRect As SKRect,
                                               visibleRows As List(Of VisibleTreeGridRow),
                                               rowHeight As Single,
                                               rowGap As Single,
                                               dpi As Single,
                                               accent As SKColor,
                                               isRtl As Boolean)
            If canvas Is Nothing OrElse Not IsSelectionMotionActive() Then Return
            Dim fromRect As SKRect = ResolveSelectionMotionRowRect(_selectionMotionFromRowKey, rowsRect, visibleRows, rowHeight, rowGap, dpi)
            Dim toRect As SKRect = ResolveSelectionMotionRowRect(_selectionMotionToRowKey, rowsRect, visibleRows, rowHeight, rowGap, dpi)
            If fromRect.IsEmpty OrElse toRect.IsEmpty Then Return

            Dim progress As Single = Math.Max(0.0F, Math.Min(1.0F, _selectionMotionProgress))
            Dim rect As New SKRect(fromRect.Left + (toRect.Left - fromRect.Left) * progress,
                                   fromRect.Top + (toRect.Top - fromRect.Top) * progress,
                                   fromRect.Right + (toRect.Right - fromRect.Right) * progress,
                                   fromRect.Bottom + (toRect.Bottom - fromRect.Bottom) * progress)
            rect = PixelSnap.SnapRect(rect, dpi)

            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(TreeGridTokens.RowSelectedAlpha)},
                  stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, dpi), .Color = accent.WithAlpha(150)}
                canvas.DrawRoundRect(rect, TreeGridTokens.RowRadiusDip * dpi, TreeGridTokens.RowRadiusDip * dpi, fill)
                canvas.DrawRoundRect(rect, TreeGridTokens.RowRadiusDip * dpi, TreeGridTokens.RowRadiusDip * dpi, stroke)
            End Using

            Dim marker As SKRect = If(isRtl,
                                      New SKRect(rect.Right - 4.0F * dpi, rect.Top + 7.0F * dpi, rect.Right - 2.0F * dpi, rect.Bottom - 7.0F * dpi),
                                      New SKRect(rect.Left + 2.0F * dpi, rect.Top + 7.0F * dpi, rect.Left + 4.0F * dpi, rect.Bottom - 7.0F * dpi))
            Using markerPaint As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(225)}
                canvas.DrawRoundRect(marker, 2.0F * dpi, 2.0F * dpi, markerPaint)
            End Using
        End Sub

        Private Sub DrawTreeDepthGuide(canvas As SKCanvas,
                                       labelRect As SKRect,
                                       depth As Integer,
                                       dpi As Single,
                                       accent As SKColor,
                                       isRtl As Boolean)
            If depth <= 0 Then Return
            Using guide As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, dpi), .Color = accent.WithAlpha(34)}
                For level As Integer = 0 To depth - 1
                    Dim x As Single = If(isRtl,
                                         labelRect.Right - TreeGridTokens.CellPaddingDip * dpi - CSng(level) * TreeGridTokens.TreeIndentDip * dpi,
                                         labelRect.Left + TreeGridTokens.CellPaddingDip * dpi + CSng(level) * TreeGridTokens.TreeIndentDip * dpi)
                    canvas.DrawLine(x, labelRect.Top + 7.0F * dpi, x, labelRect.Bottom - 7.0F * dpi, guide)
                Next
            End Using
        End Sub

        Private Sub DrawValuePresentation(canvas As SKCanvas,
                                          ctx As MASThemeContext,
                                          valueRect As SKRect,
                                          valueText As String,
                                          dpi As Single,
                                          accent As SKColor,
                                          isRtl As Boolean)
            Dim trimmed As String = If(valueText, String.Empty).Trim()
            If IsStatusLikeValue(trimmed) Then
                Dim width As Single = Math.Min(valueRect.Width - 8.0F * dpi, Math.Max(44.0F * dpi, CSng(trimmed.Length) * 7.0F * dpi + 18.0F * dpi))
                Dim pill As SKRect = If(isRtl,
                                        New SKRect(valueRect.Right - TreeGridTokens.CellPaddingDip * dpi - width, valueRect.MidY - 10.0F * dpi, valueRect.Right - TreeGridTokens.CellPaddingDip * dpi, valueRect.MidY + 10.0F * dpi),
                                        New SKRect(valueRect.Left + TreeGridTokens.CellPaddingDip * dpi, valueRect.MidY - 10.0F * dpi, valueRect.Left + TreeGridTokens.CellPaddingDip * dpi + width, valueRect.MidY + 10.0F * dpi))
                Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = accent.WithAlpha(32)}
                    canvas.DrawRoundRect(pill, 10.0F * dpi, 10.0F * dpi, fill)
                End Using
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, trimmed, pill, dpi, MASTypography.MASTextStyle.Micro, MASTreeGridPolicy.ResolvePrimaryTextColor(ctx), TypographyTextPrimitives.TextAlign.Center, False)
            Else
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, trimmed, InsetHorizontal(valueRect, TreeGridTokens.CellPaddingDip * dpi), dpi, MASTypography.MASTextStyle.Body, MASTreeGridPolicy.ResolveMutedTextColor(ctx), If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)
            End If
        End Sub

        Private Shared Function IsStatusLikeValue(value As String) As Boolean
            If String.IsNullOrWhiteSpace(value) Then Return False
            Dim lower As String = value.Trim().ToLowerInvariant()
            Return lower = "ready" OrElse lower = "pass" OrElse lower = "passed" OrElse lower = "active" OrElse lower = "done" OrElse lower = "draft" OrElse lower = "review" OrElse lower = "blocked" OrElse lower = "risk" OrElse lower = "ok"
        End Function

        Private Sub DrawExpander(canvas As SKCanvas,
                                 rect As SKRect,
                                 dpi As Single,
                                 accent As SKColor,
                                 expanded As Boolean,
                                 isRtl As Boolean)
            Using path As New SKPath()
                If expanded Then
                    path.MoveTo(rect.Left + rect.Width * 0.22F, rect.Top + rect.Height * 0.38F)
                    path.LineTo(rect.Right - rect.Width * 0.22F, rect.Top + rect.Height * 0.38F)
                    path.LineTo(rect.MidX, rect.Bottom - rect.Height * 0.22F)
                ElseIf isRtl Then
                    path.MoveTo(rect.Right - rect.Width * 0.25F, rect.Top + rect.Height * 0.2F)
                    path.LineTo(rect.Left + rect.Width * 0.25F, rect.MidY)
                    path.LineTo(rect.Right - rect.Width * 0.25F, rect.Bottom - rect.Height * 0.2F)
                Else
                    path.MoveTo(rect.Left + rect.Width * 0.25F, rect.Top + rect.Height * 0.2F)
                    path.LineTo(rect.Right - rect.Width * 0.25F, rect.MidY)
                    path.LineTo(rect.Left + rect.Width * 0.25F, rect.Bottom - rect.Height * 0.2F)
                End If
                path.Close()
                Using fill As New SKPaint()
                    fill.IsAntialias = True
                    fill.Style = SKPaintStyle.Fill
                    fill.Color = accent.WithAlpha(190)
                    canvas.DrawPath(path, fill)
                End Using
            End Using
        End Sub

        Private Sub DrawFooter(canvas As SKCanvas,
                               ctx As MASThemeContext,
                               content As SKRect,
                               plan As MASTreeGridLayoutPlan,
                               isRtl As Boolean)
            Dim dpi As Single = plan.Dpi
            Dim footer As New SKRect(content.Left, content.Bottom - plan.FooterHeightPx, content.Right, content.Bottom)
            Dim text As String = If(_selectedRowKey.Length = 0, "No row selected", "Selected: " & _selectedRowKey)
            If IsEditingRow Then
                Dim target As String = If(_editingColumnKey.Length = 0, "label", _editingColumnKey)
                text = "Editing " & target & ": " & _editingRowKey
            End If
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, text, footer, dpi, MASTypography.MASTextStyle.Micro, MASTreeGridPolicy.ResolveMutedTextColor(ctx), If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)
        End Sub

#End Region

    End Class

End Namespace
