Imports System.Drawing
Imports System.Globalization
Imports System.Windows.Forms
Imports DevExpress.Utils
Imports DevExpress.XtraGrid.Columns
Imports DevExpress.XtraGrid.Views.Grid
Imports DevExpress.XtraTreeList

Public Class GridBuilder
    Private ReadOnly EvenRowBackColor = Color.Gainsboro

    Public ReadOnly Property Views As New List(Of GridView)

    Public Sub New(ParamArray GridViews As GridView())
        Views.AddRange(GridViews)
    End Sub

    Public Sub New(GridViews As List(Of GridView))
        Views.AddRange(GridViews)
    End Sub

    Public Sub SetDefaults(ParamArray pGridViews As GridView())
        For Each oView In pGridViews
            WithDefaults(oView)
        Next
    End Sub

    Public Sub SetDefaults(ParamArray pTreeLists As TreeList())
        For Each oView In pTreeLists
            WithDefaults(oView)
        Next
    End Sub

    Public Sub SetReadOnlyOptions(ParamArray pGridViews As GridView())
        For Each oView In pGridViews
            WithReadOnlyOptions(oView)
        Next
    End Sub

    Public Sub SetReadOnlyOptions(ParamArray pTreeLists As TreeList())
        For Each oView In pTreeLists
            WithReadOnlyOptions(oView)
        Next
    End Sub

    Public Sub SetFontSizeDelta(pFontSizeDelta As Integer, ParamArray pGridViews As GridView())
        For Each oView In pGridViews
            WithFontSizeDelta(oView, pFontSizeDelta)
        Next
    End Sub

    Public Sub SetFontSizeDelta(pFontSizeDelta As Integer, ParamArray pTreeLists As TreeList())
        For Each oView In pTreeLists
            WithFontSizeDelta(oView, pFontSizeDelta)
        Next
    End Sub

    Public Sub SetClipboardHandler(ParamArray pGridViews As GridView())
        For Each oView In pGridViews
            WithClipboardHandler(oView)
        Next
    End Sub

    Public Sub SetClipboardHandler(ParamArray pTreeLists As TreeList())
        For Each oView In pTreeLists
            WithClipboardHandler(oView)
        Next
    End Sub

    ''' <summary>
    ''' Applies a proper datetime format string to all columns of the view. 
    ''' </summary>
    ''' <remarks>The view's columns need to be loaded for this to work!</remarks>
    Public Sub SetDateTimeColumns(pView As GridView)
        If pView.Columns Is Nothing Then
            Exit Sub
        End If

        Dim oDateColumns = pView.Columns.AsEnumerable.
            Where(Function(column As GridColumn) column.ColumnType = GetType(Date)).
            ToList()

        For Each oDateCol In oDateColumns
            oDateCol.DisplayFormat.FormatType = FormatType.Custom
            oDateCol.DisplayFormat.FormatString = "g"
            oDateCol.DisplayFormat.Format = DateTimeFormatInfo.CurrentInfo
        Next
    End Sub

    ''' <summary>
    ''' Applies common properties to all GridViews
    ''' </summary>
    Public Function WithDefaults() As GridBuilder
        For Each oView In Views
            WithDefaults(oView)
        Next

        Return Me
    End Function

    ''' <summary>
    ''' Applies common properties to the supplied GridView
    ''' </summary>
    Public Function WithDefaults(GridView As GridView) As GridBuilder
        GridView.OptionsView.EnableAppearanceEvenRow = True
        GridView.OptionsView.ShowAutoFilterRow = True
        GridView.Appearance.EvenRow.BackColor = EvenRowBackColor
        GridView.Appearance.EvenRow.Options.UseBackColor = True

        Return Me
    End Function

    ''' <summary>
    ''' Applies common properties to the supplied TreeList
    ''' </summary>
    Public Function WithDefaults(TreeList As TreeList) As GridBuilder
        TreeList.OptionsView.EnableAppearanceEvenRow = True
        TreeList.OptionsView.ShowAutoFilterRow = True
        TreeList.Appearance.EvenRow.BackColor = EvenRowBackColor
        TreeList.Appearance.EvenRow.Options.UseBackColor = True

        Return Me
    End Function

    ''' <summary>
    ''' Applies read-only properties to all GridViews
    ''' </summary>
    Public Function WithReadOnlyOptions() As GridBuilder
        For Each oView In Views
            WithReadOnlyOptions(oView)
        Next

        Return Me
    End Function

    ''' <summary>
    ''' Applies read-only properties to the supplied GridView
    ''' </summary>
    Public Function WithReadOnlyOptions(GridView As GridView) As GridBuilder
        GridView.OptionsBehavior.Editable = False
        GridView.OptionsBehavior.ReadOnly = True

        Return Me
    End Function

    ''' <summary>
    ''' Applies read-only properties to the supplied TreeList
    ''' </summary>
    Public Function WithReadOnlyOptions(TreeList As TreeList) As GridBuilder
        TreeList.OptionsBehavior.Editable = False
        TreeList.OptionsBehavior.ReadOnly = True

        Return Me
    End Function

    Public Function WithFontSizeDelta(pFontSizeDelta As Integer) As GridBuilder
        For Each oGridView In Views
            WithFontSizeDelta(oGridView, pFontSizeDelta)
        Next

        Return Me
    End Function

    Public Function WithFontSizeDelta(pGridView As GridView, pFontSizeDelta As Integer) As GridBuilder
        pGridView.Appearance.Row.FontSizeDelta = pFontSizeDelta
        pGridView.Appearance.GroupRow.FontSizeDelta = pFontSizeDelta
        pGridView.Appearance.GroupPanel.FontSizeDelta = pFontSizeDelta
        pGridView.Appearance.GroupFooter.FontSizeDelta = pFontSizeDelta
        pGridView.Appearance.FilterPanel.FontSizeDelta = pFontSizeDelta
        pGridView.Appearance.HeaderPanel.FontSizeDelta = pFontSizeDelta

        Return Me
    End Function

    Public Function WithFontSizeDelta(pTreeList As TreeList, pFontSizeDelta As Integer) As GridBuilder
        pTreeList.Appearance.Row.FontSizeDelta = pFontSizeDelta
        pTreeList.Appearance.GroupFooter.FontSizeDelta = pFontSizeDelta
        pTreeList.Appearance.FilterPanel.FontSizeDelta = pFontSizeDelta
        pTreeList.Appearance.HeaderPanel.FontSizeDelta = pFontSizeDelta

        Return Me
    End Function

    Public Function WithClipboardHandler() As GridBuilder
        For Each oGridView In Views
            WithClipboardHandler(oGridView)
        Next

        Return Me
    End Function

    Public Function WithClipboardHandler(View As GridView) As GridBuilder
        AddHandler View.KeyDown, AddressOf GridView_ClipboardHandler

        Return Me
    End Function

    Public Function WithClipboardHandler(View As TreeList) As GridBuilder
        AddHandler View.KeyDown, AddressOf TreeList_ClipboardHandler

        Return Me
    End Function

    Private Sub TreeList_ClipboardHandler(sender As Object, e As KeyEventArgs)
        Dim view As TreeList = CType(sender, TreeList)
        Dim oNode = view.FocusedNode
        If e.Control AndAlso e.KeyCode = Keys.C Then
            If view.GetRowCellValue(oNode, view.FocusedColumn) IsNot Nothing AndAlso view.GetRowCellValue(oNode, view.FocusedColumn).ToString() <> [String].Empty Then
                Clipboard.SetText(view.GetRowCellValue(oNode, view.FocusedColumn).ToString())
            End If
            e.Handled = True
        End If
    End Sub

    Private Sub GridView_ClipboardHandler(sender As Object, e As KeyEventArgs)
        Dim view As GridView = CType(sender, GridView)
        If e.Control AndAlso e.KeyCode = Keys.C Then
            If view.GetRowCellValue(view.FocusedRowHandle, view.FocusedColumn) IsNot Nothing AndAlso view.GetRowCellValue(view.FocusedRowHandle, view.FocusedColumn).ToString() <> [String].Empty Then
                Clipboard.SetText(view.GetRowCellValue(view.FocusedRowHandle, view.FocusedColumn).ToString())
            End If
            e.Handled = True
        End If
    End Sub

End Class
