Implementing a schematic digitizing tool
DockableDigit.vb
' Copyright 2010 ESRI
' 
' All rights reserved under the copyright laws of the United States
' and applicable international laws, treaties, and conventions.
' 
' You may freely redistribute and use this sample code, with or
' without modification, provided you include the original copyright
' notice and use restrictions.
' 
' See the use restrictions.
' 

Imports System.Xml
Imports ESRI.ArcGIS.Schematic
Imports ESRI.ArcGIS.esriSystem

''' <summary>
''' Designer class of the dockable window add-in. It contains user interfaces that
''' make up the dockable window.
''' </summary>
Public Class DigitDockableWindow

  Private m_digitCommand As DigitTool

  Dim m_dom As XmlDocument = Nothing
  Dim m_loading As Boolean = True
  Dim m_clickPanel As Boolean = False
  Dim m_curfrmWidth As Long
  Friend WithEvents m_Panel1 As System.Windows.Forms.SplitterPanel
  Friend WithEvents m_Panel2 As System.Windows.Forms.SplitterPanel
  Dim m_curPanel As System.Windows.Forms.SplitterPanel
  Dim m_mandatoryColor As System.Drawing.Color = Drawing.Color.White

  Private m_schematicLayer As ISchematicLayer
  Private m_schematicFeature1 As ISchematicFeature = Nothing
  Private m_schematicFeature2 As ISchematicFeature = Nothing
  Private m_createNode As Boolean = True 'update when click on panel and on new

  'For button OK to retrieve the coordinate of the digit feature
  Private m_x As Integer
  Private m_y As Integer

  Private m_curLink As XmlElement = Nothing
  Private m_curNode As XmlElement = Nothing
  Private m_relations As XmlNodeList = Nothing
  Private m_schDataset As ISchematicDataset = Nothing
  Private m_schEltClassCont As ISchematicElementClassContainer = Nothing
  Private m_schEltClass As ISchematicElementClass = Nothing
  Private m_schematicInMemoryDiagram As ISchematicInMemoryDiagram = Nothing
  Private m_autoClear As Boolean = False
  Private m_schematicExtension As ESRI.ArcGIS.esriSystem.IExtension

  Public Sub New(ByVal hook As Object)

    ' This call is required by the Windows Form Designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Me.Hook = hook

  End Sub



  Private m_hook As Object
  ''' <summary>
  ''' Host object of the dockable window
  ''' </summary> 
  Public Property Hook() As Object
    Get
      Return m_hook
    End Get
    Set(ByVal value As Object)
      m_hook = value
    End Set
  End Property

  ''' <summary>
  ''' Implementation class of the dockable window add-in. It is responsible for
  ''' creating and disposing the user interface class for the dockable window.
  ''' </summary>
  Public Class AddinImpl
    Inherits ESRI.ArcGIS.Desktop.AddIns.DockableWindow

    Private m_windowUI As DigitDockableWindow

    Protected Overrides Function OnCreateChild() As System.IntPtr
      m_windowUI = New DigitDockableWindow(Me.Hook)

      CurrentDigitTool.CurrentTool.digitDockableWindow = m_windowUI

      If (CurrentDigitTool.CurrentTool.currentDigit IsNot Nothing) Then
        m_windowUI.m_digitCommand = CurrentDigitTool.CurrentTool.currentDigit
        m_windowUI.m_digitCommand.m_dockableDigit = m_windowUI
      Else
                ' CurrentDigitTool.CurrentTool.CurrentDigit is null when we open ArcMap, but OnCreateChild
                ' is called if the dockable window was shown during the last ArcMap session.
        Dim windowID As UID = New UIDClass
        windowID.Value = "DigitTool_DockableWindowVB"
        CurrentDigitTool.CurrentTool.currentDockableWindow = My.ArcMap.DockableWindowManager.GetDockableWindow(windowID)
      End If

      Return m_windowUI.Handle
    End Function

    Protected Overrides Sub Dispose(ByVal Param As Boolean)
      If m_windowUI IsNot Nothing Then
        m_windowUI.Dispose(Param)
      End If

      MyBase.Dispose(Param)

    End Sub

  End Class


  Public Sub Init(ByVal schematicLayer As ISchematicLayer)

    Try

      If schematicLayer Is Nothing Then
        Return
      End If

      m_schematicLayer = schematicLayer
      Dim col As XmlNode = Nothing
      Dim myString As String = Nothing

      m_schDataset = schematicLayer.SchematicDiagram.SchematicDiagramClass.SchematicDataset

      m_schEltClassCont = m_schDataset
      m_schematicInMemoryDiagram = schematicLayer.SchematicInMemoryDiagram

      m_dom = New XmlDocument

      Dim schematicDiagram As ISchematicDiagram
      schematicDiagram = m_schematicInMemoryDiagram.SchematicDiagram

      ' get the path of the xml file that contains the definitions of the digitize dockable window
      Dim path As String

      Dim schematicDiagramClass As ISchematicDiagramClass = schematicDiagram.SchematicDiagramClass
      Dim schematicAttributeContainer As ISchematicAttributeContainer = schematicDiagramClass

      Dim schematicAttribute As ISchematicAttribute
      schematicAttribute = schematicAttributeContainer.GetSchematicAttribute("DigitizePropertiesLocation", True)

      If (schematicAttribute Is Nothing) Then
        MsgBox("Need an attribute named DigitizePropertiesLocation in the corresponding DiagramTemplate attributes")
        Return
      End If

      path = schematicAttribute.GetValue(schematicDiagram)


      If IsRelative(path) Then 'Concat the workspace's path with this path
        'current workspace path
        Dim myDataset As ISchematicDataset = schematicDiagramClass.SchematicDataset
        If Not myDataset Is Nothing Then
          Dim mySchematicWorkspace As ISchematicWorkspace = myDataset.SchematicWorkspace
          If Not mySchematicWorkspace Is Nothing Then
            Dim myWorkspace As ESRI.ArcGIS.Geodatabase.IWorkspace = mySchematicWorkspace.Workspace
            If Not myWorkspace Is Nothing Then
              Dim workspacePath As String = myWorkspace.PathName
              'add "..\" to path to step back one level...
              Dim stepBack As String = "..\"
              path = stepBack + path

              path = System.IO.Path.Combine(workspacePath, path)

            End If
          End If
        End If
      End If
      'else keep the original hard path

      Dim reader As System.Xml.XmlReader = System.Xml.XmlReader.Create(path)

      m_dom.Load(reader)

      'Load Nodes
      Dim nodes As XmlNodeList = Nothing
      nodes = m_dom.SelectNodes("descendant::NodeFeature")

      cboNodeType.Items.Clear()
      Dim node As XmlElement = Nothing
      For Each node In nodes
        Me.cboNodeType.Items.Add(node.GetAttribute("FeatureClassName").ToString)
      Next

      'Load Links
      Dim links As XmlNodeList = Nothing
      links = m_dom.SelectNodes("descendant::LinkFeature")

      cboLinkType.Items.Clear()
      Dim link As XmlElement = Nothing
      For Each link In links
        Me.cboLinkType.Items.Add(link.GetAttribute("FeatureClassName").ToString)
      Next

      col = m_dom.SelectSingleNode("descendant::MandatoryColor")
      If Not col Is Nothing Then
        myString = "System.Drawing."
        myString = col.InnerText.ToString
        m_mandatoryColor = System.Drawing.Color.FromName(myString)
      End If

      col = m_dom.SelectSingleNode("descendant::FormName")
      If Not col Is Nothing Then
        myString = col.InnerText.ToString
        Me.Text = myString
      End If


      Dim rels As XmlNodeList = m_dom.SelectNodes("descendant::Relation")
      If rels.Count > 0 Then
        m_relations = rels
      End If

      col = m_dom.SelectSingleNode("descendant::AutoClearAfterCreate")
      If Not col Is Nothing Then
        If col.InnerText.ToString = "True" Then
          m_autoClear = True
        End If
      End If
    Catch ex As Exception

    End Try

    m_Panel1 = Splitter.Panel1
    m_Panel2 = Splitter.Panel2
    m_curPanel = Splitter.Panel1
    lblMode.Text = "Create Node"
    m_loading = False
    m_clickPanel = False
    m_schEltClass = Nothing

  End Sub


  Public Function ValidateFields() As Boolean
    Dim blnValidated As Boolean = True
    Dim ctrl As Windows.Forms.Control = Nothing
    Dim mctrl As Windows.Forms.MaskedTextBox = Nothing
    Dim errors As String = ""

    'check all mandatory fields
    For Each ctrl In m_curPanel.Controls
      If TypeOf ctrl Is Windows.Forms.Label Then
        'ignore labels
      Else
        If ctrl.Tag = "Mandatory" Then
          If TypeOf ctrl Is Windows.Forms.MaskedTextBox Then
            mctrl = ctrl
            If mctrl.MaskCompleted = False Then
              blnValidated = False
              If errors.Length > 0 Then
                errors = "Incomplete mandatory field"
              Else
                errors = errors & vbCrLf & "Incomplete mandatory field"
              End If
            End If
          Else
            If Not ctrl.Text.Length > 0 Then
              blnValidated = False
              If errors.Length > 0 Then
                errors = "Incomplete mandatory field"
              Else
                errors = errors & vbCrLf & "Incomplete mandatory field"
              End If
            End If
          End If
        End If

        'check masked edit controls
        If TypeOf ctrl Is Windows.Forms.MaskedTextBox Then
          mctrl = ctrl
          'if they typed something, but didn't complete it, then error
          'if they typed nothing and it is not mandatory, then it is OK
          If mctrl.Text.Length > 0 Then
            If mctrl.Modified = True Then
              If mctrl.MaskCompleted = False Then
                blnValidated = False
                If errors.Length > 0 Then
                  errors = "Invalid entry in a masked text field"
                Else
                  errors = errors & vbCrLf & "Invalid entry in a masked text field"
                End If
              End If
            End If
          End If
        End If
        'End If

        'check link connections
        If m_curPanel Is Splitter.Panel2 Then
          'make sure that the relation is correct if it exists
          Dim fields As XmlNodeList = m_curLink.SelectNodes("descendant::Field")
          Dim field As XmlElement = Nothing
          For Each field In fields
            'find the field with a type of "Relation"
            If field.GetAttribute("Type") = "Relation" Then
              Dim rel As XmlElement = Nothing

              Dim dataset1 As ESRI.ArcGIS.Geodatabase.IDataset
              Dim dataset2 As ESRI.ArcGIS.Geodatabase.IDataset

              Dim FeatureClass1Name As String
              Dim FeatureClass2Name As String

              dataset1 = m_schematicFeature1.SchematicElementClass
              dataset2 = m_schematicFeature2.SchematicElementClass

              FeatureClass1Name = dataset1.Name
              FeatureClass2Name = dataset2.Name

              For Each rel In m_relations
                                'loop through the xml relations to match based on the from node and to node types

                If rel.GetAttribute("FromType") = FeatureClass1Name And rel.GetAttribute("ToType") = FeatureClass2Name Then
                                    'find the control with the pick list for relationships
                  Dim ctrls() As Windows.Forms.Control = m_curPanel.Controls.Find(field.GetAttribute("DBColumnName"), True)
                  If ctrls.Length > 0 Then
                    ctrl = ctrls(0)
                  End If
                  Dim vals As XmlNodeList = rel.SelectNodes("descendant::Value")
                  Dim val As XmlElement = Nothing
                  Dim myString As String = rel.GetAttribute("FromType") & "-" & rel.GetAttribute("ToType")
                  'validate that the current control string is correct
                  'if there are values, use them
                  Dim blnfound As Boolean = False
                  If vals.Count > 0 Then
                    For Each val In vals
                      If myString & "-" & val.InnerText.ToString = ctrl.Text Then
                        blnfound = True
                        Exit For
                      Else
                        blnfound = False
                      End If
                    Next
                    If blnfound = False Then
                      blnValidated = False
                      If errors.Length > 0 Then
                        errors = "Invalid link connection"
                      Else
                        errors = errors & vbCrLf & "Invalid link connection"
                      End If
                    End If
                  Else
                    If ctrl.Text <> myString Then
                      blnValidated = False
                      If errors.Length > 0 Then
                        errors = "Invalid link connection"
                      Else
                        errors = errors & vbCrLf & "Invalid link connection"
                      End If
                    End If
                  End If
                  If blnfound = False Then 'fix connection list
                    Dim vlist As XmlNodeList = m_dom.SelectNodes("descendant::Relation")
                    Dim v As XmlElement
                    Dim rellist As XmlNodeList = Nothing
                    Dim r As XmlElement = Nothing
                    Dim cboconn As Windows.Forms.ComboBox = ctrl
                    cboconn.Items.Clear()
                    For Each v In vlist
                      If v.GetAttribute("LinkType").ToString = m_curLink.GetAttribute("FeatureClassName").ToString Then
                        'make sure the node types are ok
                        If v.GetAttribute("FromType").ToString = FeatureClass1Name And v.GetAttribute("ToType").ToString = FeatureClass2Name Then  'ToString ??
                          rellist = v.SelectNodes("descendant::Value")
                          If rellist.Count > 0 Then  '
                            For Each r In rellist
                              myString = v.GetAttribute("FromType").ToString & "-" & v.GetAttribute("ToType").ToString & "-" & r.InnerText.ToString
                              cboconn.Items.Add(myString)
                            Next
                          Else 'assume they are not using subtypes
                            cboconn.Items.Add(v.GetAttribute("FromType").ToString & "-" & v.GetAttribute("ToType").ToString)
                          End If
                        End If
                      End If
                    Next
                  End If
                End If
              Next
            End If
          Next
        End If
      End If
    Next

    If errors.Length > 0 Then

      If m_curPanel Is Splitter.Panel1 Then
        btnOKPanel1.Visible = True

        ErrorProvider1.SetError(btnOKPanel1, errors)
      Else
        btnOKPanel2.Visible = True
        ErrorProvider1.SetError(btnOKPanel2, errors)
      End If
    End If
    Return blnValidated
  End Function

  Public Sub cboType_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboNodeType.SelectedValueChanged
    SelectionChanged()
  End Sub


  Public Sub SelectionChanged()
    Try
      Dim ctrl As System.Windows.Forms.Control = Nothing
      Dim ctrl2 As System.Windows.Forms.Control = Nothing
      Dim ctrls() As Object = Nothing
      Dim ctrlstoremove As Collection = New Collection
      Dim labelName As String = ""
      Dim featureClass As String = ""
      Dim cbo As Windows.Forms.ComboBox = Nothing
      Dim lblMain As Windows.Forms.Label = Nothing

      If m_digitCommand Is Nothing Then
        Return
      End If

      'clear any current elements
      If Not m_schematicFeature1 Is Nothing Then
        m_schematicFeature1 = Nothing
        m_digitCommand.SchematicFeature1() = m_schematicFeature1
      End If
      If Not m_schematicFeature2 Is Nothing Then
        m_schematicFeature2 = Nothing
        m_digitCommand.SchematicFeature2() = m_schematicFeature2
      End If

      If m_curPanel Is Splitter.Panel1 Then
        labelName = "lblNodeLabel"
        featureClass = "descendant::NodeFeature"
        cbo = cboNodeType
        lblMain = lblNodeLabel
      Else
        labelName = "lblLinkLabel"
        featureClass = "descendant::LinkFeature"
        cbo = cboLinkType
        lblMain = lblLinkLabel
      End If

      For Each ctrl In m_curPanel.Controls
        If ctrl.Name.StartsWith("lbl") And ctrl.Name.ToString <> labelName Then
          ctrls = m_curPanel.Controls.Find(ctrl.Name.Substring(3), True)
          ctrl2 = ctrls(0)
          ctrlstoremove.Add(ctrl)
          ctrlstoremove.Add(ctrl2)
        End If
      Next

      If ctrlstoremove.Count > 0 Then
        Dim ctrol As System.Windows.Forms.Control
        For Each ctrol In ctrlstoremove
          m_curPanel.Controls.Remove(ctrol)
          ctrol = Nothing
        Next
      End If

      Dim elem As XmlElement = Nothing
      Dim elems As XmlNodeList = Nothing
      m_curfrmWidth = m_curPanel.Width
      elems = m_dom.SelectNodes(featureClass)

      Dim blnFound As Boolean = False
      For Each elem In elems
        If elem.GetAttribute("FeatureClassName").ToString = cbo.Text.ToString Then
          blnFound = True
          Exit For
        End If
      Next
      If blnFound = False Then
        m_schEltClass = Nothing
        Exit Sub
      End If

      If m_curPanel Is Splitter.Panel1 Then
        m_curNode = elem
      Else
        m_curLink = elem
      End If

      'set grid
      elems = elem.SelectNodes("descendant::Field")
      Dim f As XmlElement
      Dim x As Integer = Splitter.Location.X
      Dim y As Integer = lblMain.Location.Y + lblMain.Height + 5

      Dim p As New System.Drawing.Point

      Dim rcount As Integer = 1
      For Each f In elems
        Dim lbl As New System.Windows.Forms.Label
        lbl.Name = "lbl" & f.GetAttribute("DBColumnName").ToString
        lbl.Text = f.GetAttribute("DisplayName").ToString
        lbl.AutoSize = True
        m_curPanel.Controls.Add(lbl)
        p.X = 3
        p.Y = y
        lbl.Location = p
        y = y + lbl.Height + 10
        Select Case f.GetAttribute("Type").ToString
          Case "Text"
            Dim tx As New System.Windows.Forms.TextBox
            ctrl = tx
            tx.Name = f.GetAttribute("DBColumnName").ToString
            If f.GetAttribute("Length").Length > 0 Then
              tx.MaxLength = CInt(f.GetAttribute("Length"))
            End If
            If f.GetAttribute("Default").Length > 0 Then
              tx.Text = f.GetAttribute("Default")
            End If
            m_curPanel.Controls.Add(tx)

          Case "Combo"
            Dim cb As New System.Windows.Forms.ComboBox
            Dim defaulttext As String = ""
            ctrl = cb
            cb.DropDownStyle = Windows.Forms.ComboBoxStyle.DropDownList
            cb.Name = f.GetAttribute("DBColumnName").ToString
            Dim vlist As XmlNodeList = f.SelectNodes("descendant::Value")
            Dim v As XmlElement
            For Each v In vlist
              cb.Items.Add(v.InnerText.ToString)
              If v.GetAttribute("Default").Length > 0 Then
                defaulttext = v.InnerText
              End If
            Next
            If defaulttext.Length > 0 Then
              cb.Text = defaulttext
            End If
            m_curPanel.Controls.Add(cb)

          Case "MaskText"
            Dim MaskControl As New System.Windows.Forms.MaskedTextBox
            ctrl = MaskControl
            Dim mask As String = ""
            MaskControl.Name = f.GetAttribute("DBColumnName").ToString
            If f.GetAttribute("Mask").Length > 0 Then
              mask = f.GetAttribute("Mask")
            Else
              mask = ""
            End If
            MaskControl.Mask = mask
            If f.GetAttribute("Default").Length > 0 Then
              MaskControl.Text = f.GetAttribute("Default")
            End If
            MaskControl.Modified = False
            m_curPanel.Controls.Add(MaskControl)
            AddHandler MaskControl.TextChanged, AddressOf MaskedTextBox

          Case "Number"
            Dim MaskControl As New System.Windows.Forms.MaskedTextBox
            ctrl = MaskControl
            Dim mask As String = ""
            MaskControl.Name = f.GetAttribute("DBColumnName").ToString
            Dim i As Int16 = 1
            If f.GetAttribute("Length").Length > 0 Then
              For i = 1 To CInt(f.GetAttribute("Length"))
                mask = mask & "9"
              Next
            Else
              If f.GetAttribute("Mask").Length > 0 Then
                mask = f.GetAttribute("Mask")
              Else
                mask = ""
              End If
            End If
            MaskControl.Mask = mask
            If f.GetAttribute("Default").Length > 0 Then
              MaskControl.Text = CInt(f.GetAttribute("Default"))
            End If
            MaskControl.Modified = False
            m_curPanel.Controls.Add(MaskControl)
            AddHandler MaskControl.TextChanged, AddressOf MaskedTextBox

          Case "Date"
            Dim dt As New System.Windows.Forms.DateTimePicker
            ctrl = dt
            dt.Name = f.GetAttribute("DBColumnName").ToString
            dt.Value = Now.Date
            dt.Format = Windows.Forms.DateTimePickerFormat.Short
            m_curPanel.Controls.Add(dt)

          Case "Relation"
            Dim cb As New System.Windows.Forms.ComboBox
            ctrl = cb
            cb.DropDownStyle = Windows.Forms.ComboBoxStyle.DropDownList
            cb.Name = f.GetAttribute("DBColumnName").ToString
            Dim vlist As XmlNodeList = m_dom.SelectNodes("descendant::Relation")
            Dim v As XmlElement
            Dim rellist As XmlNodeList = Nothing
            Dim r As XmlElement = Nothing
            Dim myString As String = Nothing
            For Each v In vlist
              If v.GetAttribute("LinkType").ToString = elem.GetAttribute("FeatureClassName").ToString Then
                rellist = v.SelectNodes("descendant::Value")
                If rellist.Count > 0 Then  '
                  For Each r In rellist
                    myString = v.GetAttribute("FromType").ToString & "-" & v.GetAttribute("ToType").ToString & "-" & r.InnerText.ToString
                    cb.Items.Add(myString)
                  Next
                Else 'assume they are not using subtypes
                  cb.Items.Add(v.GetAttribute("FromType").ToString & "-" & v.GetAttribute("ToType").ToString)
                End If
              End If
            Next
            'relations are always mandatory
            ctrl.BackColor = m_mandatoryColor
            ctrl.Tag = "Mandatory"
            m_curPanel.Controls.Add(cb)

        End Select
        If f.GetAttribute("Mandatory").ToString = "True" Then
          ctrl.BackColor = m_mandatoryColor
          ctrl.Tag = "Mandatory"
        End If
      Next
      ResizeForm()

      ' set m_schEltClass
      Dim schElement As ISchematicElement = Nothing
      Dim curElement As XmlElement = Nothing

      If m_curPanel Is Splitter.Panel1 Then
        curElement = m_curNode
      Else
        curElement = m_curLink
      End If

      If m_schEltClass Is Nothing Then
        m_schEltClass = m_schEltClassCont.GetSchematicElementClass(curElement.GetAttribute("FeatureClassName"))
      Else
        If m_schEltClass.Name <> curElement.GetAttribute("FeatureClassName") Then
          m_schEltClass = m_schEltClassCont.GetSchematicElementClass(curElement.GetAttribute("FeatureClassName"))
        End If
      End If


    Catch ex As Exception
      MsgBox(ex.Message)
    End Try
  End Sub


  Public Function CheckValidFeature(ByVal blnFromNode As Boolean) As Boolean

    If m_curLink Is Nothing Then
      Return False
    End If

    Dim fields As XmlNodeList = m_curLink.SelectNodes("descendant::Field")
    Dim field As XmlElement = Nothing
    For Each field In fields
      If field.GetAttribute("Type") = "Relation" Then
        Dim rel As XmlElement = Nothing
        For Each rel In m_relations
          If blnFromNode = True Then
            If m_schematicFeature1 Is Nothing Then
              Return False
            End If
            If rel.GetAttribute("FromType") = m_schematicFeature1.SchematicElementClass.Name Then
              Return True
            End If
          Else
            If m_schematicFeature2 Is Nothing Then
              Return False
            End If
            If rel.GetAttribute("ToType") = m_schematicFeature2.SchematicElementClass.Name Then
              Return True
            End If
          End If
        Next
        Return False
      End If
    Next
    Return True
  End Function

  Private Sub frmDigitize_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
    If m_loading = False Then
      ResizeForm()
    End If
  End Sub

  Private Sub ResizeForm()
    Try
      Dim ctr As System.Windows.Forms.Control
      Dim ctr2 As System.Windows.Forms.Control
      Dim ctrls() As Object
      Dim p As System.Drawing.Point
      'handle panel 1
      For Each ctr In Splitter.Panel1.Controls
        If ctr.Name.StartsWith("lbl") And ctr.Name.ToString <> "lblNodeLabel" Then
          'ctr.Width = Splitter.panel1.Width / 3
          'MsgBox(ctr.Name.Substring(3))
          ctrls = Splitter.Panel1.Controls.Find(ctr.Name.Substring(3), True)
          If ctrls.GetLength(0) > 0 Then
            ctr2 = ctrls(0)

            p.Y = ctr.Location.Y
            p.X = ctr.Width + 3
            ctr2.Location = p
            ctr2.Width = Splitter.Panel1.Width - ctr.Width - 5
          End If
        End If
      Next
      Splitter.Panel1.Refresh()
      'handle panel 2
      For Each ctr In Splitter.Panel2.Controls
        If ctr.Name.StartsWith("lbl") And ctr.Name.ToString <> "lblLinkLabel" Then
          'ctr.Width = Splitter.panel1.Width / 3
          'MsgBox(ctr.Name.Substring(3))
          ctrls = Splitter.Panel2.Controls.Find(ctr.Name.Substring(3), True)
          If ctrls.GetLength(0) > 0 Then
            ctr2 = ctrls(0)
            p.Y = ctr.Location.Y
            p.X = ctr.Width + 3
            ctr2.Location = p
            ctr2.Width = Splitter.Panel2.Width - ctr.Width - 5
          End If
        End If
      Next
      Splitter.Panel2.Refresh()
    Catch ex As Exception
      MsgBox(ex.Message)
    End Try
  End Sub

  Private Sub cboLinkType_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboLinkType.SelectedValueChanged
    SelectionChanged()
  End Sub

  Public Sub FillValue(ByRef schFeature As ISchematicFeature)

    Try

      If m_schEltClass Is Nothing Then
        Err.Raise(513, "CreateNewFeature", "Error getting Feature Class")
      End If

      Dim fldIndex As Int16 = Nothing

      Dim ctrl As Windows.Forms.Control = Nothing
      For Each ctrl In m_curPanel.Controls
        If TypeOf ctrl Is Windows.Forms.Label Or ctrl.Name = "cboNodeType" Then
          'do nothing
        Else
          If TypeOf ctrl Is Windows.Forms.TextBox Or TypeOf ctrl Is Windows.Forms.ComboBox Then
            If ctrl.Text.Length > 0 Then
              'insert in DB
              fldIndex = schFeature.Fields.FindField(ctrl.Name)
              If (fldIndex > -1) Then
                schFeature.Value(fldIndex) = ctrl.Text
                schFeature.Store()
              End If
            End If
          ElseIf TypeOf ctrl Is Windows.Forms.DateTimePicker Then
            fldIndex = schFeature.Fields.FindField(ctrl.Name)
            If (fldIndex > -1) Then
              schFeature.Value(fldIndex) = ctrl.Text
              schFeature.Store()
            End If

          ElseIf TypeOf ctrl Is Windows.Forms.MaskedTextBox Then
            Dim mctrl As Windows.Forms.MaskedTextBox = ctrl
            If mctrl.Text.Length > 0 Then
              If mctrl.Modified = True Then
                If mctrl.MaskCompleted = True Then
                  fldIndex = schFeature.Fields.FindField(ctrl.Name)
                  If (fldIndex > -1) Then
                    schFeature.Value(fldIndex) = ctrl.Text
                    schFeature.Store()
                  End If
                End If
              End If
            End If

          End If

        End If
      Next

      Return

    Catch ex As Exception
      MsgBox(ex.Message)
    End Try
  End Sub


  Private Sub btnOKPanel1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOKPanel1.Click
    'try to create the node at the original point
    If Not m_digitCommand Is Nothing Then
      m_digitCommand.MyMouseUp(m_x, m_y)
    End If

    ErrorProvider1.SetError(btnOKPanel1, "")
    btnOKPanel1.Visible = False
  End Sub

  Private Sub btnOKPanel2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOKPanel2.Click
    'try to create the link with the original points
    m_digitCommand.MyMouseUp(m_x, m_y)

    ErrorProvider1.SetError(btnOKPanel1, "")
    btnOKPanel1.Visible = False
  End Sub

  Private Sub MaskedTextBox(ByVal sender As Object, ByVal e As EventArgs)
    Dim mctrl As Windows.Forms.MaskedTextBox = sender
    mctrl.Modified = True
  End Sub

  Private Sub WindowVisibleChange() Handles Me.VisibleChanged

    If (m_digitCommand Is Nothing) Then
      m_digitCommand = CurrentDigitTool.CurrentTool.currentDigit
    End If

    If (m_digitCommand Is Nothing) Then
      Return
    End If

    If Me.Visible = True And CurrentDigitTool.CurrentTool.currentDockableWindow.IsVisible() = True Then
      If m_digitCommand.FromDeactivate = False Then
        Dim app As ESRI.ArcGIS.Framework.IApplication = Me.Hook
        app.CurrentTool = Nothing
      End If
    End If

    m_digitCommand.EndFeedBack()
    m_digitCommand.FromDeactivate = False

  End Sub

  Friend ReadOnly Property CreateNode() As Boolean
    Get
      Return m_createNode
    End Get
  End Property

  Friend ReadOnly Property AutoClear() As Boolean
    Get
      Return m_autoClear
    End Get
  End Property

  Friend ReadOnly Property FeatureClass() As ISchematicElementClass
    Get
      Return m_schEltClass
    End Get
  End Property

  Public WriteOnly Property x() As Integer
    Set(ByVal Value As Integer)
      m_x = Value
    End Set
  End Property

  Public WriteOnly Property y() As Integer
    Set(ByVal Value As Integer)
      m_y = Value
    End Set
  End Property

  Public WriteOnly Property SchematicFeature1() As ISchematicFeature
    Set(ByVal Value As ISchematicFeature)
      m_schematicFeature1 = Value
    End Set
  End Property

  Public WriteOnly Property SchematicFeature2() As ISchematicFeature
    Set(ByVal Value As ISchematicFeature)
      m_schematicFeature2 = Value
    End Set
  End Property

  'IsRelative return true when the path start with "."
  Private Function IsRelative(ByVal path As String) As Boolean
    If path(0) = "." Then
      Return True
    Else
      Return False
    End If
  End Function

  Private Sub cboNodeType_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboNodeType.SelectedIndexChanged
    SelectionChanged()
  End Sub


  Private Sub Splitter_Panel1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Splitter.Panel1.Click
    If (m_digitCommand Is Nothing) Then
      m_digitCommand = CurrentDigitTool.CurrentTool.currentDigit
    End If

    If Not m_digitCommand Is Nothing Then
      m_digitCommand.EndFeedBack()
    End If

    m_createNode = True

    If (Not m_curPanel Is Splitter.Panel1) Or (m_clickPanel = False) Then

      m_clickPanel = True

      Dim ctrl As Windows.Forms.Control
      m_curPanel = Splitter.Panel1
      For Each ctrl In Splitter.Panel2.Controls
        ctrl.Enabled = False
      Next
      For Each ctrl In Splitter.Panel1.Controls
        ctrl.Enabled = True
      Next
      lblMode.Text = "Create Node"

      If m_curPanel Is Splitter.Panel1 Then
        btnOKPanel1.Visible = False
        ErrorProvider1.SetError(btnOKPanel1, "")
      Else
        btnOKPanel2.Visible = False
        ErrorProvider1.SetError(btnOKPanel2, "")
      End If
      Dim e2 As New System.EventArgs
      cboType_SelectedValueChanged(sender, e2)
    End If
  End Sub

  Private Sub Splitter_Panel2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Splitter.Panel2.Click
    If (m_digitCommand Is Nothing) Then
      m_digitCommand = CurrentDigitTool.CurrentTool.currentDigit
    End If

    If m_digitCommand Is Nothing Then
      Return
    End If

    m_createNode = False

    If Not m_curPanel Is Splitter.Panel2 Then
      Dim ctrl As Windows.Forms.Control
      m_curPanel = Splitter.Panel2
      For Each ctrl In Splitter.Panel1.Controls
        ctrl.Enabled = False
      Next
      For Each ctrl In Splitter.Panel2.Controls
        ctrl.Enabled = True
      Next
      lblMode.Text = "Create Link"

      If Not m_schematicFeature1 Is Nothing Then
        m_schematicFeature1 = Nothing
        m_digitCommand.SchematicFeature1() = m_schematicFeature1
      End If
      If Not m_schematicFeature2 Is Nothing Then
        m_schematicFeature2 = Nothing
        m_digitCommand.SchematicFeature2() = m_schematicFeature2
      End If

      If m_curPanel Is Splitter.Panel1 Then
        btnOKPanel1.Visible = False
        ErrorProvider1.SetError(btnOKPanel1, "")
      Else
        btnOKPanel2.Visible = False
        ErrorProvider1.SetError(btnOKPanel2, "")
      End If
      Dim e2 As New System.EventArgs
      cboLinkType_SelectedValueChanged(sender, e2)
    End If
  End Sub
End Class