Files
mRemoteNG/mRemoteV1/Tree/Tree.Node.vb
2013-03-16 22:37:34 -05:00

573 lines
23 KiB
VB.net

Imports System.Windows.Forms
Imports mRemoteNG.App.Runtime
Imports System.DirectoryServices
Namespace Tree
Public Class Node
Public Enum Type
None = 0
Root = 1
Container = 2
Connection = 3
PuttyRoot = 4
PuttySession = 5
End Enum
Private Shared _TreeView As TreeView
Public Shared Property TreeView() As TreeView
Get
Return _TreeView
End Get
Set(ByVal value As TreeView)
_TreeView = value
End Set
End Property
Public Shared Property SelectedNode() As TreeNode
Get
Return _TreeView.SelectedNode
End Get
Set(ByVal value As TreeNode)
treeNodeToBeSelected = value
SelectNode()
End Set
End Property
Private Shared treeNodeToBeSelected As TreeNode
Private Delegate Sub SelectNodeCB()
Private Shared Sub SelectNode()
If _TreeView.InvokeRequired = True Then
Dim d As New SelectNodeCB(AddressOf SelectNode)
_TreeView.Invoke(d)
Else
_TreeView.SelectedNode = treeNodeToBeSelected
End If
End Sub
Public Shared Function GetConstantID(ByVal node As TreeNode) As String
Select Case GetNodeType(node)
Case Type.Connection
Return TryCast(node.Tag, mRemoteNG.Connection.Info).ConstantID
Case Type.Container
Return TryCast(node.Tag, mRemoteNG.Container.Info).ConnectionInfo.ConstantID
End Select
Return Nothing
End Function
Public Shared Function GetNodeFromPositionID(ByVal id As Integer) As TreeNode
For Each conI As Connection.Info In connectionList
If conI.PositionID = id Then
If conI.IsContainer Then
Return TryCast(conI.Parent, Container.Info).TreeNode
Else
Return conI.TreeNode
End If
End If
Next
Return Nothing
End Function
Public Shared Function GetNodeFromConstantID(ByVal id As String) As TreeNode
For Each conI As Connection.Info In connectionList
If conI.ConstantID = id Then
If conI.IsContainer Then
Return TryCast(conI.Parent, Container.Info).TreeNode
Else
Return conI.TreeNode
End If
End If
Next
Return Nothing
End Function
Public Shared Function GetNodeType(ByVal treeNode As TreeNode) As Tree.Node.Type
Try
If treeNode Is Nothing Then
Return Type.NONE
End If
If treeNode.Tag Is Nothing Then
Return Type.NONE
End If
If TypeOf treeNode.Tag Is Root.PuttySessions.Info Then
Return Type.PuttyRoot
ElseIf TypeOf treeNode.Tag Is Root.Info Then
Return Type.Root
ElseIf TypeOf treeNode.Tag Is Container.Info Then
Return Type.Container
ElseIf TypeOf treeNode.Tag Is Connection.PuttySession.Info Then
Return Type.PuttySession
ElseIf TypeOf treeNode.Tag Is Connection.Info Then
Return Type.Connection
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn't get node type" & vbNewLine & ex.Message, True)
End Try
Return Type.NONE
End Function
Public Shared Function GetNodeTypeFromString(ByVal str As String) As Tree.Node.Type
Try
Select Case LCase(str)
Case "root"
Return Type.Root
Case "container"
Return Type.Container
Case "connection"
Return Type.Connection
End Select
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn't get node type from string" & vbNewLine & ex.Message, True)
End Try
Return Type.NONE
End Function
Public Shared Function Find(ByVal treeNode As TreeNode, ByVal searchFor As String) As TreeNode
Dim tmpNode As TreeNode
Try
If InStr(LCase(treeNode.Text), LCase(searchFor)) > 0 Then
Return treeNode
Else
For Each childNode As TreeNode In treeNode.Nodes
tmpNode = Find(childNode, searchFor)
If Not tmpNode Is Nothing Then
Return tmpNode
End If
Next
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Find node failed" & vbNewLine & ex.Message, True)
End Try
Return Nothing
End Function
Public Shared Function Find(ByVal treeNode As TreeNode, ByVal conInfo As Connection.Info) As TreeNode
Dim tmpNode As TreeNode
Try
If treeNode.Tag Is conInfo Then
Return treeNode
Else
For Each childNode As TreeNode In treeNode.Nodes
tmpNode = Find(childNode, conInfo)
If Not tmpNode Is Nothing Then
Return tmpNode
End If
Next
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Find node failed" & vbNewLine & ex.Message, True)
End Try
Return Nothing
End Function
Public Shared Function IsEmpty(ByVal treeNode As TreeNode) As Boolean
Try
If treeNode.Nodes.Count <= 0 Then
Return False
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "IsEmpty (Tree.Node) failed" & vbNewLine & ex.Message, True)
End Try
Return True
End Function
Public Shared Function AddNode(ByVal NodeType As Tree.Node.Type, Optional ByVal Text As String = "") As TreeNode
Try
Dim nNode As New TreeNode
Select Case NodeType
Case Type.Connection Or Type.PuttySession
nNode.Text = My.Language.strNewConnection
nNode.ImageIndex = Images.Enums.TreeImage.ConnectionClosed
nNode.SelectedImageIndex = Images.Enums.TreeImage.ConnectionClosed
Case Type.Container
nNode.Text = My.Language.strNewFolder
nNode.ImageIndex = Images.Enums.TreeImage.Container
nNode.SelectedImageIndex = Images.Enums.TreeImage.Container
Case Type.Root
nNode.Text = My.Language.strNewRoot
nNode.ImageIndex = Images.Enums.TreeImage.Root
nNode.SelectedImageIndex = Images.Enums.TreeImage.Root
End Select
If Text <> "" Then
nNode.Text = Text
End If
Return nNode
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "AddNode failed" & vbNewLine & ex.Message, True)
End Try
Return Nothing
End Function
Public Shared Sub AddADNodes(ByVal ldapPath As String)
Try
Dim adCNode As TreeNode = Tree.Node.AddNode(Type.Container)
Dim nContI As New mRemoteNG.Container.Info()
nContI.TreeNode = adCNode
nContI.ConnectionInfo = New mRemoteNG.Connection.Info(nContI)
If Tree.Node.SelectedNode IsNot Nothing Then
If Tree.Node.GetNodeType(Tree.Node.SelectedNode) = Tree.Node.Type.Container Then
nContI.Parent = Tree.Node.SelectedNode.Tag
End If
End If
Dim strDisplayName As String
strDisplayName = ldapPath.Remove(0, ldapPath.IndexOf("OU=") + 3)
strDisplayName = strDisplayName.Substring(0, strDisplayName.IndexOf(","))
nContI.Name = strDisplayName
nContI.TreeNode.Text = strDisplayName
adCNode.Tag = nContI
containerList.Add(nContI)
CreateADSubNodes(adCNode, ldapPath)
SelectedNode.Nodes.Add(adCNode)
SelectedNode = SelectedNode.Nodes(SelectedNode.Nodes.Count - 1)
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "AddADNodes failed" & vbNewLine & ex.Message, True)
End Try
End Sub
Private Shared Sub CreateADSubNodes(ByVal rNode As TreeNode, ByVal ldapPath As String)
Try
Dim strDisplayName, strDescription, strHostName As String
Dim ldapFilter As String = "(objectClass=computer)" '"sAMAccountName=*"
Dim ldapSearcher As New DirectorySearcher
Dim ldapResults As SearchResultCollection
Dim ldapResult As SearchResult
Dim ResultFields() As String = {"securityEquals", "cn"}
With ldapSearcher
.SearchRoot = New DirectoryEntry(ldapPath)
.PropertiesToLoad.AddRange(ResultFields)
.Filter = ldapFilter
.SearchScope = SearchScope.OneLevel
ldapResults = .FindAll
End With
For Each ldapResult In ldapResults
With ldapResult.GetDirectoryEntry()
strDisplayName = .Properties("cn").Value
strDescription = .Properties("Description").Value
strHostName = .Properties("dNSHostName").Value
End With
Dim adNode As TreeNode = Tree.Node.AddNode(Type.Connection, strDisplayName)
Dim nConI As New mRemoteNG.Connection.Info()
Dim nInh As New mRemoteNG.Connection.Info.Inheritance(nConI, True)
nInh.Description = False
If TypeOf rNode.Tag Is mRemoteNG.Container.Info Then
nConI.Parent = rNode.Tag
End If
nConI.Inherit = nInh
nConI.Name = strDisplayName
nConI.Hostname = strHostName
nConI.Description = strDescription
nConI.TreeNode = adNode
adNode.Tag = nConI 'set the nodes tag to the conI
'add connection to connections
connectionList.Add(nConI)
rNode.Nodes.Add(adNode)
Next
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "CreateADSubNodes failed" & vbNewLine & ex.Message, True)
End Try
End Sub
Public Shared Sub CloneNode(ByVal oldTreeNode As TreeNode, Optional ByVal parentNode As TreeNode = Nothing)
Try
If GetNodeType(oldTreeNode) = Type.Connection Then
Dim oldConnectionInfo As Connection.Info = oldTreeNode.Tag
Dim newConnectionInfo As Connection.Info = oldConnectionInfo.Copy
Dim newInheritance As Connection.Info.Inheritance = oldConnectionInfo.Inherit.Copy()
newInheritance.Parent = newConnectionInfo
newConnectionInfo.Inherit = newInheritance
ConnectionList.Add(newConnectionInfo)
Dim newTreeNode As New TreeNode(newConnectionInfo.Name)
newTreeNode.Tag = newConnectionInfo
newTreeNode.ImageIndex = Images.Enums.TreeImage.ConnectionClosed
newTreeNode.SelectedImageIndex = Images.Enums.TreeImage.ConnectionClosed
newConnectionInfo.TreeNode = newTreeNode
If parentNode Is Nothing Then
oldTreeNode.Parent.Nodes.Insert(oldTreeNode.Index + 1, newTreeNode)
TreeView.SelectedNode = newTreeNode
Else
Dim parentContainerInfo As Container.Info = TryCast(parentNode.Tag, Container.Info)
If parentContainerInfo IsNot Nothing Then
newConnectionInfo.Parent = parentContainerInfo
End If
parentNode.Nodes.Add(newTreeNode)
End If
ElseIf GetNodeType(oldTreeNode) = Type.Container Then
Dim newContainerInfo As Container.Info = TryCast(oldTreeNode.Tag, Container.Info).Copy
Dim newConnectionInfo As Connection.Info = TryCast(oldTreeNode.Tag, Container.Info).ConnectionInfo.Copy
newContainerInfo.ConnectionInfo = newConnectionInfo
Dim newTreeNode As New TreeNode(newContainerInfo.Name)
newTreeNode.Tag = newContainerInfo
newTreeNode.ImageIndex = Images.Enums.TreeImage.Container
newTreeNode.SelectedImageIndex = Images.Enums.TreeImage.Container
newContainerInfo.ConnectionInfo.Parent = newContainerInfo
ContainerList.Add(newContainerInfo)
If parentNode Is Nothing Then
oldTreeNode.Parent.Nodes.Insert(oldTreeNode.Index + 1, newTreeNode)
TreeView.SelectedNode = newTreeNode
Else
parentNode.Nodes.Add(newTreeNode)
End If
For Each childTreeNode As TreeNode In oldTreeNode.Nodes
CloneNode(childTreeNode, newTreeNode)
Next
newTreeNode.Expand()
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.WarningMsg, String.Format(My.Language.strErrorCloneNodeFailed, ex.Message))
End Try
End Sub
Public Shared Sub SetNodeImage(ByVal treeNode As TreeNode, ByVal Img As Images.Enums.TreeImage)
SetNodeImageIndex(treeNode, Img)
End Sub
Private Delegate Sub SetNodeImageIndexCB(ByVal tNode As TreeNode, ByVal ImgIndex As Integer)
Private Shared Sub SetNodeImageIndex(ByVal tNode As TreeNode, ByVal ImgIndex As Integer)
If _TreeView.InvokeRequired Then
Dim s As New SetNodeImageIndexCB(AddressOf SetNodeImageIndex)
_TreeView.Invoke(s, New Object() {tNode, ImgIndex})
Else
tNode.ImageIndex = ImgIndex
tNode.SelectedImageIndex = ImgIndex
End If
End Sub
Public Shared Sub SetNodeToolTip(ByVal e As MouseEventArgs, ByVal tTip As ToolTip)
Try
If My.Settings.ShowDescriptionTooltipsInTree Then
'Find the node under the mouse.
Static old_node As TreeNode
Dim new_node As TreeNode = _TreeView.GetNodeAt(e.X, e.Y)
If new_node Is old_node Then Exit Sub
old_node = new_node
'See if we have a node.
If old_node Is Nothing Then
tTip.SetToolTip(_TreeView, "")
Else
'Get this node's object data.
If GetNodeType(old_node) = Type.Connection Then
tTip.SetToolTip(_TreeView, TryCast(old_node.Tag, mRemoteNG.Connection.Info).Description)
End If
End If
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "SetNodeToolTip failed" & vbNewLine & ex.Message, True)
End Try
End Sub
Public Shared Sub DeleteSelectedNode()
Try
If SelectedNode Is Nothing Then Return
Select Case Tree.Node.GetNodeType(SelectedNode)
Case Type.Root
MessageCollector.AddMessage(Messages.MessageClass.WarningMsg, "The root item cannot be deleted!")
Case Type.Container
If Tree.Node.IsEmpty(SelectedNode) = False Then
If MsgBox(String.Format(My.Language.strConfirmDeleteNodeFolder, SelectedNode.Text), MsgBoxStyle.YesNo Or MsgBoxStyle.Question) = MsgBoxResult.Yes Then
SelectedNode.Remove()
End If
Else
If MsgBox(String.Format(My.Language.strConfirmDeleteNodeFolderNotEmpty, SelectedNode.Text), MsgBoxStyle.YesNo Or MsgBoxStyle.Question) = MsgBoxResult.Yes Then
For Each tNode As TreeNode In SelectedNode.Nodes
tNode.Remove()
Next
SelectedNode.Remove()
End If
End If
Case Type.Connection
If MsgBox(String.Format(My.Language.strConfirmDeleteNodeConnection, SelectedNode.Text), MsgBoxStyle.YesNo Or MsgBoxStyle.Question) = MsgBoxResult.Yes Then
SelectedNode.Remove()
End If
Case Else
MessageCollector.AddMessage(Messages.MessageClass.WarningMsg, "Tree item type is unknown so it cannot be deleted!")
End Select
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Deleting selected node failed" & vbNewLine & ex.Message, True)
End Try
End Sub
Public Shared Sub StartRenameSelectedNode()
If SelectedNode IsNot Nothing Then SelectedNode.BeginEdit()
End Sub
Public Shared Sub FinishRenameSelectedNode(ByVal newName As String)
If newName Is Nothing Then Return
If newName.Length > 0 Then
SelectedNode.Tag.Name = newName
If My.Settings.SetHostnameLikeDisplayName Then
Dim connectionInfo As Connection.Info = TryCast(SelectedNode.Tag, Connection.Info)
If (connectionInfo IsNot Nothing) Then
connectionInfo.Hostname = newName
End If
End If
End If
End Sub
Public Shared Sub MoveNodeUp()
Try
If SelectedNode IsNot Nothing Then
If Not (SelectedNode.PrevNode Is Nothing) Then
TreeView.BeginUpdate()
TreeView.Sorted = False
Dim newNode As TreeNode = SelectedNode.Clone
SelectedNode.Parent.Nodes.Insert(SelectedNode.Index - 1, newNode)
SelectedNode.Remove()
SelectedNode = newNode
TreeView.EndUpdate()
End If
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "MoveNodeUp failed" & vbNewLine & ex.Message, True)
End Try
End Sub
Public Shared Sub MoveNodeDown()
Try
If SelectedNode IsNot Nothing Then
If Not (SelectedNode.NextNode Is Nothing) Then
TreeView.BeginUpdate()
TreeView.Sorted = False
Dim newNode As TreeNode = SelectedNode.Clone
SelectedNode.Parent.Nodes.Insert(SelectedNode.Index + 2, newNode)
SelectedNode.Remove()
SelectedNode = newNode
TreeView.EndUpdate()
End If
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "MoveNodeDown failed" & vbNewLine & ex.Message, True)
End Try
End Sub
Public Shared Sub ExpandAllNodes()
TreeView.BeginUpdate()
TreeView.ExpandAll()
TreeView.EndUpdate()
End Sub
Public Shared Sub CollapseAllNodes()
TreeView.BeginUpdate()
For Each treeNode As TreeNode In TreeView.Nodes(0).Nodes
treeNode.Collapse(False)
Next
TreeView.EndUpdate()
End Sub
Public Shared Sub Sort(ByVal treeNode As TreeNode, ByVal sorting As System.Windows.Forms.SortOrder)
If TreeView Is Nothing Then Return
TreeView.BeginUpdate()
If treeNode Is Nothing Then
If TreeView.Nodes.Count > 0 Then
treeNode = TreeView.Nodes.Item(0)
Else
Return
End If
ElseIf GetNodeType(treeNode) = Type.Connection Then
treeNode = treeNode.Parent
If treeNode Is Nothing Then Return
End If
Sort(treeNode, New Tools.Controls.TreeNodeSorter(sorting))
TreeView.EndUpdate()
End Sub
' Adapted from http://www.codeproject.com/Tips/252234/ASP-NET-TreeView-Sort
Private Shared Sub Sort(ByVal treeNode As TreeNode, ByVal nodeSorter As Tools.Controls.TreeNodeSorter)
For Each childNode As TreeNode In treeNode.Nodes
Sort(childNode, nodeSorter)
Next
Try
Dim sortedNodes As New List(Of TreeNode)
Dim currentNode As TreeNode = Nothing
While (treeNode.Nodes.Count > 0)
For Each childNode As TreeNode In treeNode.Nodes
If (currentNode Is Nothing OrElse nodeSorter.Compare(childNode, currentNode) < 0) Then
currentNode = childNode
End If
Next
treeNode.Nodes.Remove(currentNode)
sortedNodes.Add(currentNode)
currentNode = Nothing
End While
For Each childNode As TreeNode In sortedNodes
treeNode.Nodes.Add(childNode)
Next
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Sort nodes failed" & vbNewLine & ex.Message, True)
End Try
End Sub
Private Delegate Sub ResetTreeDelegate()
Public Shared Sub ResetTree()
If TreeView.InvokeRequired Then
Dim resetTreeDelegate As New ResetTreeDelegate(AddressOf ResetTree)
Windows.treeForm.Invoke(resetTreeDelegate)
Else
TreeView.BeginUpdate()
TreeView.Nodes.Clear()
TreeView.Nodes.Add(My.Language.strConnections)
TreeView.EndUpdate()
End If
End Sub
End Class
End Namespace