Imports System.Drawing.Drawing2D

Imports Stax.AppFramework

Namespace UI
    Public Class StatusControl
        Inherits UserControl

        Public Items As New ArrayList
        Private Panel As New StatusPanel(Me)

        Public Sub New()
            AutoScroll = True
            BackColor = Color.White
            Panel.BackColor = Color.White
            Controls.Add(Panel)
        End Sub

        Protected Overrides ReadOnly Property CreateParams() As CreateParams
            Get
                Const WS_EX_CLIENTEDGE As Integer = &H200&
                Dim ret As CreateParams = MyBase.CreateParams
                ret.ExStyle = ret.ExStyle Or WS_EX_CLIENTEDGE
                Return ret
            End Get
        End Property

        Public Sub AddSpace()
            Dim si As New SpaceItem
            si.List = Items
            si.StatusPanel = Panel
            Items.Add(si)
        End Sub

        Public Sub AddSection(ByVal header As String, ByVal text As String)
            AddSection(header, text, Panel.ForeColor)
        End Sub

        Public Sub AddSection(ByVal header As String, ByVal text As String, ByVal color As Color)
            Dim h As New TextItem(color)
            h.StatusPanel = Panel
            h.List = Items
            h.Font = New Font(h.Font, FontStyle.Bold)
            h.Text = header
            Items.Add(h)

            Dim li As New LineItem
            li.List = Items
            li.StatusPanel = Panel
            Items.Add(li)

            Dim t As New TextItem(color)
            t.List = Items
            t.StatusPanel = Panel
            t.Text = text
            Items.Add(t)

            Dim si As New SpaceItem
            si.List = Items
            si.StatusPanel = Panel
            Items.Add(si)

            Panel.Height = GetPanelHeight()
        End Sub

        Public Function GetPanelHeight() As Integer
            Dim ret As Integer

            For Each i As Item In Items
                ret += i.Height
            Next

            Return ret
        End Function

        Public Sub AddIconTitle(ByVal text As String, ByVal i As Icon)
            Dim h As New IconTitleItem(Panel.ForeColor)
            h.StatusPanel = Panel
            h.List = Items
            h.Font = New Font(h.Font.FontFamily, 16)
            h.Text = text
            h.Icon = i
            Items.Add(h)

            Dim si As New SpaceItem
            si.List = Items
            si.StatusPanel = Panel
            Items.Add(si)

            Panel.Height = GetPanelHeight()
        End Sub

        Private Sub SetSize()
            If ClientSize.Width <> Panel.Width Then
                Panel.Width = ClientSize.Width
                Panel.Height = GetPanelHeight()
            End If
        End Sub

        Protected Overrides Sub OnResize(ByVal e As EventArgs)
            SetSize()
            MyBase.OnResize(e)
        End Sub

        Public MustInherit Class Item
            Public Offset As Integer = 10
            Public List As IList

            Private StatusPanelValue As StatusPanel

            Public Property StatusPanel() As StatusPanel
                Get
                    Return StatusPanelValue
                End Get
                Set(ByVal Value As StatusPanel)
                    StatusPanelValue = Value
                    OnStatusPanelChanged(StatusPanelValue)
                End Set
            End Property

            Protected Overridable Sub OnStatusPanelChanged(ByVal sp As StatusPanel)
            End Sub

            Public Function GetTop() As Integer
                Dim ret As Integer

                For Each i As Item In List
                    If Not i Is Me Then
                        ret += i.Height
                    Else
                        Return ret
                    End If
                Next

                Return ret
            End Function

            Public MustOverride Sub Draw(ByVal g As Graphics)
            Public MustOverride ReadOnly Property Height() As Integer
        End Class

        Public Class LineItem
            Inherits Item

            Public Overrides Sub Draw(ByVal g As Graphics)
                Dim h As Integer = Height
                Dim sp As StatusPanel = StatusPanel
                Dim rect As New Rectangle(0, GetTop() + 1, sp.Width, 1)

                Dim b As New LinearGradientBrush(rect, Color.DarkGray, _
                    Color.White, LinearGradientMode.Horizontal)

                g.FillRectangle(b, rect)
                b.Dispose()
            End Sub

            Public Overrides ReadOnly Property Height() As Integer
                Get
                    Return 3
                End Get
            End Property
        End Class

        Public Class TextItem
            Inherits Item

            Public TextColor As Color 'prop

            Public Sub New(ByVal textColor As Color)
                Me.TextColor = textColor
            End Sub

            Private SizeValue As SizeF

            Public ReadOnly Property Size() As SizeF
                Get
                    Return SizeValue
                End Get
            End Property

            Private TextValue As String

            Public Property Text() As String
                Get
                    Return TextValue
                End Get
                Set(ByVal Value As String)
                    TextValue = Value
                    SetSize()
                End Set
            End Property

            Private FontValue As Font

            Public Property Font() As Font
                Get
                    If FontValue Is Nothing Then
                        FontValue = New Font(StatusPanel.Font, FontStyle.Regular)
                    End If

                    Return FontValue
                End Get
                Set(ByVal Value As Font)
                    FontValue = Value
                End Set
            End Property

            Public Overrides Sub Draw(ByVal g As Graphics)
                If Text Is Nothing OrElse Text = "" Then
                    Exit Sub
                End If

                Dim sp As StatusPanel = StatusPanel
                Dim brush As New SolidBrush(TextColor)

                g.DrawString(Text, Font, brush, New RectangleF( _
                    Offset, GetTop(), Size.Width, Size.Height))

                brush.Dispose()
            End Sub

            Public Overrides ReadOnly Property Height() As Integer
                Get
                    Return Convert.ToInt32(Size.Height)
                End Get
            End Property

            Protected Overrides Sub OnStatusPanelChanged(ByVal sp As StatusPanel)
                MyBase.OnStatusPanelChanged(sp)
                AddHandler StatusPanel.SizeChanged, AddressOf SizeChanged
            End Sub

            Private Sub SizeChanged(ByVal sender As Object, ByVal e As EventArgs)
                SetSize()
            End Sub

            Private Sub SetSize()
                Dim g As Graphics = StatusPanel.CreateGraphics
                SizeValue = g.MeasureString(Text, Font, StatusPanel.Width - Offset)
                g.Dispose()
            End Sub
        End Class

        Public Class SpaceItem
            Inherits Item

            Private HeightValue As Integer = 10

            Public Overrides Sub Draw(ByVal g As Graphics)
            End Sub

            Public Overrides ReadOnly Property Height() As Integer
                Get
                    Return HeightValue
                End Get
            End Property
        End Class

        Public Class IconTitleItem
            Inherits TextItem

            Public Icon As Icon
            Private HeightValue As Integer = 42

            Public Sub New(ByVal textColor As Color)
                MyBase.New(textColor)
            End Sub

            Public Overrides Sub Draw(ByVal g As Graphics)
                Dim top As Integer = GetTop()

                If Text = "" Then
                    Exit Sub
                End If

                Dim sp As StatusPanel = StatusPanel
                Dim size As SizeF = g.MeasureString(Text, Font)
                Dim rect As New Rectangle(0, top, sp.Width, HeightValue)

                Dim b As New LinearGradientBrush(rect, Appearance.GradientColorDark, _
                    Color.White, LinearGradientMode.Horizontal)

                g.FillRectangle(b, rect)
                b.Dispose()

                If Not Icon Is Nothing Then
                    Offset = Icon.Width + 10
                    g.DrawIcon(Icon, 5, (HeightValue - Icon.Height) \ 2)
                End If

                Dim blackBrush As New SolidBrush(Color.Black)

                g.DrawString(Text, Font, blackBrush, Offset, _
                    top + (HeightValue - Font.Height) \ 2)

                blackBrush.Dispose()
            End Sub

            Public Overrides ReadOnly Property Height() As Integer
                Get
                    Return HeightValue
                End Get
            End Property
        End Class

        Public Class StatusPanel
            Inherits Panel

            Private StatusControl As StatusControl

            Public Sub New(ByVal st As StatusControl)
                StatusControl = st

                SetStyle(ControlStyles.UserPaint, True)
                SetStyle(ControlStyles.AllPaintingInWmPaint, True)
                SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
            End Sub

            Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
                MyBase.OnPaint(e)
                Dim g As Graphics = e.Graphics
                g.Clear(BackColor)

                For Each i As Item In StatusControl.Items
                    i.Draw(g)
                Next
            End Sub
        End Class
    End Class
End Namespace