Imports Microsoft.VisualBasic
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Web.UI
Imports System.Web.UI.Design
Imports System.Collections.Generic

' Tag cloud ASP.NET Web server control (v1.0)
' (c) Mike Pope

Namespace MikesControls

    
'TODO: Add proper data binding.

    
Public Enum TagDisplay
        List
        Cloud
    
End Enum

    Public Enum 
TagHyperlinkData
        Name
        Value
    
End Enum

    Public Class 
TagCloud : Inherits CompositeControl

        <Browsable(
True), DefaultValue(24)> Public Property MaximumFontSize() As Integer
            Get
                If 
ViewState("tagcloudMaximumFontSize"Is Nothing Then
                    Return 
24
                
Else
                    Return CInt
(ViewState("tagcloudMaximumFontSize"))
                
End If
            End Get
            Set
(ByVal value As Integer)
                ViewState(
"tagcloudMaximumFontSize"value
            
End Set
        End Property

        
<Browsable(True), DefaultValue(10)> Public Property MinimumFontSize() As Integer
            Get
                If 
ViewState("tagcloudMinimumFontSize"Is Nothing Then
                    Return 
10
                
Else
                    Return CInt
(ViewState("tagcloudMinimumFontSize"))
                
End If
            End Get
            Set
(ByVal value As Integer)
                ViewState(
"tagcloudMinimumFontSize"value
            
End Set
        End Property

        Private 
_TagList As IEnumerable
        <Browsable(
True)> Public Property TagList() As IEnumerable
            
' The list of data to be converted to a tag cloud. The list must implement IEnumerator, and
            ' it must contain items that support two properties -- one for the tag name and one
            ' for the tag count. The names of the properties that provide this data are specified
            ' through TagNamePropertyName and TagCountPropertyName
            
Get
                Return 
_TagList
            
End Get
            Set
(ByVal value As IEnumerable)
                _TagList 
value
            
End Set
        End Property

        
<Browsable(True)> Public Property TagCSSClass() As String
            Get
                If 
ViewState("tagCloudControlTagCSSClass"Is Nothing Then
                    Return 
""
                
Else
                    Return 
ViewState("tagCloudControlTagCSSClass")
                
End If
            End Get
            Set
(ByVal value As String)
                ViewState(
"tagCloudControlTagCSSClass"value
            
End Set
        End Property

        
<Browsable(True), DefaultValue(True)> Public Property IsHyperlink() As Boolean
            Get
                If 
ViewState("tagCloudControlIsHyperlink"Is Nothing Then
                    Return True
                Else
                    Return 
CBool(ViewState("tagCloudControlIsHyperlink"))
                
End If
            End Get
            Set
(ByVal value As Boolean)
                ViewState(
"tagCloudControlIsHyperlink"value
            
End Set
        End Property

        
<Browsable(True), DefaultValue("?tag={0}")> Public Property HyperlinkFormat() As String
            Get
                If 
ViewState("tagCloudControlHyperlinkFormat"Is Nothing Then
                    Return 
"?tag={0}"
                
Else
                    Return 
ViewState("tagCloudControlHyperlinkFormat")
                
End If
            End Get
            Set
(ByVal value As String)
                ViewState(
"tagCloudControlHyperlinkFormat"value
            
End Set
        End Property

        
<Browsable(True), DefaultValue(TagHyperlinkData.Name)> Public Property HyperlinkData() As TagHyperlinkData
            
Get
                If 
ViewState("tagCloudControlHyperlinkData"Is Nothing Then
                    Return 
TagHyperlinkData.Name
                
Else
                    Return 
ViewState("tagCloudControlHyperlinkData")
                
End If
            End Get
            Set
(ByVal value As TagHyperlinkData)
                ViewState(
"tagCloudControlHyperlinkData"value
            
End Set
        End Property

        
<Browsable(True), DefaultValue(TagDisplay.Cloud)> Public Property DisplayFormat() As TagDisplay
            
Get
                If 
ViewState("tagCloudControlDisplayFormat"Is Nothing Then
                    Return 
TagDisplay.Cloud
                
Else
                    Return CType
(ViewState("tagCloudControlDisplayFormat"), TagDisplay)
                
End If
            End Get
            Set
(ByVal value As TagDisplay)
                ViewState(
"tagCloudControlDisplayFormat"value
            
End Set
        End Property

        
<Browsable(True), DefaultValue("tagName")> Public Property TagNamePropertyName() As String
            Get
                If 
ViewState("tagCloudControlTagNamePropertyName"Is Nothing Then
                    Return 
"tagName"
                
Else
                    Return 
ViewState("tagCloudControlTagNamePropertyName")
                
End If
            End Get
            Set
(ByVal value As String)
                ViewState(
"tagCloudControlTagNamePropertyName"value
            
End Set
        End Property

        
<Browsable(True), DefaultValue("tagCount")> Public Property TagCountPropertyName() As String
            Get
                If 
ViewState("tagCloudControlTagCountPropertyName"Is Nothing Then
                    Return 
"tagCount"
                
Else
                    Return 
ViewState("tagCloudControlTagCountPropertyName")
                
End If
            End Get
            Set
(ByVal value As String)
                ViewState(
"tagCloudControlTagCountPropertyName"value
            
End Set
        End Property


        Public Sub New
()
        
End Sub

        Protected Overrides Sub 
CreateChildControls()

            
If Me.TagList Is Nothing Then
                If Me
.DesignMode = True Then
                    Dim 
designTagList As New List(Of TagItem)
                    designTagList.Add(
New TagItem("tag1"10))
                    designTagList.Add(
New TagItem("tag2"5))
                    designTagList.Add(
New TagItem("tag3"15))
                    designTagList.Add(
New TagItem("tag4"20))
                    designTagList.Add(
New TagItem("tag5"5))
                    designTagList.Add(
New TagItem("tag6"15))
                    
Me.TagList designTagList
                
End If
            End If

            If Me
.TagList Is Nothing Then
                Exit Sub
                Throw New Exception
("No tag items have been specified.")
            
End If

            Me
.Controls.Clear()

            
Dim tagCount As Int16
            
Dim tagCountTotal As Integer = 0
            
Dim tagName As String
            Dim 
tagCountHi As Integer = 0
            
Dim tagCountLo As Integer = Int16.MaxValue

            
' This just gets the total tag count. First pass.
            
Dim tagListEnumerator As IEnumerator = CType(Me.TagList, IEnumerable).GetEnumerator
            
While tagListEnumerator.MoveNext()
                tagCount 
= CInt(DataBinder.GetPropertyValue(tagListEnumerator.Current(), Me.TagCountPropertyName))
                tagCountTotal +
tagCount
                
If tagCount > tagCountHi Then
                    
tagCountHi tagCount
                
End If
                If 
tagCount < tagCountLo Then
                    
tagCountLo tagCount
                
End If
            End While

            Dim 
tagCountRange As Integer = tagCountHi - tagCountLo
            
Dim tagWeight As Double
            Dim 
fontSize As Integer
            Dim 
fontSizeRange = Me.MaximumFontSize - Me.MinimumFontSize

            
' Go through the list again. For each tag, create a control (Hyperlink or Label). Set font based
            ' on weight. Weight calculates where on the scale of lowest to highest tag count a specific
            ' tag lies. This is then used to find (roughly) the corresponding position on the scale between
            ' smallest and largest font size.
            
tagListEnumerator.Reset()
            
While tagListEnumerator.MoveNext()
                tagCount 
= CInt(DataBinder.GetPropertyValue(tagListEnumerator.Current, Me.TagCountPropertyName))
                tagName 
DataBinder.GetPropertyValue(tagListEnumerator.Current, Me.TagNamePropertyName)
                tagWeight 
(tagCount - tagCountLo) / tagCountRange
                fontSize 
(CInt(tagWeight * fontSizeRange) + Me.MinimumFontSize)

                
If Me.IsHyperlink = True Then
                    Dim 
tagControl As New HyperLink

                    
' Sets the Hyperlink text to either the tag name or the tag count. (Mostly
                    ' this would be tag name.)
                    
If Me.HyperlinkData TagHyperlinkData.Name Then
                        
tagControl.NavigateUrl = String.Format(Me.HyperlinkFormat, tagName)
                    
Else
                        
tagControl.NavigateUrl = String.Format(Me.HyperlinkFormat, tagCount)
                    
End If
                    
tagControl.Text tagName
                    tagControl.CssClass 
= Me.TagCSSClass
                    tagControl.Font.Size 
= New FontUnit(fontSize.ToString())
                    
Me.Controls.Add(tagControl)
                
Else
                    Dim 
tagControl As New Label
                    tagControl.Text 
tagName
                    tagControl.CssClass 
= Me.TagCSSClass
                    tagControl.Font.Size 
= New FontUnit(fontSize.ToString())
                    
Me.Controls.Add(tagControl)
                
End If

                If Me
.DisplayFormat TagDisplay.Cloud Then
                    Me
.Controls.Add(New LiteralControl(" "))
                
ElseIf DisplayFormat TagDisplay.List Then
                    Me
.Controls.Add(New LiteralControl("<br/>"))
                
End If
            End While

        End Sub

        Public Overrides ReadOnly Property 
Controls() As System.Web.UI.ControlCollection
            
Get
                
EnsureChildControls()
                
Return MyBase.Controls
            
End Get
        End Property

        Protected Overrides Sub 
OnDataBinding(ByVal As System.EventArgs)
            EnsureChildControls()
        
End Sub

    End Class

    
' ============== TagItem class 
    
Public Class TagItem
        
Dim _tagName As String
        Dim 
_tagCount As Integer
        Public Property 
TagName() As String
            Get
                Return 
_tagName
            
End Get
            Set
(ByVal value As String)
                _tagName 
value
            
End Set
        End Property

        Public Property 
TagCount() As Integer
            Get
                Return 
_tagCount
            
End Get
            Set
(ByVal value As Integer)
                _tagCount 
value
            
End Set
        End Property

        Public Sub New
()
        
End Sub

        Public Sub New
(ByVal tagName As StringByVal tagCount As Integer)
            _tagName 
tagName
            _tagCount 
tagCount
        
End Sub
    End Class

End Namespace

Colorized by: CarlosAg.CodeColorizer