Imports UTS_Core.Undo
Imports UTS_Core.UTSModule
Imports UTS_Core.UTSModule.Station


Public Class FrmStationPlan

#Region "初始化"
    Public Property StationPlanCommand() As StationPlanCommandHelpers

    Public Property StationPlanColHelpers() As Dictionary(Of String, PlanColHelper)

    Property StationPlan() As StationPlan

    Private Property SelectRowNode() As RowNode

    Private Property SelectNode() As TreeNode

    Private Property LastSelectNode() As TreeNode

    Private _stationPlanUploading As Boolean

    ''' <summary>
    ''' 显示窗体
    ''' </summary>
    ''' <param name="parentControl"></param>
    Public Sub ShowForm(parentControl As Control)
        FormBorderStyle = FormBorderStyle.None
        TopLevel = False
        Dock = DockStyle.Fill
        Parent = parentControl
        Enabled = StationPlan IsNot Nothing

        Show()
    End Sub

    ''' <summary>
    ''' 测试站修改时处理函数
    ''' </summary>
    ''' <param name="processStation"></param>
    Public Sub Station_Changed(processStation As ProcessStation)
        StationPlan = processStation.Packet.StationPlan

        Enabled = StationPlan IsNot Nothing

        If StationPlan IsNot Nothing Then
            GrpStationPlan.Controls.Clear()
            GrpStationPlan.Controls.Add(StationPlan.TreeView)

            _stationPlanUploading = True '设置更新状态，避免触发树内容变更事件

            InitializeTreeView(StationPlan.TreeView) '初始化树
            StationPlan.UpdateTreeViewStyle() '更新树样式

            _stationPlanUploading = False
        End If
    End Sub

    ''' <summary>
    ''' 初始化站命令帮助信息
    ''' </summary>
    Private Sub InitStationPlanCommandHelper()
        Try
            StationPlanCommand = New StationPlanCommandHelpers()
            StationPlanCommand.InitCommandHelper(UtsDb.LocalDbType, UtsDb.LocalConnString)
        Catch ex As Exception
            Console.WriteLine($"InitStationPlanCommandHelper Error:{ex.Message}")
        End Try
    End Sub

    ''' <summary>
    ''' 初始化站流程帮助信息
    ''' </summary>
    Private Sub InitStationPlanColHelper()
        Try
            StationPlanColHelpers = PlanColHelper.InitPlanColHelper(UtsDb.LocalDbType, UtsDb.LocalConnString)
        Catch ex As Exception
            Console.WriteLine($"InitStationPlanColHelper Error:{ex.Message}")
        End Try

        If StationPlanColHelpers Is Nothing Then
            StationPlanColHelpers = New Dictionary(Of String, PlanColHelper)()
        End If
    End Sub

    ''' <summary>
    ''' 初始化行节点的风格
    ''' </summary>
    Private Sub InitRowNodeStyles()
        If IO.File.Exists(UtsPath.NodeStylePath()) Then
            RowNode.LoadNodeStyles(UtsPath.NodeStylePath())
        Else
            RowNode.InitNodeStyles()
        End If
    End Sub



    Private Sub FrmStationPlan_Load(sender As Object, e As EventArgs) Handles Me.Load

        InitStationPlanCommandHelper()

        InitStationPlanColHelper()

        InitRowNodeStyles()

    End Sub

    ''' <summary>
    ''' 根据节点找寻节点关联的行节点信息
    ''' </summary>
    ''' <param name="node"></param>
    ''' <returns></returns>
    Private Function FindRowInfo(node As TreeNode) As RowNode
        Return CType(node.Tag, RowNode)
    End Function


    Private Sub InitializeTreeView(tree As TreeView)
        With tree
            .Dock = DockStyle.Fill
            .AllowDrop = True '允许拖拽
            .ShowLines = True '显示线条
            .CheckBoxes = True '显示选择框
            .ShowNodeToolTips = False '不显示节点的ToolTip
            .HotTracking = True '移动反显
            .ItemHeight = 20 '行高
            .BorderStyle = BorderStyle.None
            .ContextMenuStrip = CmsMain

            RemoveHandler .ItemDrag, AddressOf TvwStationPlan_ItemDrag
            RemoveHandler .DragEnter, AddressOf TvwStationPlan_DragEnter
            RemoveHandler .DragDrop, AddressOf TvwStationPlan_DragDrop
            RemoveHandler .DragOver, AddressOf TvwStationPlan_DragOver
            RemoveHandler .AfterSelect, AddressOf TvwStationPlan_AfterSelect
            RemoveHandler .AfterCheck, AddressOf TvwStationPlan_AfterCheck
            '   RemoveHandler .KeyDown, AddressOf TvwStationPlan_KeyDown


            AddHandler .ItemDrag, AddressOf TvwStationPlan_ItemDrag
            AddHandler .DragEnter, AddressOf TvwStationPlan_DragEnter
            AddHandler .DragDrop, AddressOf TvwStationPlan_DragDrop
            AddHandler .DragOver, AddressOf TvwStationPlan_DragOver
            AddHandler .AfterSelect, AddressOf TvwStationPlan_AfterSelect
            AddHandler .AfterCheck, AddressOf TvwStationPlan_AfterCheck
            '  AddHandler .KeyDown, AddressOf TvwStationPlan_KeyDown
        End With
    End Sub

    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        RowNodeGrid.InitializeGrid(GrdRowNode)
    End Sub
#End Region

#Region "节点拖拽"

    ''' <summary>
    ''' 开始拖拽子节点
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub TvwStationPlan_ItemDrag(sender As Object, e As ItemDragEventArgs)
        Dim srcNode As TreeNode = CType(e.Item, TreeNode)
        Dim parentRowNode As RowNode = FindRowInfo(srcNode)
        If parentRowNode.CanChangeLever = False Then Return
        DoDragDrop(e.Item, DragDropEffects.Move)
    End Sub

    ''' <summary>
    ''' 拖拽进入控件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub TvwStationPlan_DragEnter(sender As Object, e As DragEventArgs)
        e.Effect = DragDropEffects.Move
    End Sub

    ''' <summary>
    ''' 拖拽松开鼠标
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub TvwStationPlan_DragDrop(sender As Object, e As DragEventArgs)
        '得到拖放数据，并转换为TreeNode型
        Dim srcNode As TreeNode = CType(e.Data.GetData(GetType(TreeNode)), TreeNode)
        Dim parentRowNode As RowNode = FindRowInfo(srcNode)

        Dim tvwDest As TreeView = CType(sender, TreeView)
        Dim destNode As TreeNode = tvwDest.GetNodeAt(tvwDest.PointToClient(New Point(e.X, e.Y))) '获取拖拽所到的节点
        Dim childRowNode As RowNode = FindRowInfo(destNode)

        If IsNothing(destNode) Then Return '未获取到节点
        If destNode.Equals(srcNode) Then Return '节点未移动

        Dim pNode As TreeNode = destNode.Parent
        While pNode IsNot Nothing
            If pNode.Equals(srcNode) Then Return '移动至本身的子节点
            pNode = pNode.Parent
        End While


        If parentRowNode.RowLever <> childRowNode.ParentNode.RowLever Then
            If parentRowNode.CanChangeLever = False Then Return '不允许节点移动
        End If

        DeleteNode(srcNode)
        InsertNode(childRowNode.ParentNode, parentRowNode, destNode.Index)

        srcNode.BackColor = Color.White '修改节点背景色
        tvwDest.SelectedNode = srcNode '选中当前节点
    End Sub

    ''' <summary>
    ''' 拖拽完成
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub TvwStationPlan_DragOver(sender As Object, e As DragEventArgs)

    End Sub
#End Region

#Region "数据同步与反同步"
    Private Sub UpdateRowNodeGridFromNode(node As TreeNode)
        If node Is Nothing Then Return
        If _cellChanged = GridCellChangedEnum.None Then _cellChanged = GridCellChangedEnum.SelectChange

        If _cellChanged = GridCellChangedEnum.SelectChange Then

            RowNodeGrid.AfterSelectUpdateGrid(GrdRowNode, FindRowInfo(node))

            _cellChanged = GridCellChangedEnum.None
        End If
    End Sub


    ''' <summary>
    ''' 选中节点时，更新节点被选中的样式
    ''' </summary>
    ''' <param name="node">更新的节点对象</param>
    ''' <param name="selected">是否处于选中状态</param>
    Private Sub UpdateNodeStyle(node As TreeNode, selected As Boolean)
        Static lastColor As Color = Color.Transparent
        If node Is Nothing Then Return

        If selected Then
            lastColor = node.BackColor
            node.BackColor = Color.DodgerBlue
        Else
            node.BackColor = lastColor
        End If
    End Sub

    Private Sub TvwStationPlan_AfterSelect(sender As Object, e As TreeViewEventArgs)
        If _stationPlanUploading Then Return
        UpdateNodeStyle(LastSelectNode, False) '取消上一选中节点选中状态

        SelectNode = StationPlan.TreeView.SelectedNode
        SelectRowNode = FindRowInfo(SelectNode)

        UpdateRowNodeGridFromNode(SelectNode)
        UpdateNodeStyle(SelectNode, True) '更新当前节点的选中状态

        LastSelectNode = SelectNode
    End Sub

    ''' <summary>
    ''' 详细信息表格内容变更类型枚举值
    ''' </summary>
    Enum GridCellChangedEnum
        ''' <summary>
        ''' 未变更
        ''' </summary>
        None
        ''' <summary>
        ''' 加载流程时时引起的变更
        ''' </summary>
        TestPlan
        ''' <summary>
        ''' 行节点信息修改引起的变更
        ''' </summary>
        RowNodeInfo
        ''' <summary>
        ''' 切换选择节点引起的变更
        ''' </summary>
        SelectChange
    End Enum

    ''' <summary>
    ''' 详细信息表格内容变更类型
    ''' </summary>
    Private _cellChanged As GridCellChangedEnum = GridCellChangedEnum.None

    ''' <summary>
    '''  行节点表，下拉框选择行
    ''' </summary>
    Private _grdSingleRowDropRow As Integer

    ''' <summary>
    ''' 行节点表，下拉框所在列
    ''' </summary>
    Private _grdSingleRowDropCol As Integer


    Private Sub GrdSingleRow_CellChange(sender As Object, e As FlexCell.Grid.CellChangeEventArgs) Handles GrdRowNode.CellChange
        If SelectNode Is Nothing Then Return

        If _cellChanged = GridCellChangedEnum.None Then _cellChanged = GridCellChangedEnum.RowNodeInfo
        If _cellChanged = GridCellChangedEnum.RowNodeInfo Then
            If e.Col = RowNodeGrid.ColNameEnum.ColValue Then
                Manager.RunCommand(New RowNodeCommand(SelectRowNode, e.Row, GrdRowNode.Cell(e.Row, e.Col).Text))
            End If

            _cellChanged = GridCellChangedEnum.None
        End If
    End Sub

    ''' <summary>
    ''' 单行信息表格命令修改后,同步刷新本身信息
    ''' </summary>
    Private Sub GrdSingleRowInfoCommandChanged(commandType As String, commandName As String)
        Dim planCommand As StationPlanCommand = StationPlanCommand.GetCommand(commandType, commandName)
        If planCommand IsNot Nothing Then

            '拷贝所有参数到当前节点信息中
            SelectRowNode.Parameters.Clear()
            For Each cmdParam As CommandParam In planCommand.Params
                SelectRowNode.Parameters.Add(cmdParam.Clone())
            Next


            '更新行节点信息表格内容
            GrdRowNode.Rows = RowNodeGrid.RowNameEnum.Parameters + planCommand.Params.Count
            For idx As Integer = 0 To planCommand.Params.Count - 1
                Dim row As Integer = RowNodeGrid.RowNameEnum.Parameters + idx

                GrdRowNode.Cell(row, RowNodeGrid.ColNameEnum.ColName).Text = planCommand.Params(idx).Desc
                GrdRowNode.Cell(row, RowNodeGrid.ColNameEnum.ColValue).Text = planCommand.Params(idx).Value
            Next

        Else
            GrdRowNode.Rows = RowNodeGrid.RowNameEnum.Parameters + 1

            GrdRowNode.Cell(RowNodeGrid.RowNameEnum.Parameters, RowNodeGrid.ColNameEnum.ColName).Text = RowNodeGrid.RowNameEnum.Parameters.ToString()
            GrdRowNode.Cell(RowNodeGrid.RowNameEnum.Parameters, RowNodeGrid.ColNameEnum.ColValue).Text = ""
        End If
    End Sub

    ''' <summary>
    ''' 下拉框选择对象事件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub GrdSingleRow_ComboClick(sender As Object, e As FlexCell.Grid.ComboClickEventArgs) Handles GrdRowNode.ComboClick
        If SelectNode Is Nothing Then Return
        Select Case _grdSingleRowDropRow
            Case RowNodeGrid.RowNameEnum.CommandType
                '如果类型变化则,清空命令
                Dim cmdType As String = GrdRowNode.Cell(RowNodeGrid.RowNameEnum.CommandType, RowNodeGrid.ColNameEnum.ColValue).Text
                If String.Compare(SelectRowNode.CommandType, cmdType) <> 0 Then
                    GrdRowNode.Cell(RowNodeGrid.RowNameEnum.Command, RowNodeGrid.ColNameEnum.ColValue).Text = ""

                    GrdSingleRowInfoCommandChanged(cmdType, "")
                End If
            Case RowNodeGrid.RowNameEnum.Command
                Dim cmdName As String = GrdRowNode.Cell(RowNodeGrid.RowNameEnum.Command, RowNodeGrid.ColNameEnum.ColValue).Text
                If String.Compare(SelectRowNode.Command, cmdName) <> 0 Then
                    GrdSingleRowInfoCommandChanged(SelectRowNode.CommandType, cmdName)
                End If
            Case RowNodeGrid.RowNameEnum.RowType

        End Select
    End Sub

    ''' <summary>
    ''' 表格下拉框出现时触发事件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub GrdSingleRow_ComboDropDown(sender As Object, e As FlexCell.Grid.ComboDropDownEventArgs) Handles GrdRowNode.ComboDropDown
        _grdSingleRowDropRow = e.Row
        _grdSingleRowDropCol = e.Col

        Select Case e.Row
            Case RowNodeGrid.RowNameEnum.CommandType
                GrdRowNode.ComboBox(0).Items.Clear()
                GrdRowNode.ComboBox(0).Items.AddRange(StationPlanCommand.GetCommandTypes())
            Case RowNodeGrid.RowNameEnum.Command
                GrdRowNode.ComboBox(0).Items.Clear()
                GrdRowNode.ComboBox(0).Items.AddRange(StationPlanCommand.GetCommandNames(SelectRowNode.CommandType))
            Case RowNodeGrid.RowNameEnum.RowType
                GrdRowNode.ComboBox(0).Items.Clear()
                GrdRowNode.ComboBox(0).Items.Add(RowNode.RowTypeEnum.Control)
                GrdRowNode.ComboBox(0).Items.Add(RowNode.RowTypeEnum.Flow)
                GrdRowNode.ComboBox(0).Items.Add(RowNode.RowTypeEnum.Module)
        End Select
    End Sub

#End Region

#Region "RowNode 选择行提示"
    'Private _lastSingleRowSelCol As Integer
    Private _lastSingleRowSelRow As Integer

    ''' <summary>
    ''' 更新流程列名提示
    ''' </summary>
    ''' <param name="colName"></param>
    Private Sub UpdatePlanColNameTip(colName As String)
        If StationPlanColHelpers.ContainsKey(colName) Then
            Dim colHelper As PlanColHelper = StationPlanColHelpers.Item(colName)
            RtxColTip.SuspendLayout()
            RtxColTip.Clear()

            RtxColTip.AppendText($"{colHelper.ColName}{vbCrLf}")
            RtxColTip.AppendText($"类型：{colHelper.ColType}{vbCrLf}")
            RtxColTip.AppendText($"描述：{colHelper.ColDesc}{vbCrLf}")
            RtxColTip.ResumeLayout(False)
        End If
    End Sub


    ''' <summary>
    ''' 更新流程命令提示
    ''' </summary>
    ''' <param name="colName"></param>
    ''' <param name="commandType"></param>
    ''' <param name="commandName"></param>
    ''' <param name="paramIndex"></param>
    Private Sub UpdateCommandTip(colName As String, commandType As String, commandName As String, paramIndex As Integer)

        Dim planCommand As StationPlanCommand = StationPlanCommand.GetCommand(commandType, commandName)
        If planCommand IsNot Nothing Then
            RtxColTip.SuspendLayout()
            RtxColTip.Clear()

            RtxColTip.AppendText($"{colName}{vbCrLf}")
            RtxColTip.AppendText($"类型：{planCommand.Params(paramIndex).Type}{vbCrLf}")
            RtxColTip.AppendText($"上限：{planCommand.Params(paramIndex).UpperLimit}{vbCrLf}")
            RtxColTip.AppendText($"下限：{planCommand.Params(paramIndex).LowerLimit}{vbCrLf}")
            RtxColTip.AppendText($"描述：{planCommand.Params(paramIndex).Desc}{vbCrLf}")
            RtxColTip.ResumeLayout(False)
        Else
            RtxColTip.AppendText($"{colName}{vbCrLf}")
        End If
    End Sub


    ''' <summary>
    ''' 单行信息表格更新当前行
    ''' </summary>
    ''' <param name="row"></param>
    Private Sub UpdateSingleRowTip(row As Integer)
        Dim colName As String = GrdRowNode.Cell(row, RowNodeGrid.ColNameEnum.ColName).Text

        If row >= RowNodeGrid.RowNameEnum.Parameters Then
            Dim commandType As String = GrdRowNode.Cell(RowNodeGrid.RowNameEnum.CommandType, RowNodeGrid.ColNameEnum.ColValue).Text
            Dim command As String = GrdRowNode.Cell(RowNodeGrid.RowNameEnum.Command, RowNodeGrid.ColNameEnum.ColValue).Text

            If String.IsNullOrEmpty(command) Then
                UpdatePlanColNameTip(colName)
            Else
                UpdateCommandTip(colName, commandType, command, row - RowNodeGrid.RowNameEnum.Parameters)
            End If
        Else
            UpdatePlanColNameTip(colName)
        End If

    End Sub


    Private Sub SingleRowSelChange(row As Integer)
        If _lastSingleRowSelRow = row Then Return
        If _lastSingleRowSelRow >= GrdRowNode.Rows Then Return
        '新增命令切换处理

        GrdRowNode.Cell(_lastSingleRowSelRow, RowNodeGrid.ColNameEnum.ColName).FontBold = False

        GrdRowNode.Cell(row, RowNodeGrid.ColNameEnum.ColName).FontBold = True

        UpdateSingleRowTip(row) '更新列提示

        _lastSingleRowSelRow = row
    End Sub

    Private Sub GrdRowNode_SelChange(sender As Object, e As FlexCell.Grid.SelChangeEventArgs) Handles GrdRowNode.SelChange
        SingleRowSelChange(e.FirstRow)
    End Sub
#End Region

#Region "增删节点"

    ''' <summary>
    ''' 删除节点
    ''' </summary>
    ''' <param name="node"></param>
    Private Function DeleteNode(node As TreeNode) As Boolean
        If node Is Nothing Then Return False
        Dim rowNode As RowNode = FindRowInfo(node)
        If rowNode.CanDelete = False Then Return False

        Manager.RunCommand(New RowNodeCommand2(rowNode.ParentNode, rowNode, RowNodeCommand2.ChangeType.Remove))

        Return True
    End Function


    Private Sub ClearAllNode()
        StationPlan.CreateNewStationPlan()
    End Sub

    ''' <summary>
    ''' 上移节点
    ''' </summary>
    ''' <param name="node"></param>
    Private Sub MoveUpNode(node As TreeNode)
        Dim index As Integer = node.Index
        If index = 0 Then Return
        Dim rowNode As RowNode = FindRowInfo(node)

        Manager.RunCommand(New RowNodeCommand2(rowNode.ParentNode, rowNode, RowNodeCommand2.ChangeType.MoveUp))

        rowNode.TreeView.SelectedNode = rowNode.TreeNode
    End Sub

    ''' <summary>
    ''' 下移节点
    ''' </summary>
    ''' <param name="node"></param>
    Private Sub MoveDownNode(node As TreeNode)
        Dim index As Integer = node.Index
        If index = node.Parent.Nodes.Count - 1 Then Return

        Dim rowNode As RowNode = FindRowInfo(node)
        Manager.RunCommand(New RowNodeCommand2(rowNode.ParentNode, rowNode, RowNodeCommand2.ChangeType.MoveDown))

        rowNode.TreeView.SelectedNode = rowNode.TreeNode
    End Sub

    ''' <summary>
    ''' 左移节点
    ''' </summary>
    ''' <param name="node"></param>
    Private Sub MoveLeftNode(node As TreeNode)
        If node.Level = 0 Then Return

        Dim rowNode As RowNode = FindRowInfo(node)
        If rowNode.CanChangeLever = False Then Return
        Manager.RunCommand(New RowNodeCommand2(rowNode.ParentNode, rowNode, RowNodeCommand2.ChangeType.MoveLeft))

        rowNode.TreeView.SelectedNode = rowNode.TreeNode
    End Sub

    ''' <summary>
    ''' 右移节点
    ''' </summary>
    ''' <param name="node"></param>
    Private Sub MoveRightNode(node As TreeNode)
        If node.Index = 0 Then Return

        Dim rowNode As RowNode = FindRowInfo(node)
        If rowNode.CanChangeLever = False Then Return
        Manager.RunCommand(New RowNodeCommand2(rowNode.ParentNode, rowNode, RowNodeCommand2.ChangeType.MoveRight))

        rowNode.TreeView.SelectedNode = rowNode.TreeNode
    End Sub


    ''' <summary>
    ''' 选中节点
    ''' </summary>
    ''' <param name="node"></param>
    Private Sub CheckNode(node As TreeNode)
        If node.Checked Then
            node.Checked = False
        Else
            node.Checked = True
        End If
    End Sub

    ''' <summary>
    ''' 全选节点
    ''' </summary>
    ''' <param name="tvw"></param>
    ''' <param name="checked"></param>
    Private Sub CheckAll(tvw As TreeView, checked As Boolean)
        For Each node As TreeNode In tvw.Nodes
            node.Checked = checked
        Next
    End Sub

    ''' <summary>
    ''' 根据节点当前状态，展开或折叠节点
    ''' </summary>
    ''' <param name="node"></param>
    Private Sub ExpendNode(node As TreeNode)
        If node.IsExpanded Then
            node.Collapse()
        Else
            node.Expand()
        End If
    End Sub

    ''' <summary>
    ''' 在指定父节点下，增加子节点
    ''' </summary>
    ''' <param name="node">添加子节点的树节点</param>
    Private Sub AddNode(node As TreeNode)
        If node Is Nothing Then Return
        Dim parentRowNode As RowNode = FindRowInfo(node)
        Dim rowNode As New RowNode With {.RowType = RowNode.RowTypeEnum.Flow}

        If parentRowNode.CanAddChildNode Then
            Manager.RunCommand(New RowNodeCommand2(parentRowNode, rowNode, RowNodeCommand2.ChangeType.Add))
        Else
            Manager.RunCommand(New RowNodeCommand2(parentRowNode.ParentNode, rowNode, RowNodeCommand2.ChangeType.Insert, parentRowNode.RowIndex + 1))
        End If

    End Sub

    ''' <summary>
    ''' 在指定的行节点下，添加指定行节点
    ''' </summary>
    ''' <param name="parentRowNode"></param>
    ''' <param name="rowNode"></param>
    Private Sub AddNode(parentRowNode As RowNode, rowNode As RowNode)
        If parentRowNode.CanAddChildNode Then
            Manager.RunCommand(New RowNodeCommand2(parentRowNode, rowNode, RowNodeCommand2.ChangeType.Add))
        Else
            Manager.RunCommand(New RowNodeCommand2(parentRowNode.ParentNode, rowNode, RowNodeCommand2.ChangeType.Insert, parentRowNode.RowIndex + 1))
        End If
    End Sub


    Private Sub InsertNode(parentRowNode As RowNode, rowNode As RowNode, index As Integer)
        If parentRowNode.CanAddChildNode Then
            Manager.RunCommand(New RowNodeCommand2(parentRowNode, rowNode, RowNodeCommand2.ChangeType.Insert, index))
        Else
            Manager.RunCommand(New RowNodeCommand2(parentRowNode.ParentNode, rowNode, RowNodeCommand2.ChangeType.Add))
        End If
    End Sub

    ''' <summary>
    ''' 读取XML,加载树状视图
    ''' </summary>
    Private Sub LoadTreeViewFormXml()
        _stationPlanUploading = True
        Dim revStationPlanPath As String = $"{UtsPath.StationPacketTestPlanDirPath(StationPlan.ParentPacket.Name)}\Main.xml"
        Try
            StationPlan.LoadFromXml(revStationPlanPath)
            Manager.ClearCommands()
        Catch ex As Exception
            MsgBox($"加载测试站流程发生错误,{ex.Message}")
            StationPlan.CreateNewStationPlan()
        End Try
        _stationPlanUploading = False
    End Sub

    ''' <summary>
    ''' 读取XML,加载树状视图
    ''' </summary>
    Private Sub LoadTreeViewFormXml(revStationPlanPath As String)
        _stationPlanUploading = True
        Try
            StationPlan.LoadFromXml(revStationPlanPath)
            Manager.ClearCommands()
        Catch ex As Exception
            MsgBox($"加载测试站流程发生错误,{ex.Message}")
            StationPlan.CreateNewStationPlan()
        End Try
        _stationPlanUploading = False
    End Sub

    ''' <summary>
    ''' 将树状视图导出为Xml
    ''' </summary>
    Private Sub ExportTreeViewToXml()
        Dim revStationPlanPath As String = $"{UtsPath.StationPacketTestPlanDirPath(StationPlan.ParentPacket.Name)}\Main.xml"
        StationPlan.ExportToXml(revStationPlanPath)
    End Sub

    Private Sub TsBtnAddNode_Click(sender As Object, e As EventArgs) Handles TsBtnAddNode.Click
        AddNode(SelectNode)
    End Sub

    Private Sub TsBtnDeleteNode_Click(sender As Object, e As EventArgs) Handles TsBtnDeleteNode.Click
        DeleteNode(SelectNode)
    End Sub

    Private Sub TsBtnClearAll_Click(sender As Object, e As EventArgs) Handles TsBtnClearAll.Click
        If MsgBox("该操作无法撤销，是否继续清空节点？", MsgBoxStyle.OkCancel) = MsgBoxResult.Ok Then
            If _stationPlanUploading Then Return
            _stationPlanUploading = True
            ClearAllNode() '清空树节点
            Manager.ClearCommands() '清空撤销缓存
            _stationPlanUploading = False
            If StationPlan.TreeView.Nodes.Count > 0 Then StationPlan.TreeView.SelectedNode = StationPlan.TreeView.Nodes(0)
        End If
    End Sub
    Private Sub TsBtnMoveUp_Click(sender As Object, e As EventArgs) Handles TsBtnMoveUp.Click
        MoveUpNode(SelectNode)
    End Sub

    Private Sub TsBtnMoveDown_Click(sender As Object, e As EventArgs) Handles TsBtnMoveDown.Click
        MoveDownNode(SelectNode)
    End Sub

    Private Sub TsBtnMoveLeft_Click(sender As Object, e As EventArgs) Handles TsBtnMoveLeft.Click
        MoveLeftNode(SelectNode)
    End Sub

    Private Sub TsBtnMoveRight_Click(sender As Object, e As EventArgs) Handles TsBtnMoveRight.Click
        MoveRightNode(SelectNode)
    End Sub

    Private Sub TsBtnNodeCheck_Click(sender As Object, e As EventArgs) Handles TsBtnNodeCheck.Click
        CheckNode(SelectNode)
    End Sub

    Private Sub TsBtnAllCheck_Click(sender As Object, e As EventArgs) Handles TsBtnAllCheck.Click
        CheckAll(StationPlan.TreeView, True)
    End Sub

    Private Sub TsBtnAllUncheck_Click(sender As Object, e As EventArgs) Handles TsBtnAllUncheck.Click
        CheckAll(StationPlan.TreeView, False)
    End Sub


    Private Sub TsBtnCollapseAll_Click(sender As Object, e As EventArgs) Handles TsBtnCollapseAll.Click
        StationPlan.TreeView.CollapseAll()

    End Sub

    Private Sub TsBtnAllExpend_Click(sender As Object, e As EventArgs) Handles TsBtnExpandAll.Click
        StationPlan.TreeView.ExpandAll()

    End Sub

    Private Sub TsBtnNodeExpend_Click(sender As Object, e As EventArgs) Handles TsBtnNodeExpend.Click
        ExpendNode(SelectNode)

    End Sub

    Private Sub TsBtnOpen_Click(sender As Object, e As EventArgs) Handles TsBtnOpen.Click
        Using xml As New OpenFileDialog
            xml.Filter = $"流程文件(*.xml)|*.xml"

            If xml.ShowDialog() = DialogResult.OK Then
                LoadTreeViewFormXml(xml.FileName)
            End If
        End Using
    End Sub

    Private Sub TsBtnLoad_Click(sender As Object, e As EventArgs) Handles TsBtnLoad.Click
        LoadTreeViewFormXml()
    End Sub


    Private Sub TsBtnSave_Click(sender As Object, e As EventArgs) Handles TsBtnSave.Click
        ExportTreeViewToXml()
    End Sub


    ''' <summary>
    ''' 当前节点勾选状态变更时,同步修改其子节点的勾选状态
    ''' </summary>
    ''' <param name="rowNode"></param>
    ''' <param name="node"></param>
    Private Sub AfterCheckUpdateChildRowNode(rowNode As RowNode, node As TreeNode)
        For i As Integer = 0 To node.Nodes.Count - 1
            Dim cRowNode As RowNode = CType(rowNode.RowNodes.Item(i), RowNode)
            cRowNode.Action = rowNode.Action
            cRowNode.UpdateTreeNodeText(node.Nodes.Item(i)) '更新节点文本

            node.Nodes.Item(i).Checked = node.Checked

            AfterCheckUpdateChildRowNode(cRowNode, node.Nodes.Item(i))
        Next
    End Sub

    ''' <summary>
    ''' 当前节点勾选状态变更时，检查同级节点状态是否相同，更新父节点勾选状态
    ''' </summary>
    ''' <param name="rowNode"></param>
    ''' <param name="node"></param>
    Private Sub AfterCheckUpdateParentRowNode(rowNode As RowNode, node As TreeNode)
        If rowNode.RowLever = 0 Then Return
        If rowNode.ParentNode.Action = rowNode.Action Then Return

        For i As Integer = 0 To rowNode.ParentNode.RowNodes.Count - 1
            Dim cRowNode As RowNode = CType(rowNode.ParentNode.RowNodes(i), RowNode)
            If cRowNode.Action <> rowNode.Action Then Return
        Next
        rowNode.ParentNode.Action = rowNode.Action
        rowNode.ParentNode.UpdateTreeNodeText(node.Parent)
        node.Parent.Checked = node.Checked

        AfterCheckUpdateParentRowNode(rowNode.ParentNode, node.Parent)
    End Sub



    Private Sub TvwStationPlan_AfterCheck(sender As Object, e As TreeViewEventArgs)
        If _stationPlanUploading Then Return '设计修改父节点与子节点勾选信息，防止重复处理事件
        _stationPlanUploading = True

        Dim rowNode As RowNode = FindRowInfo(e.Node)
        rowNode.Action = e.Node.Checked
        rowNode.UpdateTreeNodeText(e.Node) '更新节点文本

        If e.Node.Equals(SelectNode) Then
            UpdateRowNodeGridFromNode(e.Node) '更新表格显示
        End If


        AfterCheckUpdateChildRowNode(rowNode, e.Node)

        AfterCheckUpdateParentRowNode(rowNode, e.Node)

        _stationPlanUploading = False
    End Sub

    Private Sub TsBtnStyle_Click(sender As Object, e As EventArgs) Handles TsBtnStyle.Click
        Using dlgStyle As New DlgStationPlanStyle
            If dlgStyle.ShowDialog() = DialogResult.OK Then
                StationPlan.UpdateTreeViewStyle()

                '保存样式
                RowNode.SaveNodeStyles(UtsPath.NodeStylePath)

            End If
        End Using
    End Sub

#End Region

#Region "保存与读取节点文件"

    Private Sub SaveNodeFile(node As TreeNode)
        If node Is Nothing Then Return

        Using dialog As New SaveFileDialog
            dialog.Title = $"请输入需要保存节点的文件名"
            dialog.AddExtension = True
            dialog.Filter = $"节点文件(*.xml)|*.xml"
            If dialog.ShowDialog() <> DialogResult.OK Then Return

            Dim rowNode As RowNode = FindRowInfo(node)
            rowNode.ExportToXml(dialog.FileName)
        End Using
    End Sub

    Private Sub LoadNodeFile(node As TreeNode)
        If node Is Nothing Then Return

        Using dialog As New OpenFileDialog
            dialog.Title = $"请选择需要加载的节点文件"
            dialog.Filter = $"节点文件(*.xml)|*.xml"
            dialog.Multiselect = False
            If dialog.ShowDialog() <> DialogResult.OK Then Return

            _stationPlanUploading = True

            Dim parentRowNode As RowNode = FindRowInfo(node)

            Dim childRowNode As New RowNode
            childRowNode.LoadFormXml(dialog.FileName)

            AddNode(parentRowNode, childRowNode)

            If node.IsExpanded = False Then node.Expand() '展开当前节点
            _stationPlanUploading = False
        End Using

    End Sub

    Private Sub MsiSaveNodeFile_Click(sender As Object, e As EventArgs) Handles MsiSaveNodeFile.Click
        SaveNodeFile(SelectNode)
    End Sub


    Private Sub MsiLoadNodeFile_Click(sender As Object, e As EventArgs) Handles MsiLoadNodeFile.Click
        LoadNodeFile(SelectNode)
    End Sub
#End Region

#Region "撤销重做"
    ''' <summary>
    ''' 撤销重做操作类
    ''' </summary>
    ''' <returns></returns>
    Private Property Manager() As New CommandManager

    ''' <summary>
    ''' 撤销节点操作
    ''' </summary>
    Private Sub UndoNode()
        Manager.Undo()

        UpdateRowNodeGridFromNode(SelectNode) '更新表格显示
    End Sub

    ''' <summary>
    ''' 重做节点操作
    ''' </summary>
    Private Sub RedoNode()
        Manager.Redo()
        UpdateRowNodeGridFromNode(SelectNode) '更新表格显示
    End Sub
#End Region

#Region "节点复制剪切粘贴操作"
    Private Property CloneRowNode As RowNode

    ''' <summary>
    ''' 复制节点
    ''' </summary>
    Private Sub CopyNode(node As TreeNode)
        If node Is Nothing Then Return
        CloneRowNode = FindRowInfo(node).Clone()
    End Sub

    ''' <summary>
    ''' 剪切节点
    ''' </summary>
    Private Sub CutNode(node As TreeNode)
        If node Is Nothing Then Return

        If DeleteNode(node) Then
            CloneRowNode = FindRowInfo(node)
        End If
    End Sub

    ''' <summary>
    ''' 粘贴节点
    ''' </summary>
    Private Sub PasteNode(node As TreeNode)
        If CloneRowNode Is Nothing Then Return
        If node Is Nothing Then Return

        Dim parentRowNode As RowNode = FindRowInfo(node)
        Dim childRowNode As RowNode = CloneRowNode.Clone()

        AddNode(parentRowNode, childRowNode)
        If node.IsExpanded = False Then node.Expand()
    End Sub




    Private Sub MsiCopyNode_Click(sender As Object, e As EventArgs) Handles MsiCopyNode.Click
        CopyNode(SelectNode)
    End Sub

    Private Sub MsiCutNode_Click(sender As Object, e As EventArgs) Handles MsiCutNode.Click
        CutNode(SelectNode)
    End Sub

    Private Sub MsiNodePaste_Click(sender As Object, e As EventArgs) Handles MsiNodePaste.Click
        PasteNode(SelectNode)
    End Sub

    Private Sub MsiUndo_Click(sender As Object, e As EventArgs) Handles MsiUndo.Click
        UndoNode()
    End Sub

    Private Sub MsiRedo_Click(sender As Object, e As EventArgs) Handles MsiRedo.Click
        RedoNode()
    End Sub

    ''' <summary>
    ''' 快捷键操作
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub TvwStationPlan_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
        If e.Modifiers = Keys.Control Then
            Select Case e.KeyCode
                Case Keys.C '复制
                    If StationPlan.TreeView.Focused = False Then Return
                    CopyNode(SelectNode)
                Case Keys.X '剪切
                    If StationPlan.TreeView.Focused = False Then Return
                    CutNode(SelectNode)
                Case Keys.V '粘贴
                    If StationPlan.TreeView.Focused = False Then Return
                    PasteNode(SelectNode)

                Case Keys.Z '撤销
                    UndoNode()
                Case Keys.Y '重做
                    RedoNode()

                Case Keys.O '加载
                    LoadTreeViewFormXml()
                Case Keys.S '保存
                    ExportTreeViewToXml()

                Case Keys.Up '节点上移
                    MoveUpNode(SelectNode)
                Case Keys.Down '节点下移
                    MoveDownNode(SelectNode)
                Case Keys.Left '节点左移
                    MoveLeftNode(SelectNode)
                Case Keys.Right '节点移动
                    MoveRightNode(SelectNode)

                Case Keys.D '增加节点
                    AddNode(SelectNode)
                Case Keys.R '删除节点
                    DeleteNode(SelectNode)
            End Select
        ElseIf e.Modifiers = Keys.Alt Then
            Select Case e.KeyCode
                Case Keys.O '加载指定节点文件
                    LoadNodeFile(SelectNode)
                Case Keys.S '保存指定节点
                    SaveNodeFile(SelectNode)
            End Select

        ElseIf e.Modifiers = Keys.None Then
            Select Case e.KeyCode
                Case Keys.Back '删除
                    If StationPlan.TreeView.Focused = False Then Return
                    DeleteNode(SelectNode)
            End Select

        End If
    End Sub

    Private Sub GrdRowNode_Load(sender As Object, e As EventArgs) Handles GrdRowNode.Load

    End Sub


#End Region

End Class