#Region " Enumarations "
''' <summary>
''' Represents AnalogClock.MarkerStyle enumeration for AnalogClock.Marker object.
''' </summary>
Public Enum MarkerStyle As Integer
Regular = 0
Ring = 1
Triangle = 2
Custom = 3
End Enum
#End Region
''' <summary>
''' Represents the AnalogClock.Marker object for AnalogClock.Clock.
''' </summary>
<DebuggerNonUserCode()> _
<System.ComponentModel.TypeConverterAttribute(GetType(MarkerConverter))> _
Public Class Marker
Inherits Element
Friend Event CustomElementRequest As EventHandler(Of AnalogClock.CustomElementEventArgs)
Private _tMatrix As Drawing2D.Matrix
Private _basePath As Drawing2D.GraphicsPath
Private WithEvents _paintAttributes As PaintAttributes
Private _smoothMode As SmoothMode
Private _width As Single
Private _relativeLength As Single
Private _style As MarkerStyle
Private _disposedValue As Boolean
#Region " Properties "
''' <summary>
''' Gets or sets the paint attributes of the element.
''' </summary>
<System.ComponentModel.Category("Appearance"), _
System.ComponentModel.Description("Indicates the paint attributes for the element.")> _
Public Property [PaintAttributes]() As PaintAttributes
Get
Return Me._paintAttributes
End Get
Set(ByVal value As PaintAttributes)
If Not Me._paintAttributes.Equals(value) Then
Me._paintAttributes = value
Me.OnPropertyChanged(New System.ComponentModel.PropertyChangedEventArgs("PaintAttributes"))
End If
End Set
End Property
''' <summary>
''' Gets or sets the smoothing mode of the element.
''' </summary>
<System.ComponentModel.DefaultValue(GetType(SmoothMode), "AntiAlias"), System.ComponentModel.Category("Appearance"), _
System.ComponentModel.Description("Indicates the smoothing mode of the element.")> _
Public Property [SmoothMode]() As SmoothMode
Get
Return Me._smoothMode
End Get
Set(ByVal [smoothMode] As SmoothMode)
If Not [Enum].IsDefined(GetType(SmoothMode), [smoothMode]) Then
Throw New System.ComponentModel.InvalidEnumArgumentException( _
"smoothMode", [smoothMode], GetType(SmoothMode))
Else
If Me._smoothMode <> [smoothMode] Then
Me._smoothMode = [smoothMode]
Me.OnPropertyChanged(New System.ComponentModel.PropertyChangedEventArgs("SmoothingMode"))
End If
End If
End Set
End Property
''' <summary>
''' Gets or sets the element's relative-length that is directly proportional to its radius.
''' </summary>
<System.ComponentModel.Category("Layout"), System.ComponentModel.TypeConverterAttribute(GetType(PercentageConverter)), _
System.ComponentModel.Description("Indicates the element's relative length that is directly proportional to its radius.")> _
Public Property RelativeLength() As Single
Get
Return Me._relativeLength
End Get
Set(ByVal relativeLength As Single)
If relativeLength < 0.0F OrElse relativeLength > 1.0F Then
Throw New ArgumentOutOfRangeException( _
"relativeLength", relativeLength, "The value should be in the range 0% to 100%.")
Else
If Me._relativeLength <> relativeLength Then
Me._relativeLength = relativeLength
Me.UpdateBasePath()
Me.OnPropertyChanged(New System.ComponentModel.PropertyChangedEventArgs("RelativeLength"))
End If
End If
End Set
End Property
''' <summary>
''' Gets or sets the element's width.
''' </summary>
<System.ComponentModel.DefaultValue(1.0F), System.ComponentModel.Category("Layout"), _
System.ComponentModel.Description("Indicates the element's width.")> _
Public Property Width() As Single
Get
Return Me._width
End Get
Set(ByVal width As Single)
If width < 1.0F Then
Throw New ArgumentOutOfRangeException( _
"width", width, "The value should be in the range 1 to " & Single.MaxValue)
Else
If Me._width <> width Then
Me._width = width
Me.UpdateBasePath()
Me.OnPropertyChanged(New System.ComponentModel.PropertyChangedEventArgs("Width"))
End If
End If
End Set
End Property
''' <summary>
''' Gets or sets the element's style. If the style is 'Custom',
''' than related 'AnalogClock.CustomElementRequest' event should be handled.
''' </summary>
<System.ComponentModel.DefaultValue(GetType(MarkerStyle), "Regular"), _
System.ComponentModel.Category("Appearance"), _
System.ComponentModel.Description("Indicates the element's style. If the style is 'Custom', " _
& "than related 'CustomElementRequest' event should be handled.")> _
Public Property Style() As MarkerStyle
Get
Return Me._style
End Get
Set(ByVal style As MarkerStyle)
If Not [Enum].IsDefined(GetType(MarkerStyle), style) Then
Throw New System.ComponentModel.InvalidEnumArgumentException("style", style, GetType(MarkerStyle))
Else
If Me._style <> style Then
Me._style = style
Me.UpdateBasePath()
Me.OnPropertyChanged(New System.ComponentModel.PropertyChangedEventArgs("Style"))
End If
End If
End Set
End Property
''' <summary>
''' Gets the element's length.
''' </summary>
<System.ComponentModel.Browsable(False)> _
Public ReadOnly Property Length() As Single
Get
Return Me.Radius * Me._relativeLength
End Get
End Property
''' <summary>
''' Gets the element's graphics path.
''' </summary>
<System.ComponentModel.Browsable(False)> _
Public ReadOnly Property Path() As Drawing2D.GraphicsPath
Get
Return Me._basePath
End Get
End Property
#End Region
#Region " Methods "
''' <param name="name">The name of the element.</param>
''' <param name="angle">The angle of the element in degrees.</param>
''' <param name="clockRadius">The cluck's radius for the element.</param>
''' <param name="col">The color of the element.</param>
''' <param name="width">The width of the element.</param>
''' <param name="relativeLength">The relative length of the
''' element that is directly proportional to its radius.</param>
''' <param name="relativeRadius">The relative radius of the
''' element that is directly proportional to the clock's radius.</param>
Sub New(ByVal name As String, _
ByVal clockRadius As Single, _
ByVal relativeRadius As Single, _
ByVal angle As Single, _
ByVal col As Color, _
ByVal width As Single, _
ByVal relativeLength As Single)
Me.New(name, clockRadius, relativeRadius, _
angle, col, width, relativeLength, True)
End Sub
''' <param name="name">The name of the element.</param>
''' <param name="angle">The angle of the element in degrees.</param>
''' <param name="clockRadius">The cluck's radius for the element.</param>
''' <param name="col">The color of the element.</param>
''' <param name="width">The width of the element.</param>
''' <param name="relativeLength">The relative length of the
''' element that is directly proportional to its radius.</param>
''' <param name="relativeRadius">The relative radius of the
''' element that is directly proportional to the clock's radius.</param>
''' <param name="visible">The visibility of the element.</param>
Sub New(ByVal name As String, _
ByVal clockRadius As Single, _
ByVal relativeRadius As Single, _
ByVal angle As Single, _
ByVal col As Color, _
ByVal width As Single, _
ByVal relativeLength As Single, _
ByVal visible As Boolean)
Me.New(name, angle, col, MarkerStyle.Regular, _
visible, clockRadius, _
width, relativeLength, relativeRadius, _
New PaintAttributes(AnalogClock.PaintObject.Brush), _
SmoothMode.AntiAlias, _
Nothing)
End Sub
''' <param name="name">The name of the element.</param>
''' <param name="angle">The angle of the element in degrees.</param>
''' <param name="col">The color of the element.</param>
''' <param name="style">The style of the element.</param>
''' <param name="visible">The visibility of the element.</param>
''' <param name="clockRadius">The cluck's radius for the element.</param>
''' <param name="width">The width of the element.</param>
''' <param name="relativeLength">The relative length of the
''' element that is directly proportional to its radius.</param>
''' <param name="relativeRadius">The relative radius of the
''' element that is directly proportional to the clock's radius.</param>
''' <param name="paintAttributes">The paint attributes of the element.</param>
''' <param name="smoothMode">The smoothing mode of the element.</param>
Sub New(ByVal name As String, _
ByVal angle As Single, _
ByVal col As Color, _
ByVal style As MarkerStyle, _
ByVal visible As Boolean, _
ByVal clockRadius As Single, _
ByVal width As Single, _
ByVal relativeLength As Single, _
ByVal relativeRadius As Single, _
ByVal [paintAttributes] As PaintAttributes, _
ByVal [smoothMode] As SmoothMode, _
ByVal tag As Object)
MyBase.New(name, angle, col, visible, relativeRadius, clockRadius, tag)
Me._style = style
Me._width = width
Me._relativeLength = relativeLength
Me._paintAttributes = [paintAttributes]
Me._smoothMode = [smoothMode]
Me._tMatrix = New Drawing2D.Matrix
Me._basePath = New Drawing2D.GraphicsPath
End Sub
''' <summary>
''' Paints the clock's element.
''' </summary>
''' <param name="e">A System.Windows.Forms.PaintEventArgs
''' object that will paint the element.</param>
Friend Overrides Sub Paint(ByVal e As System.Windows.Forms.PaintEventArgs)
If Me.Visible Then
Dim arg As New AnalogClock.PaintEventArgs(e.Graphics, e.ClipRectangle)
Me.OnElementPainting(arg)
arg.Graphics.SmoothingMode = CType(Me._smoothMode, Drawing2D.SmoothingMode)
If Me._width > 1 Then
If Me._paintAttributes.PaintObject = AnalogClock.PaintObject.Brush Then
If arg.Brush IsNot Nothing Then
arg.Graphics.FillPath(arg.Brush, Me._basePath)
Else
Dim br As SolidBrush = New SolidBrush(Me.Color)
arg.Graphics.FillPath(br, Me._basePath)
br.Dispose()
End If
Else
If arg.Brush IsNot Nothing Then
Dim p As New Pen(arg.Brush, Me._paintAttributes.PenWidth)
arg.Graphics.DrawPath(p, Me._basePath)
p.Dispose()
Else
Dim p As New Pen(Me.Color, Me._paintAttributes.PenWidth)
arg.Graphics.DrawPath(p, Me._basePath)
p.Dispose()
End If
End If
Else
Dim p As New Pen(Me.Color)
arg.Graphics.DrawPath(p, Me._basePath)
p.Dispose()
End If
arg.Dispose()
Me.OnElementPainted(e)
End If
End Sub
''' <summary>
''' Updates the element's base-path.
''' </summary>
Protected Friend Sub UpdateBasePath()
If Me._style = MarkerStyle.Regular Then
Me.ToRegular()
ElseIf Me._style = MarkerStyle.Ring Then
Me.ToRing()
ElseIf Me._style = MarkerStyle.Triangle Then
Me.ToTriangle()
ElseIf Me._style = MarkerStyle.Custom Then
Me._basePath.Reset()
Dim e As New CustomElementEventArgs
Me.OnCustomElementRequest(e)
If e.CustomPath IsNot Nothing Then
Me._basePath.AddPath(e.CustomPath, False)
e.Dispose()
End If
End If
Me.RotateMarker()
End Sub
''' <summary>
''' Rotate the element's base-paths.
''' </summary>
Private Sub RotateMarker()
If Me._basePath.PointCount > 0 Then
Me._tMatrix.Reset()
Me._tMatrix.RotateAt(90 - Me.Angle, Me.PivotalPoint)
Me._basePath.Transform(Me._tMatrix)
End If
End Sub
''' <summary>
''' Releases the unmanaged resources used by the
''' AnalogClock.Element and optionally releases the managed resources.
''' </summary>
''' <param name="disposing">True to release both base and derived class
''' resources; false to release only base class resources.</param>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If Not Me._disposedValue Then
If disposing Then
Me._tMatrix.Dispose()
Me._basePath.Dispose()
End If
End If
Me._disposedValue = True
MyBase.Dispose(disposing)
End Sub
#End Region
#Region " Events "
Private Sub _paintAttributes_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
Handles _paintAttributes.PropertyChanged
Me.OnPropertyChanged(e)
End Sub
#End Region
#Region " OnEvent "
''' <summary>
''' Raises the AnalogClock.Element.PropertyChanged event.
''' </summary>
''' <param name="e">A System.ComponentModel.PropertyChangedEventArgs
''' that contains the event data.</param>
Protected Overrides Sub OnPropertyChanged(ByVal e As System.ComponentModel.PropertyChangedEventArgs)
If e.PropertyName = "RelativeRadius" OrElse e.PropertyName = "ClockRadius" Then
Me.UpdateBasePath()
End If
MyBase.OnPropertyChanged(e)
End Sub
''' <summary>
''' Raises the AnalogClock.Marker.CustomElementRequest event.
''' </summary>
''' <param name="e">An AnalogClock.CustomElementEventArgs
''' that contains the event data.</param>
Protected Overridable Sub OnCustomElementRequest(ByVal e As AnalogClock.CustomElementEventArgs)
RaiseEvent CustomElementRequest(Me, e)
End Sub
#End Region
#Region " Styles "
''' <summary>
''' Sets the element's base-path to regular style (at 12 o'clock position).
''' </summary>
Private Sub ToRegular()
'Reset the base-path
Me._basePath.Reset()
If Me._width <> 0.0F AndAlso Me.Length <> 0.0F Then
Dim pOuter, pInner As PointF
pOuter = New PointF(Me.PivotalPoint.X, Me.ClockRadius - Me.Radius)
pInner = New PointF(Me.PivotalPoint.X, Me.ClockRadius - (Me.Radius - Me.Length))
Me._basePath.AddLine(pOuter, pInner)
'If the hand's width is biger than 1, than widen the path
If Me._width > 1 Then
Dim p As New Pen(Color.Transparent, Me._width)
Me._basePath.Widen(p)
p.Dispose()
End If
Me._basePath.CloseAllFigures()
End If
End Sub
''' <summary>
''' Sets the element's base-path to triangle style (at 12 o'clock position).
''' </summary>
Private Sub ToTriangle()
'Reset the base-path
Me._basePath.Reset()
If Me._width <> 0.0F AndAlso Me.Length <> 0.0F Then
Dim pOuter, pInner As PointF
Dim points(2) As PointF
pOuter = New PointF(Me.PivotalPoint.X, Me.ClockRadius - Me.Radius)
pInner = New PointF(Me.PivotalPoint.X, Me.ClockRadius - (Me.Radius - Me.Length))
points(0) = New PointF(pOuter.X - Me._width / 2, pOuter.Y)
points(1) = New PointF(pOuter.X + Me._width / 2, pOuter.Y)
points(2) = pInner
Me._basePath.AddLines(points)
Me._basePath.CloseAllFigures()
End If
End Sub
''' <summary>
''' Sets the element's base-path to pointed style (at 12 o'clock position).
''' </summary>
Private Sub ToRing()
'Reset the base-path
Me._basePath.Reset()
If Me._width <> 0.0F AndAlso Me.Length <> 0.0F Then
Dim pOuter, pInner As PointF
pOuter = New PointF(Me.PivotalPoint.X, Me.ClockRadius - Me.Radius)
pInner = New PointF(Me.PivotalPoint.X, Me.ClockRadius - (Me.Radius - Me.Length))
Dim rect As New RectangleF(pOuter.X - Me._width / 2, pOuter.Y, Me._width, Me.Length)
Me._basePath.AddEllipse(rect)
Me._basePath.CloseAllFigures()
End If
End Sub
#End Region
End Class