Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Windows.Forms.Design
Imports System.Drawing.Drawing2D
<Designer(GetType(StatusListDesigner))> _
Public Class StatusList
#Region " Declarations "
Private _Items As New StatusCollection(Me) ' The StatusItem Collection
Private highlightedItem As StatusItem ' The currently selected item in the designer
Private _FailedImage As Image ' the pending image
Private _CompleteImage As Image ' the complete image
Private _imageSize As Size = New Size(12, 12) ' the image size
Const _pad As Int16 = 3 ' the padding between the outer bounds and the image/text
Private Indent As Int16 = 30
Private _ShowTitle As Boolean = True
Private _LineColor As Color = Color.Green
#End Region
#Region " Properties "
<Category("Appearance")> _
Public Property LineColor() As Color
Get
Return _LineColor
End Get
Set(ByVal value As Color)
_LineColor = value
Me.DrawItems()
End Set
End Property
<Category("Appearance")> _
Public Property ShowTitle() As Boolean
Get
Return _ShowTitle
End Get
Set(ByVal value As Boolean)
_ShowTitle = value
Me.DrawItems()
End Set
End Property
<Category("Custom Properties"), Browsable(False), Description("The padding between the outer bounds and the image/text")> _
Public ReadOnly Property Pad() As Int16
Get
Return _pad
End Get
End Property
<Category("Custom Properties"), Description("The default image size")> _
Public Property ImageSize() As Size
Get
Return _imageSize
End Get
Set(ByVal value As Size)
If value.Width < 12 Or value.Height < 12 Then
MsgBox("Minimum size is '12, 12'")
Exit Property
End If
_imageSize = value
Me.DrawItems()
End Set
End Property
Public Overrides Property Font() As System.Drawing.Font
Get
Return MyBase.Font
End Get
Set(ByVal value As System.Drawing.Font)
MyBase.Font = value
Me.DrawItems()
End Set
End Property
<Category("Custom Properties"), Description("The image used for pending items")> _
Public Property FailedImage() As Image
Get
Return _FailedImage
End Get
Set(ByVal value As Image)
_FailedImage = value
Me.DrawItems()
End Set
End Property
<Category("Custom Properties"), Description("The image used for completed items")> _
Public Property CompleteImage() As Image
Get
Return _completeImage
End Get
Set(ByVal value As Image)
_completeImage = value
Me.DrawItems()
End Set
End Property
<Browsable(True), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Category("Data"), Description("Returns a collection of all the status items")> _
Public Property Items() As StatusCollection
Get
Return _Items
End Get
Set(ByVal value As StatusCollection)
_Items = value
Me.DrawItems()
End Set
End Property
#End Region
#Region " Methods "
Friend Sub DrawItems()
' ----------------------------
' This methods calculates the layout of all the status items, designating them certain bounds, to stop overflow
' ----------------------------
Dim item As StatusItem ' The current item
Dim y As Int16 = 0 ' Y-Axis position of the current item
Dim itemSize As Size ' The size of the current item
Dim g As Graphics = Me.CreateGraphics
If Not Me.ShowTitle Then
y = 0
Else
y = g.MeasureString(Me.Text, New Font(Me.Font, FontStyle.Bold)).Height + Pad * 5
End If
Try
For Each item In Items
' Measure the string size
itemSize = New Size(g.MeasureString(item.Text, New Font(Me.Font, FontStyle.Bold)).Width - 4, g.MeasureString(item.Text, New Font(Me.Font, FontStyle.Bold)).Height)
' Check if the image height is larger than the current height
If ImageSize.Height > itemSize.Height Then
' If it is, resize the control to accommodate it
itemSize.Height = ImageSize.Height
End If
' Set the bounds of the control to the width of the image, text and associated padding for nicer viewing
'item.Bounds = New Rectangle(Pad, y, ImageSize.Width + (Pad * 3) + itemSize.Width + (Pad * 2), (itemSize.Height + Pad * 2))
item.Bounds = New Rectangle(Indent, y, itemSize.Width + Pad * 2, itemSize.Height + Pad * 2)
If item.Text = "" Then
item.Bounds.Width = 10
End If
' Set the Y-Axis position of the next item
y = item.Bounds.Bottom + 2
Next
Catch ex As Exception
End Try
g.Dispose()
'Mark the control as invalid so it gets redrawn
Invalidate()
End Sub
Public Shadows Property Text() As String
Get
Return MyBase.Text
End Get
Set(ByVal value As String)
MyBase.Text = value
Me.DrawItems()
End Set
End Property
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
' If the control is resized, re-calculate the items and make the control invalid
Me.DrawItems()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
' ----------------------------
' This method performs all the painting of the items, text and images.
' ----------------------------
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
If Me.ShowTitle Then
e.Graphics.DrawString(Me.Text, New Font(Me.Font, FontStyle.Bold), New SolidBrush(Me.ForeColor), 0, 0)
Dim y As Int16 = e.Graphics.MeasureString(Me.Text, New Font(Me.Font, FontStyle.Bold)).Height + Pad * 2
Dim lin As New LinearGradientBrush(New Point(Pad, 0), New Point(Me.Width - Pad, 0), LineColor, Color.FromArgb(0, LineColor))
e.Graphics.DrawLine(New Pen(lin), Pad, y, Me.Width - Pad, y)
End If
' ----------------------------------------------
' This methods needs to be cleaned up... Please don't judge just yet!
' ----------------------------------------------
Dim item As StatusItem ' The current item
Dim b As Brush = Nothing ' The current brush
Dim wrct As Rectangle ' The current item bounds
Dim yOffSet As Int16 = 0 ' The offSet of each item on the Y-Axis
For Each item In Items
'Create brush from button colour
If Not (b Is Nothing) Then b.Dispose()
b = New SolidBrush(Color.FromArgb(180, Color.SteelBlue))
'Fill rectangle with this colour
wrct = item.Bounds
If item.Text = "" And Me.DesignMode Then
Dim p As New Pen(Color.Black)
p.DashStyle = DashStyle.Dot
e.Graphics.DrawRectangle(p, wrct)
End If
Select Case item.Status
Case StatusItem.CurrentStatus.Complete
e.Graphics.DrawImage(Me.CompleteImage, New Rectangle(0, wrct.Top, 24, 24))
Case StatusItem.CurrentStatus.Failed
e.Graphics.DrawImage(Me.FailedImage, New Rectangle(0, wrct.Top, 24, 24))
Case StatusItem.CurrentStatus.Pending
e.Graphics.DrawString(item.Text, Me.Font, New SolidBrush(Me.ForeColor), wrct.Left + Pad, wrct.Top + Pad)
Case StatusItem.CurrentStatus.Running
Dim wid, range As Double
range = item.Maximum - item.Minimum
wid = (item.Maximum - (item.Maximum - item.Value)) / range
wrct.Inflate(-1, 0)
e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(255, 227, 247, 255)), wrct.Left, wrct.Top, CInt(wrct.Width * wid), wrct.Height)
e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(255, 185, 233, 252)), wrct.Left, wrct.Bottom - CInt(wrct.Height * 0.55), CInt(wrct.Width * wid), wrct.Height - CInt(wrct.Height * 0.55) + 1)
wrct.Inflate(1, 0)
e.Graphics.DrawLine(New Pen(Color.FromArgb(255, 147, 201, 227)), wrct.Left + 1, wrct.Top, wrct.Right - 1, wrct.Top)
e.Graphics.DrawLine(New Pen(Color.FromArgb(255, 147, 201, 227)), wrct.Left + 1, wrct.Bottom, wrct.Right - 1, wrct.Bottom)
e.Graphics.DrawLine(New Pen(Color.FromArgb(255, 136, 203, 235)), wrct.Left, wrct.Top + 1, wrct.Left, wrct.Bottom - 1)
e.Graphics.DrawLine(New Pen(Color.FromArgb(255, 105, 187, 227)), wrct.Left, wrct.Bottom - CInt(wrct.Height * 0.55), wrct.Left, wrct.Bottom - 1)
e.Graphics.DrawLine(New Pen(Color.FromArgb(255, 136, 203, 235)), wrct.Right, wrct.Top + 1, wrct.Right, wrct.Bottom - 1)
e.Graphics.DrawLine(New Pen(Color.FromArgb(255, 105, 187, 227)), wrct.Right, wrct.Bottom - CInt(wrct.Height * 0.55), wrct.Right, wrct.Bottom - 1)
Dim h As Int16 = e.Graphics.MeasureString(wid * 100 & "%", New Font(Me.Font.Name, 7, FontStyle.Regular)).Height
e.Graphics.DrawString(wid * 100 & "%", New Font(Me.Font.Name, 7, FontStyle.Regular), New SolidBrush(Me.ForeColor), 0, wrct.Bottom - CInt(wrct.Height / 2) - h / 2)
End Select
e.Graphics.DrawString(item.Text, Me.Font, New SolidBrush(Color.FromArgb(220, Me.ForeColor)), wrct.Left + Pad, wrct.Top + Pad)
If highlightedItem Is item Then
wrct.Inflate(-1, -1)
e.Graphics.DrawRectangle(New Pen(b, 2), wrct)
End If
Next
End Sub
Friend Sub OnSelectionChanged()
' ----------------------------
' This methods is called by the StatusLabel control when a selection has changed in design mode
' ----------------------------
Dim item As StatusItem
Dim newHighlightedItem As StatusItem = Nothing
Dim s As ISelectionService = DirectCast(GetService(GetType(ISelectionService)), ISelectionService)
'See if the primary selection is one of our buttons
For Each item In Items
If s.PrimarySelection Is item Then
newHighlightedItem = item
Exit For
End If
Next
'Apply if necessary
If Not newHighlightedItem Is highlightedItem Then
highlightedItem = newHighlightedItem
Invalidate()
End If
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
' ----------------------------
' This methods checks the MouseDown event within the control and determines whether an item was selected, and if so, which one
' ----------------------------
Dim wrct As Rectangle ' The current item bounds
Dim s As ISelectionService ' Selection service
Dim a As ArrayList ' array of selected items
Dim item As StatusItem ' the current item
If DesignMode Then
For Each item In Items
' Get the current item bounds
wrct = item.Bounds
If wrct.Contains(e.X, e.Y) Then
' if the current item has mouse down focus, add it to the array and exit the loop
s = DirectCast(GetService(GetType(ISelectionService)), ISelectionService)
a = New ArrayList()
a.Add(item)
s.SetSelectedComponents(a)
Exit For
End If
Next
End If
' Perform any additional tasks here
MyBase.OnMouseDown(e)
End Sub
#End Region
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
' Initialisations go here...
SetStyle(ControlStyles.AllPaintingInWmPaint, True)
SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
SetStyle(ControlStyles.ResizeRedraw, True)
SetStyle(ControlStyles.SupportsTransparentBackColor, True)
' IMPORTANT!!! This declares the New Collection
_Items = New StatusCollection(Me)
' Set the default size of the control
Me.Size = New Size(200, 100)
End Sub
End Class