Imports System.ComponentModel
Imports System.Drawing.Drawing2D

Friend Class CollapsablePanel
    Inherits System.Windows.Forms.UserControl

    Private _controlVisibilityStates As New Hashtable
    Private _headerText As String = String.Empty
    Private _height As Integer
    Private _isExpanded As Boolean = True

    Public Event BeginCollapse As EventHandler
    Public Event BeginExpand As EventHandler
    Public Event Collapsed As EventHandler
    Public Event Expanded As EventHandler

    Public Sub New()

        MyBase.New()
        MyBase.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        MyBase.SetStyle(ControlStyles.ContainerControl, True)
        MyBase.SetStyle(ControlStyles.DoubleBuffer, True)
        MyBase.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        MyBase.SetStyle(ControlStyles.ResizeRedraw, True)
        MyBase.SetStyle(ControlStyles.Selectable, True)
        MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
        MyBase.SetStyle(ControlStyles.UserPaint, True)
        MyBase.BackColor = Color.Transparent
        MyBase.DoubleBuffered = True

    End Sub

    Public Property HeaderText() As String

        Get
            Return _headerText
        End Get

        Set(ByVal value As String)
            _headerText = value
            MyBase.Invalidate()
        End Set

    End Property

    Public Shadows Property Height() As Integer

        Get
            Return _height
        End Get

        Set(ByVal value As Integer)
            If Me.IsExpanded Then
                MyBase.Height = value
            Else
                _height = value
            End If
            MyBase.Invalidate()
        End Set

    End Property

    Public Property IsExpanded() As Boolean

        Get
            Return _isExpanded
        End Get

        Set(ByVal value As Boolean)
            ChangeHeight(value)
            MyBase.Invalidate()
        End Set

    End Property

    Private Sub ChangeHeight(ByVal expand As Boolean)

        If expand Then
            Me.OnBeginExpand(New EventArgs)
            MyBase.Height = _height
            If _isDisableOnCollapse Then ShowChildControls()
            _isExpanded = True
            Me.OnExpanded(New EventArgs)
        Else
            Me.OnBeginCollapse(New EventArgs)
            _height = MyBase.Height
            MyBase.Height = 40
            If _isDisableOnCollapse Then HideChildControls()
            _isExpanded = False
            Me.OnCollapsed(New EventArgs)
        End If

    End Sub

    Public Sub Collapse()

        If _isExpanded Then ChangeHeight(False)

    End Sub

    Public Sub Expand()

        If Not _isExpanded Then ChangeHeight(True)

    End Sub

    Private Sub HideChildControls()

        With _controlVisibilityStates
            .Clear()
            For Each ctrl As Control In Me.Controls
                If Not .ContainsKey(ctrl.Handle.ToString) Then .Add(ctrl.Handle.ToString, ctrl.Visible)
                ctrl.Visible = False
            Next ctrl
        End With

    End Sub

    Private Sub ShowChildControls()

        With _controlVisibilityStates
            For Each ctrl As Control In MyBase.Controls
                ctrl.Visible = CBool(IIf(.ContainsKey(ctrl.Handle.ToString), .Item(ctrl.Handle.ToString), True))
            Next ctrl
        End With

    End Sub

    Protected Overrides Sub OnMouseClick(ByVal e As System.Windows.Forms.MouseEventArgs)

        If e.Button = System.Windows.Forms.MouseButtons.Left AndAlso _isEnableCollapsingExpanding Then
            If e.Y > 38 Or e.Y < 16 Then Exit Sub
            ChangeHeight(Not _isExpanded)
            Me.Invalidate()
        End If
        MyBase.OnMouseDown(e)

    End Sub

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

    End Sub

    Protected Overridable Sub OnBeginCollapse(ByVal e As EventArgs)

        RaiseEvent BeginCollapse(Me, e)

    End Sub

    Protected Overridable Sub OnBeginExpand(ByVal e As EventArgs)

        RaiseEvent BeginExpand(Me, e)

    End Sub

    Protected Overridable Sub OnCollapsed(ByVal e As EventArgs)

        RaiseEvent Collapsed(Me, e)

    End Sub

    Protected Overridable Sub OnExpanded(ByVal e As EventArgs)

        RaiseEvent Expanded(Me, e)

    End Sub

End Class
