Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Globalization

Public Class EgtDictionary
   Inherits ResourceDictionary

End Class

#Region "<!--ButtonBase-->"

Public Class ButtonExtensions

   Public Shared ReadOnly CornerRadiusProperty As DependencyProperty = DependencyProperty.RegisterAttached("CornerRadius", GetType(Double), GetType(ButtonExtensions), New PropertyMetadata(0.0))

   Public Shared Function GetCornerRadius(element As UIElement) As Double
      Return CDbl(element.GetValue(CornerRadiusProperty))
   End Function

   Public Shared Sub SetCornerRadius(element As UIElement, value As Double)
      element.SetValue(CornerRadiusProperty, value)
   End Sub

End Class

#End Region

Namespace ControlExtensions

#Region "<!--CheckBoxBase-->"

   'Converter che permette di ridimensionare la spunta
   Public Class CheckboxConverter
      Implements IMultiValueConverter

      Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IMultiValueConverter.Convert
         If values.Length <> 2 Then
            Throw New ArgumentException("There should be three values.")
         End If

         If String.IsNullOrEmpty(values(0).ToString) Then
            values(0) = "0"
         End If

         If String.IsNullOrEmpty(values(1).ToString()) Then
            values(2) = "0"
         End If

         Dim x As Double
         If Not Double.TryParse(values(0).ToString(), x) Then
            Throw New ArgumentException("values[0] must parse to double")
         End If

         Dim y As Double
         If Not Double.TryParse(values(1).ToString(), y) Then
            Throw New ArgumentException("values[0] must parse to double")
         End If

         Return (x / y) - 1

      End Function

      Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As Globalization.CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
         Return New Object() {Binding.DoNothing}
      End Function
   End Class

#End Region

#Region "<!--GroupBoxBase-->"

   Public Class GroupBoxExtensions

      Public Shared ReadOnly CornerRadiusProperty As DependencyProperty = DependencyProperty.RegisterAttached("CornerRadius", GetType(Double), GetType(GroupBoxExtensions), New PropertyMetadata(0.0))

      Public Shared Function GetCornerRadius(element As UIElement) As Double
         Return CDbl(element.GetValue(CornerRadiusProperty))
      End Function

      Public Shared Sub SetCornerRadius(element As UIElement, value As Double)
         element.SetValue(CornerRadiusProperty, value)
      End Sub

      Public Shared ReadOnly FirstColumnProperty As DependencyProperty = DependencyProperty.RegisterAttached("FirstColumn", GetType(Double), GetType(GroupBoxExtensions), New PropertyMetadata(0.0))

      Public Shared Function GetFirstColumn(element As UIElement) As Double
         Return CDbl(element.GetValue(CornerRadiusProperty))
      End Function

      Public Shared Sub SetFirstColumn(element As UIElement, value As Double)
         element.SetValue(CornerRadiusProperty, value)
      End Sub

   End Class

   'Converter che permette di massimizzare l'area interna del GroupBox

   Public Class GroupBoxConverter
      Implements IMultiValueConverter

      Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IMultiValueConverter.Convert

         ' Parameter Validation
         Dim doubleType As Type = GetType(Double)

         If values Is Nothing OrElse values.Length <> 3 OrElse values(0) Is Nothing OrElse values(1) Is Nothing OrElse values(2) Is Nothing Then
            Return DependencyProperty.UnsetValue
         End If

         ' Conversion
         Dim dBorderThickness As Double = 0
         Dim dCornerRadius As Double = 0
         Dim sItems(3) As String
         Dim Val1 As Double
         Dim Val2 As Double

         sItems = values(0).ToString.Split(",".ToCharArray)
         Double.TryParse(sItems(2), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture.NumberFormat, Val1)
         Double.TryParse(sItems(3), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture.NumberFormat, Val2)
         dBorderThickness = Math.Max(Val1, Val2)
         sItems = values(1).ToString.Split(",".ToCharArray)
         Double.TryParse(sItems(2), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture.NumberFormat, Val1)
         Double.TryParse(sItems(3), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture.NumberFormat, Val2)
         dCornerRadius = Math.Max(Val1, Val2)

         ' Width of the line to the left of the header 
         ' to be used to set the width of the first column of the Grid
         Dim GridLengthConverter As New GridLengthConverter
         'Dim lineWidth As Double = CDbl(GridLengthConverter.ConvertToString(values(2)))
         Dim lineWidth As Double
         If GridLengthConverter.ConvertToString(values(2)).Contains("*") Then
            lineWidth = 1
         Else
            lineWidth = CDbl(GridLengthConverter.ConvertToString(values(2)))
         End If

         ' Calcolo il Margin sottraendo alla larghezza della colonna (6) il massimo tra BorderThickness e CornerRadius
         Dim dRightMargin = -6 + Math.Max(dBorderThickness, dCornerRadius)
         Dim dLeftMargin = -lineWidth + Math.Max(dBorderThickness, dCornerRadius) - Math.Sqrt(2) / 2 * (dCornerRadius - dBorderThickness - 2)
         ' Calcolo il minimo tra il valore ottenuto e 0 perchè BorderThickness non può spingere il Margin oltre lo 0
         dRightMargin = Math.Min(0, dRightMargin)
         dLeftMargin = Math.Min(0, dLeftMargin)
         ' Creo Thickness con il valore ottenuto da ritornare
         Dim ReturnValue As Thickness
         ReturnValue.Top = 0
         ReturnValue.Bottom = dRightMargin
         ReturnValue.Left = dLeftMargin
         ReturnValue.Right = dRightMargin
         Return ReturnValue

      End Function

      Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As Globalization.CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
         Return New Object() {Binding.DoNothing}
      End Function
   End Class

   ''' <summary> 
   ''' BorderGapMaskConverter class
   ''' </summary>
   Public Class BorderGapMaskConverter
      Implements IMultiValueConverter

      ''' <summary> 
      ''' Convert a value. 
      ''' </summary>
      ''' <param name="values">values as produced by source binding</param>
      ''' <param name="targetType">target type</param>
      ''' <param name="parameter">converter parameter</param>
      ''' <param name="culture">culture information</param>
      ''' <returns> 
      ''' Converted value.
      ''' Visual Brush that is used as the opacity mask for the Border 
      ''' in the style for GroupBox. 
      ''' </returns>
      Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IMultiValueConverter.Convert

         ' Parameter Validation
         Dim doubleType As Type = GetType(Double)

         If values Is Nothing OrElse values.Length <> 4 OrElse values(0) Is Nothing OrElse values(1) Is Nothing OrElse values(2) Is Nothing OrElse values(3) Is Nothing OrElse Not doubleType.IsAssignableFrom(values(0).[GetType]()) OrElse Not doubleType.IsAssignableFrom(values(1).[GetType]()) OrElse Not doubleType.IsAssignableFrom(values(2).[GetType]()) Then
            Return DependencyProperty.UnsetValue
         End If

         ' Conversion
         Dim headerWidth As Double = CDbl(values(0))
         Dim borderWidth As Double = CDbl(values(1))
         Dim borderHeight As Double = CDbl(values(2))

         ' Width of the line to the left of the header 
         ' to be used to set the width of the first column of the Grid
         Dim GridLengthConverter As New GridLengthConverter
         'Dim lineWidth As Double = CDbl(GridLengthConverter.ConvertToString(values(3)))
         Dim lineWidth As Double
         If GridLengthConverter.ConvertToString(values(3)).Contains("*") Then
            lineWidth = 1
         Else
            lineWidth = CDbl(GridLengthConverter.ConvertToString(values(3)))
         End If

         ' Doesn't make sense to have a Grid
         ' with 0 as width or height 
         If borderWidth = 0 OrElse borderHeight = 0 Then
            Return Nothing
         End If

         Dim grid__1 As New Grid()
         grid__1.Width = borderWidth
         grid__1.Height = borderHeight
         Dim colDef1 As New ColumnDefinition()
         Dim colDef2 As New ColumnDefinition()
         Dim colDef3 As New ColumnDefinition()
         colDef1.Width = New GridLength(lineWidth)
         colDef2.Width = New GridLength(headerWidth)
         colDef3.Width = New GridLength(1, GridUnitType.Star)
         grid__1.ColumnDefinitions.Add(colDef1)
         grid__1.ColumnDefinitions.Add(colDef2)
         grid__1.ColumnDefinitions.Add(colDef3)
         Dim rowDef1 As New RowDefinition()
         Dim rowDef2 As New RowDefinition()
         rowDef1.Height = New GridLength(borderHeight / 2)
         rowDef2.Height = New GridLength(1, GridUnitType.Star)
         grid__1.RowDefinitions.Add(rowDef1)
         grid__1.RowDefinitions.Add(rowDef2)

         Dim rectColumn1 As New Rectangle()
         Dim rectColumn2 As New Rectangle()
         Dim rectColumn3 As New Rectangle()
         rectColumn1.Fill = Brushes.Black
         rectColumn2.Fill = Brushes.Black
         rectColumn3.Fill = Brushes.Black

         Grid.SetRowSpan(rectColumn1, 2)
         Grid.SetRow(rectColumn1, 0)
         Grid.SetColumn(rectColumn1, 0)

         Grid.SetRow(rectColumn2, 1)
         Grid.SetColumn(rectColumn2, 1)

         Grid.SetRowSpan(rectColumn3, 2)
         Grid.SetRow(rectColumn3, 0)
         Grid.SetColumn(rectColumn3, 2)

         grid__1.Children.Add(rectColumn1)
         grid__1.Children.Add(rectColumn2)
         grid__1.Children.Add(rectColumn3)

         Return (New VisualBrush(grid__1))

      End Function

      ''' <summary> 
      ''' Not Supported
      ''' </summary>
      ''' <param name="value">value, as produced by target</param>
      ''' <param name="targetTypes">target types</param>
      ''' <param name="parameter">converter parameter</param>
      ''' <param name="culture">culture information</param>
      ''' <returns>Nothing</returns> 
      Public Function ConvertBack(value As Object, targetTypes As Type(), parameter As Object, culture As Globalization.CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
         Return New Object() {Binding.DoNothing}
      End Function



   End Class

#End Region

#Region "<!--HierarchicalTreeView-->"

   Public Class CathegoryItem
      Inherits TreeViewItemBase

      Private m_sTitle As String
      Private m_sPictureString As String
      Private m_Items As ObservableCollection(Of CustomItem)

      Sub New(Title As String)
         Me.Title = Title
         Me.Items = New ObservableCollection(Of CustomItem)
      End Sub

      Public Property Title As String
         Get
            Return m_sTitle
         End Get
         Set(value As String)
            m_sTitle = value
         End Set
      End Property

      Public ReadOnly Property PictureString As String
         Get
            Return "/Resources/ToolsTreeviewImages/Folder.png"
         End Get
      End Property

      Public Property Items As ObservableCollection(Of CustomItem)
         Get
            Return m_Items
         End Get
         Set(value As ObservableCollection(Of CustomItem))
            m_Items = value
         End Set
      End Property

   End Class

   Public Class CustomItem
      Inherits TreeViewItemBase

      Private m_sTitle As String

      Sub New(Title As String)
         Me.Title = Title
      End Sub

      Public Property Title As String
         Get
            Return m_sTitle
         End Get
         Set(value As String)
            m_sTitle = value
         End Set
      End Property

   End Class

   Public Class TreeViewItemBase
      Implements INotifyPropertyChanged

      Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

      Private m_isSelected As Boolean
      Public Property IsSelected As Boolean
         Get
            Return m_isSelected
         End Get
         Set(value As Boolean)
            If (value <> m_isSelected) Then
               m_isSelected = value
               NotifyPropertyChanged("IsSelected")
            End If
         End Set
      End Property

      Private m_isExpanded As Boolean
      Public Property IsExpanded As Boolean
         Get
            Return m_isExpanded
         End Get
         Set(value As Boolean)
            If (value <> m_isExpanded) Then
               m_isExpanded = value
               NotifyPropertyChanged("IsExpanded")
            End If
         End Set
      End Property



      Public Sub NotifyPropertyChanged(propName As String)
         RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
      End Sub

   End Class

#End Region

   Public Class ToggleButtonExtensions

      Public Shared ReadOnly CornerRadiusProperty As DependencyProperty = DependencyProperty.RegisterAttached("CornerRadius", GetType(Double), GetType(ToggleButtonExtensions), New PropertyMetadata(0.0))

      Public Shared Function GetCornerRadius(element As UIElement) As Double
         Return CDbl(element.GetValue(CornerRadiusProperty))
      End Function

      Public Shared Sub SetCornerRadius(element As UIElement, value As Double)
         element.SetValue(CornerRadiusProperty, value)
      End Sub

   End Class

End Namespace
