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
}
}