using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using DPumpHydr.WinFrmUI.RLT.Controls; using DPumpHydr.WinFrmUI.RLT.Util; using static DPumpHydr.WinFrmUI.RLT.Helper.CrownHelper; namespace DPumpHydr.WinFrmUI.Base { public partial class StepTreeView : CrownScrollView { private StepTreeNode _selStepNode = null; private StepTreeNodePara SelStepNodePara { get { if (_selStepNode == null) return null; return _selStepNode.NodePara; } } /// /// 步骤节点选择改变前后事件 /// public event Func BeforeSelectedNodeChangedEvent; public event Func AfterSelectedNodeChangedEvent; /// /// /// public StepTreeView() { BuildNodeImageList(); _nodes = new ObservableList(); } #region 构建和获取树 /// /// 根据步骤ID聚焦节点 /// /// public void SetFocusedNode(long StepNodeID) { this._selStepNode = GetNodeByID(StepNodeID); RefreshAllNodesImage(); Invalidate(); } /// /// 内部使用, 不对外 /// /// private void SetSelectNode4Click(StepTreeNode node) { if (node == null || !node.NodePara.AllowSelect) return; if (BeforeSelectedNodeChangedEvent != null) { if (BeforeSelectedNodeChangedEvent.Invoke(this.SelStepNodePara, node.NodePara) == false) { return; } } if (AfterSelectedNodeChangedEvent != null) { if (AfterSelectedNodeChangedEvent.Invoke(this.SelStepNodePara, node.NodePara) == false) { return; } } // _selStepNode = node; RefreshAllNodesImage(); Invalidate(); } /// /// /// /// /// private StepTreeNode GetNodeByID(long StepNodeID) { foreach (var node1 in this._nodes) { var step1 = node1.NodePara; if (step1.ID == StepNodeID) { return node1; } if (node1.Nodes != null && node1.Nodes.Count > 0) { foreach (var node2 in node1.Nodes) { var step2 = node2.NodePara; if (step2.ID == StepNodeID) { return node2; } if (node2.Nodes != null && node2.Nodes.Count > 0) { foreach (var node3 in node2.Nodes) { var step3 = node3.NodePara; if (step3.ID == StepNodeID) { return node3; } } } } } } return null; } /// /// /// /// private void BuildTree(List node_paras_list ) { this._nodes.Clear(); var node_paras1 = node_paras_list.Where(x => x.ParentID == 0).OrderByDescending(x => x.ID); foreach (var node_para1 in node_paras1) { StepTreeNode node1 = new(this,node_para1) ; var step_paras2 = node_paras_list.Where(x => x.ParentID == node_para1.ID).OrderBy(x => x.ID); for (int x2 = 0; x2 < step_paras2.Count(); x2++) { var step_para2 = step_paras2.ElementAt(x2); StepTreeNode node2 = new(this, step_para2); node1.Nodes.Add(node2); var step_paras3 = node_paras_list.Where(x => x.ParentID == step_para2.ID).OrderBy(x => x.ID); if (step_paras3 != null && step_paras3.Count() > 0) { for (int x3 = 0; x3 < step_paras3.Count(); x3++) { var step_para3 = step_paras3.ElementAt(x3); StepTreeNode node3 = new(this, step_para3); node2.Nodes.Add(node3); } node2.Expanded = true; } } node1.Expanded = true; this._nodes.Add(node1); } UpdateNodes(); } /// /// 设置步骤数据源 /// /// public void SetStepSource(List steps) { BuildTree(steps); RefreshAllNodesImage(); } /// /// 设置步骤数据源 /// /// /// public void SetStepSource(List steps, long ID) { BuildTree(steps); SetFocusedNode(ID); } #endregion #region 图标 public bool IsShowIcons { get; set; } = true; private System.Windows.Forms.ImageList _imageList = null; private void BuildNodeImageList() { _imageList = new System.Windows.Forms.ImageList(); _imageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit; _imageList.TransparentColor = System.Drawing.Color.Transparent; _imageList.Images.Add(DPumpHydr.WinFrmUI.Volute.Properties.Resources.errorstep16);//0 _imageList.Images.Add(DPumpHydr.WinFrmUI.Volute.Properties.Resources.finishstep16);//1 _imageList.Images.Add(DPumpHydr.WinFrmUI.Volute.Properties.Resources.xiangxia32);//2 _imageList.Images.Add(DPumpHydr.WinFrmUI.Volute.Properties.Resources.ingstep32); //3 _imageList.Images.Add(DPumpHydr.WinFrmUI.Volute.Properties.Resources.WaitingGray32);//4 } /// /// /// /// /// private void RefreshAllNodesImage() { foreach (var node1 in this._nodes) { node1.Icon = BuildNodeImage(node1.NodePara); if (node1.Nodes != null) { foreach (var node2 in node1.Nodes) { node2.Icon = BuildNodeImage(node2.NodePara); //最多遍历3层 if (node2.Nodes != null) { foreach (var node3 in node2.Nodes) { node3.Icon = BuildNodeImage(node3.NodePara); } } } } } } /// /// /// /// /// private System.Drawing.Image BuildNodeImage(StepTreeNodePara node) { if (node.SpecImage != null) return node.SpecImage; if (this._selStepNode != null && node.ID == this._selStepNode.NodePara.ID) { return this._imageList.Images[3]; } if (node.ParentID == 0) return this._imageList.Images[2]; if (node.DataState == StepTreeNodePara.eDataState.错误) return this._imageList.Images[0]; if (node.ProgressState == StepTreeNodePara.eProgressState.已完成) return this._imageList.Images[1]; if (node.ProgressState == StepTreeNodePara.eProgressState.未完成) return this._imageList.Images[4]; if (node.ProgressState == StepTreeNodePara.eProgressState.正在进行) return this._imageList.Images[3]; return null; } //注册事件(备份) private void RegistEvents() { //this.treeList1.GetSelectImage += (sender, e) => //{ // var ID = Convert.ToInt64(e.Node.GetValue("ID")); // var stepNode = GetStepSource().Find(x => x.ID == ID); // if (stepNode == null) // return; // switch (stepNode.DataState) // { // case TreeStepNode.eDataState.错误: e.NodeImageIndex = 0; break; // case TreeStepNode.eDataState.正确: e.NodeImageIndex = 1; break; // case TreeStepNode.eDataState.未知: e.NodeImageIndex = -1; break; // default: break; // } //}; //this.treeList1.GetStateImage += (sender, e) => //{ // var ID = Convert.ToInt64(e.Node.GetValue("ID")); // var stepNode = GetStepSource().Find(x => x.ID == ID); // if (stepNode == null) // return; // switch (stepNode.ProgressState) // { // case TreeStepNode.eProgressState.未完成: e.NodeImageIndex = 0; break; // case TreeStepNode.eProgressState.正在进行: e.NodeImageIndex = 1; break; // case TreeStepNode.eProgressState.已完成: e.NodeImageIndex = 2; break; // default: break; // } //}; //this.treeList1.BeforeFocusNode += (sender, e) => //{ // var nextStepID = Convert.ToInt64(e.Node.GetValue("ID")); // var nextStepNode = GetStepSource().Find(x => x.ID == nextStepID); // if (!nextStepNode.AllowSelect) // { // e.CanFocus = false; // return; // } // if (_selStepNode != null) // { // if (_selStepNode.ID == nextStepNode.ID) // return; // } // if (this.BeforeStepNodeSelectedChangedEvent != null) // { // TreeStepNode beforeStepNode = null; // if (e.OldNode != null) // { // var beforeStepID = Convert.ToInt64(e.OldNode.GetValue("ID")); // beforeStepNode = GetStepSource().Find(x => x.ID == beforeStepID); // } // if (!this.BeforeStepNodeSelectedChangedEvent(beforeStepNode, nextStepNode)) // { // e.CanFocus = false; // return; // } // } //}; //this.treeList1.AfterFocusNode += (sender, e) => //{ // var ID = Convert.ToInt64(e.Node.GetValue("ID")); // var nodeModel = GetStepSource().Find(x => x.ID == ID); // this.SelectedStepNode = nodeModel; //}; //this.treeList1.AfterExpand += (sender, e) => //{ // if (_selStepNode != null) // { // var node = this.treeList1.FindNodeByKeyID(_selStepNode.ID); // if (e.Node.Nodes.Contains(node)) // this.treeList1.FocusedNode = node; // } //}; } #endregion #region Field Region private bool _disposed; private readonly int _topNodeSpaceWidth = 5;//顶部节点左边的间隔空间 private readonly int _iconSize = 16; private int _itemHeight = 30; private int _indent = 15;//缩进 父节点给定的水平空间量 Determines the amount of horizontal space given by parent node. #endregion #region 鼠标操作 protected override void OnMouseMove(MouseEventArgs e) { CheckNodeHover(); base.OnMouseMove(e); } protected override void OnMouseWheel(MouseEventArgs e) { CheckNodeHover(); base.OnMouseWheel(e); } protected override void OnMouseDown(MouseEventArgs e) { if (e.Button is MouseButtons.Left or MouseButtons.Right) { foreach (StepTreeNode node in _nodes) { CheckNodeClick(node, OffsetMousePosition, e.Button); } } base.OnMouseDown(e); } protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); } protected override void OnMouseDoubleClick(MouseEventArgs e) { if (ModifierKeys == Keys.Control) { return; } if (e.Button == MouseButtons.Left) { foreach (StepTreeNode node in _nodes) { CheckNodeDoubleClick(node, OffsetMousePosition); } } base.OnMouseDoubleClick(e); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); foreach (StepTreeNode node in _nodes) { NodeMouseLeave(node); } } #endregion #region 构建Node private ObservableList _nodes; private void UpdateNodes() { if (IsDragging) { return; } ContentSize = new(0, 0); if (_nodes.Count == 0) { return; } int yOffset = 0; bool isOdd = false; int index = 0; StepTreeNode prevNode = null; for (int i = 0; i <= _nodes.Count - 1; i++) { StepTreeNode node = _nodes[i]; UpdateNode(node, ref prevNode, 0, ref yOffset, ref isOdd, ref index); } ContentSize = new(ContentSize.Width, yOffset); Invalidate(); } private void UpdateNode(StepTreeNode node, ref StepTreeNode prevNode, int indent, ref int yOffset, ref bool isOdd, ref int index) { UpdateNodeBounds(node, yOffset, indent); yOffset += _itemHeight; node.Odd = isOdd; isOdd = !isOdd; node.VisibleIndex = index; index++; node.PrevVisibleNode = prevNode; if (prevNode != null) { prevNode.NextVisibleNode = node; } prevNode = node; if (node.Expanded) { foreach (StepTreeNode childNode in node.Nodes) { UpdateNode(childNode, ref prevNode, indent + _indent, ref yOffset, ref isOdd, ref index); } } } private void UpdateNodeBounds(StepTreeNode node, int yOffset, int indent) { int expandTop = yOffset + (_itemHeight / 2) - (_topNodeSpaceWidth / 2); node.ExpandArea = new(indent + 3, expandTop, _topNodeSpaceWidth, _topNodeSpaceWidth); int iconTop = yOffset + (_itemHeight / 2) - (_iconSize / 2); if (IsShowIcons) { node.IconArea = new(node.ExpandArea.Right + 2, iconTop, _iconSize, _iconSize); } else { node.IconArea = new(node.ExpandArea.Right, iconTop, 0, 0); } using (Graphics g = CreateGraphics()) { int textSize = (int)g.MeasureString(node.Text, Font).Width; node.TextArea = new(node.IconArea.Right + 2, yOffset, textSize + 1, _itemHeight); } node.FullArea = new(indent, yOffset, node.TextArea.Right - indent, _itemHeight); if (ContentSize.Width < node.TextArea.Right + 2) { ContentSize = new(node.TextArea.Right + 2, ContentSize.Height); } } /// /// 节点是否悬停 /// private void CheckNodeHover() { if (!ClientRectangle.Contains(PointToClient(MousePosition))) { return; } foreach (StepTreeNode node in _nodes) { CheckNodeHover(node, OffsetMousePosition); } } /// /// /// /// /// private void CheckNodeHover(StepTreeNode node, Point location) { bool isHover = node.FullArea.Contains(location); if (node.IsHover != isHover) { node.IsHover = isHover; Invalidate(); } foreach (StepTreeNode childNode in node.Nodes) { CheckNodeHover(childNode, location); } } /// /// 鼠标离开 /// /// private void NodeMouseLeave(StepTreeNode node) { node.IsHover = false; foreach (StepTreeNode childNode in node.Nodes) { NodeMouseLeave(childNode); } Invalidate(); } /// /// 检查鼠标点击在哪个 /// /// /// /// private void CheckNodeClick(StepTreeNode node, Point location, MouseButtons button) { Rectangle rect = GetNodeFullRowArea(node); if (rect.Contains(location)) { if (node.ExpandArea.Contains(location)) { if (button == MouseButtons.Left) { node.Expanded = !node.Expanded; } } else { if (button == MouseButtons.Left) { SetSelectNode4Click(node); return; } else if (button == MouseButtons.Right) {//以后做菜单 //if (!SelectedNodes.Contains(node)) //{ // SelectNode(node); //} return; } } } //检查下一级 if (node.Expanded) { foreach (StepTreeNode childNode in node.Nodes) { CheckNodeClick(childNode, location, button); } } } /// /// 双击 展开 /// /// /// private void CheckNodeDoubleClick(StepTreeNode node, Point location) { Rectangle rect = GetNodeFullRowArea(node); if (rect.Contains(location)) { if (!node.ExpandArea.Contains(location)) { node.Expanded = !node.Expanded; } return; } if (node.Expanded) { foreach (StepTreeNode childNode in node.Nodes) { CheckNodeDoubleClick(childNode, location); } } } /// /// /// /// /// public Rectangle GetNodeFullRowArea(StepTreeNode node) { if (node.ParentNode != null && !node.ParentNode.Expanded) { return new Rectangle(-1, -1, -1, -1); } int width = Math.Max(ContentSize.Width, Viewport.Width); Rectangle rect = new(0, node.FullArea.Top, width, _itemHeight); return rect; } /// /// 确保所选节点可见 /// public void EnsureVisible() { if (_selStepNode == null) { return; } // foreach (StepTreeNode node in SelectedNodes) { _selStepNode.EnsureVisible(); } int itemTop = -1; if (_selStepNode != null) { itemTop = _selStepNode.FullArea.Top; } int itemBottom = itemTop + _itemHeight; if (itemTop < Viewport.Top) { VScrollTo(itemTop); } if (itemBottom > Viewport.Bottom) { VScrollTo(itemBottom - Viewport.Height); } } #endregion #region Paint Region protected override void OnPaintBackground(PaintEventArgs e) { base.OnPaintBackground(e); //LoadIcons(); } protected override void PaintContent(Graphics g) { // Fill body using (SolidBrush b = new(ThemeProvider.Theme.Colors.GreyBackground)) { g.FillRectangle(b, ClientRectangle); } foreach (StepTreeNode node in _nodes) { DrawNode(node, g); } } private System.Drawing.Color _oddRowBackgroundColor = System.Drawing.Color.White; private System.Drawing.Color _evenRowBackgroundColor = System.Drawing.Color.FromArgb(238 ,233, 233); private void DrawNode(StepTreeNode node, Graphics g) { Rectangle rect = GetNodeFullRowArea(node); // 1.绘制背景 Draw background Color bgColor = node.Odd ? _oddRowBackgroundColor : _evenRowBackgroundColor; if (_selStepNode != null && _selStepNode == node) {//被选中的背景 bgColor = ThemeProvider.Theme.Colors.BlueSelection;// Focused ? ThemeProvider.Theme.Colors.BlueSelection : System.Drawing.Color.DodgerBlue; } using (SolidBrush b = new(bgColor)) { g.FillRectangle(b, rect); } // 2.绘制图标 Draw icon if (IsShowIcons && node.Icon != null) { g.DrawImageUnscaled(node.Icon, node.IconArea.Location); } // 3. 绘制文字 Draw text if ( node == this._selStepNode) { System.Drawing.Color text_color = System.Drawing.Color.White; if (node.IsHover) { text_color = ThemeProvider.Theme.Colors.BlueSelection; } using (SolidBrush b = new(text_color)) { StringFormat stringFormat = new() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }; g.DrawString(node.Text, Font, b, node.TextArea, stringFormat); } } else { using (SolidBrush b = new(System.Drawing.Color.Black)) { StringFormat stringFormat = new() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }; g.DrawString(node.Text, Font, b, node.TextArea, stringFormat); } } // 4. 绘制下一级 Draw child nodes if (node.Expanded) { foreach (StepTreeNode childNode in node.Nodes) { DrawNode(childNode, g); } } } #endregion #region Dispose Region protected override void Dispose(bool disposing) { if (!_disposed) { if (BeforeSelectedNodeChangedEvent != null) { BeforeSelectedNodeChangedEvent = null; } if (AfterSelectedNodeChangedEvent != null) { AfterSelectedNodeChangedEvent = null; } if (_nodes != null) { _nodes.Dispose(); } _disposed = true; } base.Dispose(disposing); } #endregion } }