Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.ComponentModel.Design.Serialization
Imports System.Reflection
Imports System.Globalization
Imports System
Imports System.Windows.Forms
Imports System.Collections

Imports Stax.UI

Namespace ComponentModel
    <AttributeUsage(AttributeTargets.All)> _
    Public Class NameAttribute
        Inherits Attribute

        Public Sub New(ByVal name As String)
            ValueValue = name
        End Sub

        Private ValueValue As String

        Public ReadOnly Property Value() As String
            Get
                Return ValueValue
            End Get
        End Property

        Public Shared Function GetEnumName(Of T)(ByVal value As T) As String
            For Each i As FieldInfo In value.GetType.GetFields
                If i.GetValue(value).Equals(value) Then
                    Dim attributes As Object() = i.GetCustomAttributes(False)

                    For Each i2 As Object In attributes
                        If i2.GetType Is GetType(NameAttribute) Then
                            Return DirectCast(i2, NameAttribute).Value
                        End If
                    Next

                    Return i.Name
                End If
            Next

            Throw New Exception
        End Function
    End Class

    <AttributeUsage(AttributeTargets.Property)> _
    Public Class OrderAttribute
        Inherits Attribute

        Public Sub New(ByVal order As Integer)
            Value = order
        End Sub

        Private ValueValue As Integer

        Public Property Value() As Integer
            Get
                Return ValueValue
            End Get
            Set(ByVal Value As Integer)
                ValueValue = Value
            End Set
        End Property
    End Class

    Public Class PropertyConverter
        Inherits TypeConverter

        Public Overloads Overrides Function GetPropertiesSupported(ByVal context As ITypeDescriptorContext) As Boolean
            Return True
        End Function

        Public Overloads Overrides Function GetProperties(ByVal context As ITypeDescriptorContext, ByVal value As Object, ByVal attributes As Attribute()) As System.ComponentModel.PropertyDescriptorCollection
            Dim c As PropertyDescriptorCollection = TypeDescriptor.GetProperties(value, attributes)
            Dim s As New Sorter

            For Each i As PropertyDescriptor In c
                Dim oa As OrderAttribute = CType(i.Attributes(GetType(OrderAttribute)), OrderAttribute)

                If oa Is Nothing Then
                    s.Add(999, i)
                Else
                    s.Add(oa.Value, i)
                End If

                Dim na As NameAttribute = CType(i.Attributes(GetType(NameAttribute)), NameAttribute)

                If Not na Is Nothing Then
                    Dim fi2 As FieldInfo = GetType(MemberDescriptor).GetField("displayName", BindingFlags.NonPublic Or BindingFlags.Instance)
                    fi2.SetValue(i, na.Value)
                End If
            Next

            Dim l As New List(Of String)

            For Each i As PropertyDescriptor In s.GetSortedList
                l.Add(i.Name)
            Next

            Return c.Sort(l.ToArray)
        End Function
    End Class
End Namespace