Namespace Controls.Form
Public Class MakeXmlForm
Implements IMakeForm
'<layout>
' <linegroup height="x">
' <container title="Title" width="x" type="expander,groupbox,border,clear">
' <lines width="x">
' csvDef
Private _csv As New MakeCsvForm
Private _oneStar As New GridLength(1, GridUnitType.Star)
Private _oneAuto As New GridLength(1, GridUnitType.Auto)
Private _form As DataForm
Public Property ButtonMaker As MakeButton Implements IMakeForm.ButtonMaker
Private _doc As New Xml.XmlDocument
Private _id As Integer = 1
Public Property Doc As Xml.XmlDocument
Get
Return _doc
End Get
Set(value As Xml.XmlDocument)
If value Is Nothing Then Throw New NullReferenceException("value must be a valid xml document")
_doc = value
End Set
End Property
Public Property LayoutXML As String
Get
Return _doc.OuterXml
End Get
Set(value As String)
_doc.LoadXml(value)
End Set
End Property
Public Function Create(base As DataForm) As Dictionary(Of String, Control) Implements IMakeForm.Create
Dim root = _doc.DocumentElement
_csv.Form = base
_csv.ButtonMaker = ButtonMaker
_form = base
Dim bag = base.Container
bag.Children.Clear()
bag.RowDefinitions.Clear()
bag.ColumnDefinitions.Clear()
Dim list As New Dictionary(Of String, Control)(StringComparer.CurrentCultureIgnoreCase)
AddColumn(bag, _oneStar)
bag.Name = "XML" & _id
_id += 1
If base.Title IsNot Nothing Then
Dim r = AddRow(bag, _oneAuto)
base.Title.VerticalAlignment = VerticalAlignment.Bottom
Windows.Controls.Grid.SetRow(base.Title, r)
Windows.Controls.Grid.SetColumn(base.Title, 0)
bag.Children.Add(base.Title)
If base.LineSpacing > 0 Then
AddRow(bag, New GridLength(base.LineSpacing, GridUnitType.Pixel))
End If
End If
For Each child As Xml.XmlNode In root.ChildNodes
Select Case LCase(child.Name)
Case "linegroup"
Dim size = GetSize(child, "height", "A")
Dim r = AddRow(bag, size)
Call LineGroup(bag, child, list, r, 0)
Case "container"
Dim r = AddRow(bag, _oneAuto)
Call Me.Container(bag, child, list, r, 0)
Case "lines"
Dim r = AddRow(bag, _oneAuto)
Call Lines(bag, child, list, r, 0)
End Select
Next
base.Container.RowDefinitions.Add(New RowDefinition With {.Height = New GridLength(base.LineSpacing)})
Return list
End Function
Private Sub LineGroup(container As Grid, root As Xml.XmlElement, list As Dictionary(Of String, Control), row As Integer, col As Integer)
Dim bag As New Grid
bag.Name = "LineGroup" & _id
_id += 1
Grid.SetRow(bag, row)
Grid.SetColumn(bag, col)
AddRow(bag, _oneAuto)
container.Children.Add(bag)
For Each child As Xml.XmlElement In root.ChildNodes
Select Case LCase(child.Name)
Case "container"
Dim size = GetSize(child, "width", "1*")
Dim c = AddColumn(bag, size)
Call Me.Container(bag, child, list, 0, c)
Case "lines"
Dim size = GetSize(child, "width", "1*")
Dim c = AddColumn(bag, size)
Call Lines(bag, child, list, 0, c)
End Select
Next
End Sub
Private Sub Container(container As Grid, root As Xml.XmlElement, list As Dictionary(Of String, Control), row As Integer, col As Integer)
Dim bag As New Grid
Dim factType = GetAtr(root, "type")
Select Case LCase(factType)
Case "expander"
Dim fact = New ExpanderColumn
fact.Title = GetAtr(root, "title")
Dim control = CType(fact.CreateControl(_form), Expander)
Dim isOpen = (GetAtr(root, "isopen") <> String.Empty)
control.IsExpanded = isOpen
control.HorizontalAlignment = HorizontalAlignment.Stretch
control.Width = Double.NaN
control.Height = Double.NaN
control.Name = "Container" & _id
_id += 1
Grid.SetRow(control, row)
Grid.SetColumn(control, col)
container.Children.Add(control)
control.Content = bag
Case "groupbox"
Dim fact = New GroupBoxColumn
fact.Title = GetAtr(root, "title")
Dim control = CType(fact.CreateControl(_form), GroupBox)
control.HorizontalAlignment = HorizontalAlignment.Stretch
control.Width = Double.NaN
control.Height = Double.NaN
control.Name = "Container" & _id
_id += 1
Grid.SetRow(control, row)
Grid.SetColumn(control, col)
container.Children.Add(control)
control.Content = bag
Case "border"
Dim fact = New BorderColumn
Dim control = CType(fact.CreateControl(_form), Border)
control.HorizontalAlignment = HorizontalAlignment.Stretch
control.Name = "Container" & _id
control.Width = Double.NaN
control.Height = Double.NaN
_id += 1
Grid.SetRow(control, row)
Grid.SetColumn(control, col)
container.Children.Add(control)
control.Child = bag
Case "clear"
Grid.SetRow(bag, row)
Grid.SetColumn(bag, col)
container.Children.Add(bag)
End Select
AddColumn(bag, _oneStar)
bag.HorizontalAlignment = HorizontalAlignment.Stretch
bag.Name = "ContainerBag" & _id
_id += 1
For Each child As Xml.XmlElement In root.ChildNodes
Select Case LCase(child.Name)
Case "lines"
Dim r = AddRow(bag, _oneAuto)
Call Lines(bag, child, list, r, 0)
End Select
Next
End Sub
Private Sub Lines(container As Grid, root As Xml.XmlElement, list As Dictionary(Of String, Control), row As Integer, col As Integer)
Dim bag As New Grid
bag.Name = "Lines" & _id
_id += 1
Grid.SetRow(bag, row)
Grid.SetColumn(bag, col)
container.Children.Add(bag)
Dim lines As New List(Of String)
lines.AddRange(Split(root.InnerText, vbCrLf))
_csv.MakeForm(_form, bag, False, lines, list)
End Sub
Private Function GetAtr(root As Xml.XmlElement, attributeName As String) As String
Dim at = root.Attributes(attributeName)
If at Is Nothing Then Return String.Empty
Return at.Value
End Function
Private Function GetSize(root As Xml.XmlElement, attributeName As String, defaultValue As String) As GridLength
Dim value = GetAtr(root, attributeName)
Dim w As Double = 1.0#
Dim u As GridUnitType = GridUnitType.Pixel
Dim v As String = Trim("" & value)
If v = String.Empty Then v = defaultValue
Select Case LCase(Right(v, 1))
Case "a"
u = GridUnitType.Auto
Case "*"
u = GridUnitType.Star
w = Val(Left(v, v.Length - 1))
Case Else
u = GridUnitType.Pixel
w = Val(v)
End Select
Return New GridLength(w, u)
End Function
Private Function AddColumn(container As Grid, width As GridLength) As Integer
Dim cd As New ColumnDefinition With {.Width = width}
container.ColumnDefinitions.Add(cd)
Return container.ColumnDefinitions.Count - 1
End Function
Private Function AddRow(container As Grid, height As GridLength) As Integer
Dim rd As New RowDefinition With {.Height = height}
container.RowDefinitions.Add(rd)
Return container.RowDefinitions.Count - 1
End Function
End Class
End Namespace