using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using System.Xml;
namespace Dongke.IBOSS.Basics.FlowSetting
{
///
/// 流程设计器
///
public partial class FlowBox : UserControl
{
#region 常量
#region 事件
private static readonly object EventNodeDoubleClick = new object();
private static readonly object EventFlowNodeLoading = new object();
#endregion 事件
//private const Version CurrentVersion = new Version(1, 1);
#endregion 常量
#region 成员变量
///
/// 流程项目绘制管理器
///
private ItemManager _itemManager = null;
///
/// 流程编辑模式
///
private FlowBoxMode _flowBoxMode = FlowBoxMode.Edit;
///
/// 加载流程的版本
///
private Version _loadVersion = new Version(1, 1);
///
/// 流程名称
///
private string _flowName = null;
#endregion 成员变量
#region 构造函数
///
/// 构造函数
///
public FlowBox()
{
this.InitializeComponent();
this._itemManager = new ItemManager(this, this.canvasBox);
this.canvasBox.SetCanvasSize(Consts.CANVAS_SIZE_DEFAULT);
this.canvasBox.CanvasControl.BackgroundImage = new Bitmap(this.GetType(), "Images.backImage1.gif");
this.canvasBox.CanvasControl.MouseDown += this.flowCanvas_MouseDown;
this.canvasBox.CanvasControl.MouseMove += this.flowCanvas_MouseMove;
this.canvasBox.CanvasControl.MouseUp += this.flowCanvas_MouseUp;
this.canvasBox.CanvasControl.Paint += this.flowCanvas_Paint;
this.canvasBox.CanvasControl.MouseDoubleClick += this.flowCanvas_MouseDoubleClick;
this.canvasBox.KeyControl.KeyDown += this.keyControl_KeyDown;
}
#endregion 构造函数
#region 属性
///
/// 流程名称
///
public string FlowName
{
get
{
return this._flowName;
}
set
{
this._flowName = value;
}
}
///
/// 加载流程的版本
///
public Version LoadVersion
{
get
{
return this._loadVersion;
}
}
///
/// 流程编辑模式
///
public FlowBoxMode BoxMode
{
get
{
return this._flowBoxMode;
}
set
{
if (this._flowBoxMode != value)
{
this._flowBoxMode = value;
this._itemManager.BoxMode = value;
this.ClearSelection();
// todo
}
}
}
///
/// 获取或设置画布大小
///
public Size CanvasSize
{
get
{
return this.canvasBox.CanvasSize;
}
set
{
this.canvasBox.SetCanvasSize(value);
this._itemManager.RefreshItems();
}
}
///
/// 获取或设置画布背景
///
public Image CanvasBackgroundImage
{
get
{
return this.canvasBox.CanvasBackgroundImage;
}
set
{
this.canvasBox.CanvasBackgroundImage = value;
}
}
///
/// 获取画布
///
public Image CanvasImage
{
get
{
return this.canvasBox.CanvasImage;
}
//set
//{
// this.canvasBox.CanvasImage = value;
//}
}
///
/// 获取画布
///
public Control CanvasControl
{
get
{
return this.canvasBox.CanvasControl;
}
//set
//{
// this.canvasBox.CanvasImage = value;
//}
}
///
/// 获取全部流程项目
///
public List Items
{
get
{
return this._itemManager.Items;
}
}
///
/// 获取选择的流程项目
///
public List SelectedItems
{
get
{
return this._itemManager.SelectedItems;
}
}
///
/// 获取删除的节点
///
public List DeletedNodes
{
get
{
return this._itemManager.DeletedNodes;
}
}
///
/// 获取全部的节点(包括删除的)
///
public List AllNodes
{
get
{
return this._itemManager.AllNodes;
}
}
/////
///// 获取画板
/////
//internal CanvasBox CanvasBox
//{
// get
// {
// return this.canvasBox;
// }
//}
#endregion 属性
#region 事件处理
#region 画布事件
///
/// 画布绘制
///
///
///
private void flowCanvas_Paint(object sender, PaintEventArgs e)
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return;
}
this.canvasBox.SetSmoothingMode(e.Graphics);
//this._itemManager.RefreshActiveItems(e.Graphics);
this._itemManager.RefreshMouseSelectRect(e.Graphics);
}
///
/// 鼠标按下
///
///
///
private void flowCanvas_MouseDown(object sender, MouseEventArgs e)
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return;
}
this._itemManager.MouseDown(e);
}
///
/// 鼠标移动
///
///
///
private void flowCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return;
}
this._itemManager.MouseMove(e);
}
///
/// 鼠标抬起
///
///
///
private void flowCanvas_MouseUp(object sender, MouseEventArgs e)
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return;
}
this._itemManager.MouseUp(e);
}
///
/// 鼠标双击
///
///
///
private void flowCanvas_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return;
}
NodeDoubleClickEventHandler nodeDoubleClick = this.GetNodeDoubleClickEventHandler();
if (nodeDoubleClick != null)
{
FlowNode node = this._itemManager.MouseDoubleClick(e);
if (node != null)
{
nodeDoubleClick(this, new NodeEventArgs(node));
}
}
}
#endregion 画布事件
#endregion 事件处理
#region 公有方法
#region 新建项目
///
/// 停止新建节点(鼠标操作)
///
public void StopDrawingItem()
{
//if (this._flowBoxMode != FlowBoxMode.Edit)
//{
// return;
//}
this._itemManager.StopDrawingItem();
}
///
/// 新建节点(鼠标操作,指定位置)
///
public FlowNode DrawingNode()
{
if (this._flowBoxMode != FlowBoxMode.Edit)
{
return null;
}
return this._itemManager.DrawingNode();
}
///
/// 新建线段(鼠标操作,指定位置)
///
public FlowLine DrawingLine()
{
if (this._flowBoxMode != FlowBoxMode.Edit)
{
return null;
}
return this._itemManager.DrawingLine();
}
///
/// 新建节点(默认位置)
///
/// 节点
public FlowNode NewNode()
{
if (this._flowBoxMode != FlowBoxMode.Edit)
{
return null;
}
return this._itemManager.NewNode();
}
///
/// 新建节点(指定位置)
///
/// 节点位置
public FlowNode NewNode(Point location)
{
if (this._flowBoxMode != FlowBoxMode.Edit)
{
return null;
}
return this._itemManager.NewNode(location);
}
///
/// 新建线段(默认位置)
///
/// 线段
public FlowLine NewLine()
{
if (this._flowBoxMode != FlowBoxMode.Edit)
{
return null;
}
return this._itemManager.NewLine();
}
///
/// 新建线段(指定位置)
///
/// 起始点
/// 结束点
/// 线段
public FlowLine NewLine(Point pointBegin, Point pointEnd)
{
if (this._flowBoxMode != FlowBoxMode.Edit)
{
return null;
}
return this._itemManager.NewLine(pointBegin, pointEnd);
}
#endregion 新建项目
#region 刷新项目
///
/// 刷新Item的图片
///
public void RefreshItems()
{
this._itemManager.RefreshItems();
}
#endregion 刷新项目
#region 操作项目
///
/// 全部不选择
///
public void ClearSelection()
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return;
}
this._itemManager.ClearSelection();
this._itemManager.RefreshItems();
}
///
/// 全部选择
///
public void SelectAllItem()
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return;
}
this._itemManager.SelectAllItems();
this._itemManager.RefreshItems();
}
///
/// 删除全部项目
///
public void DeleteAllItem()
{
if (this._flowBoxMode != FlowBoxMode.Edit)
{
return;
}
this._itemManager.DeleteAllItems();
this._itemManager.RefreshItems();
}
///
/// 删除选择项目
///
public void DeleteSelectedItem()
{
if (this._flowBoxMode != FlowBoxMode.Edit)
{
return;
}
this._itemManager.DeleteSelectedItems();
this._itemManager.RefreshItems();
}
///
/// 撤销删除
///
/// 节点编码
public void UndeleteNodeByNodeCode(string nodeCode)
{
foreach (FlowNode node in this._itemManager.DeletedNodes)
{
if (node.ItemCode == nodeCode)
{
this._itemManager.DeletedNodes.Remove(node);
this._itemManager.Items.Add(node);
if (node.NodeState == FlowNodeState.Detached ||
node.NodeState == FlowNodeState.Added)
{
node.NodeState = FlowNodeState.Added;
}
else
{
node.NodeState = FlowNodeState.Unchanged;
}
return;
}
}
}
/////
///// 对齐选定的节点
/////
///// 对齐方式
//public void ArrangeNodes(ArrangeType arrangeType)
//{
// this._itemManager.ArrangeNodes(arrangeType);
//}
/////
///// 顶部对齐所有选中的节点
/////
//public void ArrangeNodesTop()
//{
// this._itemManager.ArrangeNodesTop();
//}
/////
///// 底部对齐所有选中的节点
/////
//public void ArrangeNodesBottom()
//{
// this._itemManager.ArrangeNodesBottom();
//}
/////
///// 左侧对齐所有选中的节点
/////
//public void ArrangeNodesLeft()
//{
// this._itemManager.ArrangeNodesLeft();
//}
/////
///// 右侧对齐所有选中的节点
/////
//public void ArrangeNodesRight()
//{
// this._itemManager.ArrangeNodesRight();
//}
/////
///// 垂直方向中心对齐所有选中的节点
/////
//public void ArrangeNodesVerticalCenter()
//{
// this._itemManager.ArrangeNodesVerticalCenter();
//}
/////
///// 水平方向中心对齐所有选中的节点
/////
//public void ArrangeNodesHorizontalCenter()
//{
// this._itemManager.ArrangeNodesHorizontalCenter();
//}
#endregion 操作项目
#region 流程校验
///
/// 不完整的线
///
private List _incompleteLines = new List();
///
/// 全部线
///
private List _checkedLines = new List();
///
/// 独立的节点
///
private List _aloneNodes = new List();
///
/// 开始节点(包括前置节点是可以跳过的)
///
private List _beginNodes = new List();
///
/// 结束节点(包括后置节点是可以跳过的)
///
private List _endNodes = new List();
///
/// 中间节点
///
private List _generalNodes = new List();
///
/// 全部节点
///
private List _checkedNodes = new List();
///
/// 不完整的线(CheckFlow调用后)
///
public List IncompleteLines
{
get
{
return this._incompleteLines;
}
}
///
/// 全部线(CheckFlow调用后)
///
public List CheckedLines
{
get
{
return this._checkedLines;
}
}
///
/// 独立的节点(CheckFlow调用后)
///
public List AloneNodes
{
get
{
return this._aloneNodes;
}
}
///
/// 开始节点(包括前置节点是可以跳过的)(CheckFlow调用后)
///
public List BeginNodes
{
get
{
return this._beginNodes;
}
}
///
/// 结束节点(包括前置节点是可以跳过的)(CheckFlow调用后)
///
public List EndNodes
{
get
{
return this._endNodes;
}
}
///
/// 中间节点(CheckFlow调用后)
///
public List GeneralNodes
{
get
{
return this._generalNodes;
}
}
///
/// 全部节点(CheckFlow调用后)
///
public List CheckedNodes
{
get
{
return this._checkedNodes;
}
}
///
/// 校验流程
///
///
public bool CheckFlow()
{
this._incompleteLines.Clear();
this._checkedLines.Clear();
this._beginNodes.Clear();
this._endNodes.Clear();
this._generalNodes.Clear();
this._checkedNodes.Clear();
//this.ErrorNodes.Clear();
//this.ErrorMessages.Clear();
bool checkResult = true;
foreach (FlowItem item in this.Items)
{
// 不显示无效节点 2024-11-27 by chenxy
if (!item.IsShow)
{
continue;
}
if (item is FlowLine)
{
FlowLine line = item as FlowLine;
if (line.AnchorBegin == AnchorKind.None ||
line.AnchorEnd == AnchorKind.None)
{
this._incompleteLines.Add(line);
}
this._checkedLines.Add(line);
}
if (item is FlowNode)
{
FlowNode node = item as FlowNode;
node.PreNodes.Clear();
node.NextNodes.Clear();
this._checkedNodes.Add(node);
// 后续节点
this.SetNextNodes(node, null);
// 前置节点
this.SetPreNodes(node, null);
if (node.NodeType == FlowNodeType.Begin)
{
node.CheckedNodeType = FlowNodeType.Begin;
this._beginNodes.Add(node);
}
else if (node.NodeType == FlowNodeType.End)
{
node.CheckedNodeType = FlowNodeType.End;
this._endNodes.Add(node);
if (node.CanSkip)
{
checkResult = false;
//this.ErrorMessages.Add("结束节点不能跳过");
}
}
else if (node.NodeType == FlowNodeType.Alone)
{
node.CheckedNodeType = FlowNodeType.Alone;
this._aloneNodes.Add(node);
}
//else
{
bool isBegin = false;
bool isEnd = false;
foreach (FlowNode preNode in node.PreNodes)
{
if (preNode.NodeType == FlowNodeType.Begin &&
preNode.CanSkip)
{
isBegin = true;
break;
}
}
foreach (FlowNode nextNode in node.NextNodes)
{
if (nextNode.NodeType == FlowNodeType.End &&
nextNode.CanSkip)
{
isEnd = true;
break;
}
}
if (isBegin && isEnd)
{
node.CheckedNodeType = FlowNodeType.Alone;
this._aloneNodes.Add(node);
}
else if (isBegin)
{
node.CheckedNodeType = FlowNodeType.Begin;
this._beginNodes.Add(node);
}
else if (isEnd)
{
node.CheckedNodeType = FlowNodeType.End;
this._endNodes.Add(node);
}
else
{
node.CheckedNodeType = FlowNodeType.General;
this._generalNodes.Add(node);
}
}
}
}
if (this._incompleteLines.Count > 0)
{
checkResult = false;
//this.ErrorMessages.Add("有未完成的连接线");
}
if (this._beginNodes.Count == 0)
{
checkResult = false;
//this.ErrorMessages.Add("没有开始节点");
}
if (this._endNodes.Count == 0)
{
checkResult = false;
//this.ErrorMessages.Add("没有结束节点");
}
return checkResult;
}
#endregion 流程校验
#region 保存、读取
///
/// 清空流程
///
public void ClearFlow()
{
//if (this._flowBoxMode != FlowBoxMode.Edit)
//{
// return;
//}
this._flowName = null;
this._itemManager = new ItemManager(this, this.canvasBox);
//this.canvasBox.SetCanvasSize(Consts.CANVAS_SIZE_DEFAULT);
//this.canvasBox.CanvasControl.BackgroundImage = new Bitmap(this.GetType(), "Images.backImage1.gif");
this._itemManager.RefreshItems();
}
///
/// 保存流程(1.1)
///
/// 二进制
public byte[] SaveFlow()
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return null;
}
using (MemoryStream memoryStream = new MemoryStream())
{
if (this.SaveFlow(memoryStream))
{
return memoryStream.ToArray();
}
}
return null;
}
///
/// 保存流程(1.1)
///
/// 流
/// 是否成功
public bool SaveFlow(Stream stream)
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return false;
}
if (stream == null)
{
return false;
}
try
{
XmlDocument xmlDoc = this.SaveFlowXmlDoc();
if (xmlDoc != null)
{
xmlDoc.Save(stream);
return true;
}
return false;
}
catch
{
return false;
}
}
///
/// 保存流程(1.1)
///
/// XML
public string SaveFlowXml()
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return null;
}
XmlDocument xmlDoc = this.SaveFlowXmlDoc();
return xmlDoc.OuterXml;
}
///
/// 保存流程(1.1)
///
/// XML
public XmlDocument SaveFlowXmlDoc()
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return null;
}
return this.SaveFlowXmlDoc_1_1();
}
///
/// 加载流程
///
/// 二进制
/// 是否成功
public bool LoadFlow(byte[] bytes)
{
if (bytes != null && 0 < bytes.Length)
{
using (MemoryStream memoryStream = new MemoryStream(bytes))
{
memoryStream.Position = 0;
return this.LoadFlow(memoryStream);
}
}
return false;
}
///
/// 加载流程
///
/// 流
/// 是否成功
public bool LoadFlow(Stream stream)
{
//this.ClearFlow();
this._itemManager = new ItemManager(this, this.canvasBox);
if (stream == null)
{
this._itemManager.RefreshItems();
return false;
}
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(stream);
// 如果要改图里的东西,在这改,再保存。
//xmlDoc.Load("C:\\Users\\Administrator\\流程图.txt");
bool result = this.LoadFlowByVersion(xmlDoc);
this._itemManager.RefreshItems();
return result;
/* 读取xml异常时,将流程xml保存本地后直接读取本地文件,然后再输出导入到db中
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("D:\\yyy");
bool result = this.LoadFlowByVersion(xmlDoc);
File.WriteAllText("D:\\www", this.SaveFlowXml());
*/
}
catch
{
this._itemManager.RefreshItems();
return false;
}
}
///
/// 加载流程
///
/// xml
/// 是否成功
public bool LoadFlow(string xml)
{
//this.ClearFlow();
this._itemManager = new ItemManager(this, this.canvasBox);
if (string.IsNullOrWhiteSpace(xml))
{
this._itemManager.RefreshItems();
return false;
}
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
bool result = this.LoadFlowByVersion(xmlDoc);
this._itemManager.RefreshItems();
return result;
}
catch
{
this._itemManager.RefreshItems();
return false;
}
}
#endregion 保存、读取
#endregion 公有方法
#region 内部方法
#endregion 内部方法
#region 受保护方法
#endregion 受保护方法
#region 私有方法
#region 事件相关
///
/// 获取节点双击的注册事件
///
///
private NodeDoubleClickEventHandler GetNodeDoubleClickEventHandler()
{
if (this._flowBoxMode < FlowBoxMode.LimitEdit)
{
return null;
}
return (NodeDoubleClickEventHandler)base.Events[FlowBox.EventNodeDoubleClick];
}
///
/// 流程节点加载时事件
///
///
private FlowNodeLoadingEventHandler GetFlowNodeLoadingEventHandler()
{
return (FlowNodeLoadingEventHandler)base.Events[FlowBox.EventFlowNodeLoading];
}
#endregion 事件相关
#region 流程校验
///
/// 设置前置节点
///
/// 需要设置的节点
/// 前置节点集合
private void SetPreNodes(FlowNode node, List preNodes)
{
// 不显示无效节点 2024-11-27 by chenxy
if (!node.IsShow)
{
return;
}
preNodes = (preNodes == null) ? node.PreNodes : preNodes;
foreach (FlowLine inLine in node.InLines)
{
if (inLine.AnchorBegin != AnchorKind.None)
{
FlowNode preNode = inLine.NodeBegin;
if (preNode != null && !preNodes.Contains(preNode))
{
preNodes.Add(preNode);
if (preNode.CanSkip)
{
this.SetPreNodes(preNode, preNodes);
}
}
}
}
}
///
/// 设置后续节点
///
/// 需要设置的节点
/// 后续节点集合
private void SetNextNodes(FlowNode node, List nextNodes)
{
// 不显示无效节点 2024-11-27 by chenxy
if (!node.IsShow)
{
return;
}
nextNodes = (nextNodes == null) ? node.NextNodes : nextNodes;
foreach (FlowLine outLine in node.OutLines)
{
if (outLine.AnchorEnd != AnchorKind.None)
{
FlowNode nextNode = outLine.NodeEnd;
if (nextNode != null && !nextNodes.Contains(nextNode))
{
nextNodes.Add(nextNode);
if (nextNode.CanSkip)
{
this.SetNextNodes(nextNode, nextNodes);
}
}
}
}
}
#endregion 流程校验
#region 保存、读取
///
/// 保存流程(1.1)
///
/// XML
private XmlDocument SaveFlowXmlDoc_1_1()
{
XmlDocument xmlDoc = new XmlDocument();
// 创建Xml声明部分,即
xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null));
// 根节点
XmlNode root = xmlDoc.CreateElement("FlowSetting");
// 版本
XmlAttribute version = xmlDoc.CreateAttribute("Version");
version.Value = "1.1";
root.Attributes.Append(version);
// 编码
XmlAttribute managerCode = xmlDoc.CreateAttribute("ManagerCode");
managerCode.Value = this._itemManager.ManagerCode;
root.Attributes.Append(managerCode);
// 新项目ID
//XmlNode newItemID = xmlDoc.CreateElement("NewItemID");
//newItemID.AppendChild(xmlDoc.CreateTextNode(this._itemManager.GetNewItemID().ToString()));
//root.AppendChild(newItemID);
XmlAttribute newItemID = xmlDoc.CreateAttribute("NewItemID");
newItemID.Value = this._itemManager.GetNewItemID().ToString();
root.Attributes.Append(newItemID);
// 流程名称
XmlNode flowName = xmlDoc.CreateElement("FlowName");
flowName.AppendChild(xmlDoc.CreateCDataSection(this._flowName));
root.AppendChild(flowName);
// 画布大小
XmlNode canvasSize = xmlDoc.CreateElement("CanvasSize");
canvasSize.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(this.CanvasSize)));
root.AppendChild(canvasSize);
//// 画布背景
//XmlNode backgroundImage = xmlDoc.CreateElement("BackgroundImage");
//backgroundImage.Value = Converter.ToXMLString(this.CanvasBox.CanvasBackgroundImage);
//backgroundImage.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(this.CanvasBox.CanvasBackgroundImage)));
//flowNode.AppendChild(backgroundImage);
// FlowItems
XmlNode flowItems = xmlDoc.CreateElement("FlowItems");
foreach (FlowItem item in this._itemManager.Items)
{
XmlNode flowItem = xmlDoc.CreateElement("FlowItem");
// ItemID
XmlAttribute itemID = xmlDoc.CreateAttribute("ItemID");
itemID.Value = item.ItemID.ToString();
flowItem.Attributes.Append(itemID);
// OnlyCode
XmlAttribute itemCode = xmlDoc.CreateAttribute("ItemCode");
itemCode.Value = item.ItemCode;
flowItem.Attributes.Append(itemCode);
// ItemType
XmlAttribute itemType = xmlDoc.CreateAttribute("ItemType");
itemType.Value = item.GetType().Name;
flowItem.Attributes.Append(itemType);
// ID
XmlNode id = xmlDoc.CreateElement("ID");
id.AppendChild(xmlDoc.CreateTextNode(item.ID.ToString()));
flowItem.AppendChild(id);
// Code
XmlNode code = xmlDoc.CreateElement("Code");
code.AppendChild(xmlDoc.CreateCDataSection(item.Code));
flowItem.AppendChild(code);
// Name
XmlNode name = xmlDoc.CreateElement("Name");
name.AppendChild(xmlDoc.CreateCDataSection(item.Name));
flowItem.AppendChild(name);
// Remark
XmlNode remark = xmlDoc.CreateElement("Remark");
remark.AppendChild(xmlDoc.CreateCDataSection(item.Remark));
flowItem.AppendChild(remark);
// ShowName
XmlNode showName = xmlDoc.CreateElement("ShowName");
showName.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(item.ShowName)));
flowItem.AppendChild(showName);
// Font
XmlNode font = xmlDoc.CreateElement("Font");
font.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(item.Font)));
flowItem.AppendChild(font);
// FontColor
XmlNode fontColor = xmlDoc.CreateElement("FontColor");
fontColor.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(item.FontColor)));
flowItem.AppendChild(fontColor);
// TagSerializable todo object
XmlNode ts = xmlDoc.CreateElement("TS");
if (item.TagSerializable != null)
{
using (MemoryStream memoryStream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, item.TagSerializable);
ts.AppendChild(xmlDoc.CreateTextNode(Convert.ToBase64String(memoryStream.ToArray())));
}
}
flowItem.AppendChild(ts);
if (item is FlowNode)
{
FlowNode node = item as FlowNode;
// Bounds
XmlNode bounds = xmlDoc.CreateElement("Bounds");
bounds.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.Bounds)));
flowItem.AppendChild(bounds);
// BorderWidth
XmlNode borderWidth = xmlDoc.CreateElement("BorderWidth");
borderWidth.AppendChild(xmlDoc.CreateTextNode(node.BorderWidth.ToString()));
flowItem.AppendChild(borderWidth);
// BorderColor
XmlNode borderColor = xmlDoc.CreateElement("BorderColor");
borderColor.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.BorderColor)));
flowItem.AppendChild(borderColor);
// FillColor
XmlNode fillColor = xmlDoc.CreateElement("FillColor");
if (node.FillColor.HasValue)
{
fillColor.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.FillColor)));
}
flowItem.AppendChild(fillColor);
// CanSkip
XmlNode canSkip = xmlDoc.CreateElement("CanSkip");
canSkip.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.CanSkip)));
flowItem.AppendChild(canSkip);
// NodeImageType
XmlNode nodeImageType = xmlDoc.CreateElement("NodeImageType");
if (node.NodeImageType.HasValue)
{
nodeImageType.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.NodeImageType)));
}
flowItem.AppendChild(nodeImageType);
// NodeImage
XmlNode nodeImage = xmlDoc.CreateElement("NodeImage");
if (!node.NodeImageType.HasValue && node.NodeImage != null)
{
nodeImage.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.NodeImage)));
}
flowItem.AppendChild(nodeImage);
}
if (item is FlowLine)
{
FlowLine line = item as FlowLine;
// PointBegin
XmlNode pointBegin = xmlDoc.CreateElement("PointBegin");
pointBegin.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(line.PointBegin)));
flowItem.AppendChild(pointBegin);
// PointEnd
XmlNode pointEnd = xmlDoc.CreateElement("PointEnd");
pointEnd.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(line.PointEnd)));
flowItem.AppendChild(pointEnd);
// LineColor
XmlNode lineColor = xmlDoc.CreateElement("LineColor");
lineColor.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(line.LineColor)));
flowItem.AppendChild(lineColor);
// LineWidth
XmlNode lineWidth = xmlDoc.CreateElement("LineWidth");
lineWidth.AppendChild(xmlDoc.CreateTextNode(line.LineWidth.ToString()));
flowItem.AppendChild(lineWidth);
// AnchorBegin
XmlNode anchorBegin = xmlDoc.CreateElement("AnchorBegin");
if (line.NodeBegin == null)
{
line.AnchorBegin = AnchorKind.None;
}
else
{
anchorBegin.AppendChild(xmlDoc.CreateTextNode(line.NodeBegin.ItemCode));
}
XmlAttribute kindBegin = xmlDoc.CreateAttribute("Kind");
kindBegin.Value = Converter.ToXMLString(line.AnchorBegin);
anchorBegin.Attributes.Append(kindBegin);
flowItem.AppendChild(anchorBegin);
// AnchorEnd
XmlNode anchorEnd = xmlDoc.CreateElement("AnchorEnd");
if (line.NodeEnd == null)
{
line.AnchorEnd = AnchorKind.None;
}
else
{
anchorEnd.AppendChild(xmlDoc.CreateTextNode(line.NodeEnd.ItemCode));
}
XmlAttribute kindEnd = xmlDoc.CreateAttribute("Kind");
kindEnd.Value = Converter.ToXMLString(line.AnchorEnd);
anchorEnd.Attributes.Append(kindEnd);
flowItem.AppendChild(anchorEnd);
}
flowItems.AppendChild(flowItem);
}
root.AppendChild(flowItems);
xmlDoc.AppendChild(root);
return xmlDoc;
}
///
/// 根据文档版本加载流程
///
/// xml
/// 是否成功
private bool LoadFlowByVersion(XmlDocument xmlDoc)
{
bool result = false;
// 根节点
XmlNode root = xmlDoc.DocumentElement;
if (root == null)
{
return result;
}
if ("WorkFlow" == root.Name)
{
this._loadVersion = new Version(1, 0);
this.LoadFlow_1_0(root);
result = true;
}
else if ("FlowSetting" == root.Name)
{
// 版本
string version = root.Attributes["Version"].Value;
switch (version)
{
case "1.1":
this._loadVersion = new Version(1, 1);
this.LoadFlow_1_1(root);
result = true;
break;
default:
break;
}
}
return result;
}
///
/// 加载流程(1.0)
///
/// XML
private void LoadFlow_1_0(XmlNode root)
{
int itemCount = 0;
//获取结点列表
XmlNodeList xmlNodeChilds = root.SelectNodes("//arrNodeList//node");
foreach (XmlNode xmlNode in xmlNodeChilds)
{
itemCount++;
XmlNodeList xnl = xmlNode.ChildNodes;
int index = Convert.ToInt32(xmlNode.Attributes.Item(0).InnerText);
int nodetype = Convert.ToInt32(xmlNode.Attributes.Item(1).InnerText);
//itemCount = Math.Max(itemCount, index);
FlowNode node = new FlowNode(this._itemManager, index, Guid.NewGuid().ToString().ToUpper());
node.NodeImageType = nodetype;
node.Name = xnl.Item(0).InnerText;
string fontname = xnl.Item(1).InnerText;
int fontSize = Convert.ToInt32(xnl.Item(2).InnerText);
node.Font = new System.Drawing.Font(fontname, fontSize);
node.FontColor = System.Drawing.Color.FromArgb(int.Parse(xnl.Item(3).InnerText));
node.BorderWidth = 0;
node.BorderColor = Color.FromArgb(int.Parse(xnl.Item(4).InnerText));
node.FillColor = Color.FromArgb(int.Parse(xnl.Item(5).InnerText));
int height = Convert.ToInt32(xnl.Item(6).InnerText);
int width = Convert.ToInt32(xnl.Item(7).InnerText);
int x = Convert.ToInt32(xnl.Item(8).InnerText);
int y = Convert.ToInt32(xnl.Item(9).InnerText);
node.Bounds = new Rectangle(x, y, width, height);
node.Remark = xnl.Item(17).InnerText;
FlowNodeLoadingEventHandler flowNodeLoading = this.GetFlowNodeLoadingEventHandler();
if (flowNodeLoading != null)
{
flowNodeLoading(this, new NodeEventArgs(node));
}
this._itemManager.Items.Add(node);
this._itemManager.AllNodes.Add(node);
}
//获取线列表
XmlNodeList xmlLineChilds = root.SelectNodes("//arrLineList//line");
foreach (XmlNode xmlLine in xmlLineChilds)
{
XmlNodeList xnl = xmlLine.ChildNodes;
int index = Convert.ToInt32(xmlLine.Attributes.Item(0).InnerText);
int lineType = Convert.ToInt32(xmlLine.Attributes.Item(1).InnerText);
FlowLine line = new FlowLine(this._itemManager, ++itemCount, Guid.NewGuid().ToString().ToUpper());
int x0 = Convert.ToInt32(xnl.Item(0).InnerText);
int y0 = Convert.ToInt32(xnl.Item(1).InnerText);
int x1 = Convert.ToInt32(xnl.Item(2).InnerText);
int y1 = Convert.ToInt32(xnl.Item(3).InnerText);
line.PointBegin = new Point(x0, y0);
line.PointEnd = new Point(x1, y1);
if (lineType == 1)
{
//line.X2 = Convert.ToInt32(xnl.Item(4).InnerText);
//line.Y2 = Convert.ToInt32(xnl.Item(5).InnerText);
//line.X3 = Convert.ToInt32(xnl.Item(6).InnerText);
//line.Y3 = Convert.ToInt32(xnl.Item(7).InnerText);
//line.LineNodeCount = Convert.ToInt32(xnl.Item(8).InnerText);
if (xnl.Item(9).InnerText != "null")
{
int firstIndex = Convert.ToInt32(xnl.Item(9).InnerText);
line.NodeBegin = this._itemManager.Items[firstIndex] as FlowNode;
if (line.NodeBegin != null)
{
line.NodeBegin.OutLines.Add(line);
int index1 = Convert.ToInt32(xnl.Item(11).InnerText);
switch (index1)
{
case 0:
line.AnchorBegin = AnchorKind.Top;
line.NodeBegin.TopLines.Add(line);
break;
case 1:
line.AnchorBegin = AnchorKind.Left;
line.NodeBegin.LeftLines.Add(line);
break;
case 2:
line.AnchorBegin = AnchorKind.Right;
line.NodeBegin.RightLines.Add(line);
break;
case 3:
line.AnchorBegin = AnchorKind.Bottom;
line.NodeBegin.BottomLines.Add(line);
break;
default:
break;
}
}
}
if (xnl.Item(10).InnerText != "null")
{
int secondIndex = Convert.ToInt32(xnl.Item(10).InnerText);
line.NodeEnd = this._itemManager.Items[secondIndex] as FlowNode;
if (line.NodeEnd != null)
{
line.NodeEnd.InLines.Add(line);
int index2 = Convert.ToInt32(xnl.Item(12).InnerText);
switch (index2)
{
case 0:
line.AnchorEnd = AnchorKind.Top;
line.NodeEnd.TopLines.Add(line);
break;
case 1:
line.AnchorEnd = AnchorKind.Left;
line.NodeEnd.LeftLines.Add(line);
break;
case 2:
line.AnchorEnd = AnchorKind.Right;
line.NodeEnd.RightLines.Add(line);
break;
case 3:
line.AnchorEnd = AnchorKind.Bottom;
line.NodeEnd.BottomLines.Add(line);
break;
default:
break;
}
}
}
line.LineWidth = Convert.ToInt32(xnl.Item(13).InnerText);
line.LineColor = System.Drawing.Color.FromArgb(int.Parse(xnl.Item(14).InnerText));
line.Name = xnl.Item(15).InnerText;
}
else if (lineType == 0)
{
//line.LineNodeCount = Convert.ToInt32(xnl.Item(4).InnerText);
if (xnl.Item(5).InnerText != "null")
{
int firstIndex = Convert.ToInt32(xnl.Item(5).InnerText);
line.NodeBegin = this._itemManager.Items[firstIndex] as FlowNode;
if (line.NodeBegin != null)
{
line.NodeBegin.OutLines.Add(line);
int index3 = Convert.ToInt32(xnl.Item(7).InnerText);
switch (index3)
{
case 0:
line.AnchorBegin = AnchorKind.Top;
line.NodeBegin.TopLines.Add(line);
break;
case 1:
line.AnchorBegin = AnchorKind.Left;
line.NodeBegin.LeftLines.Add(line);
break;
case 2:
line.AnchorBegin = AnchorKind.Right;
line.NodeBegin.RightLines.Add(line);
break;
case 3:
line.AnchorBegin = AnchorKind.Bottom;
line.NodeBegin.BottomLines.Add(line);
break;
default:
break;
}
}
}
if (xnl.Item(6).InnerText != "null")
{
int secondIndex = Convert.ToInt32(xnl.Item(6).InnerText);
line.NodeEnd = this._itemManager.Items[secondIndex] as FlowNode;
if (line.NodeEnd != null)
{
line.NodeEnd.InLines.Add(line);
int index4 = Convert.ToInt32(xnl.Item(8).InnerText);
switch (index4)
{
case 0:
line.AnchorEnd = AnchorKind.Top;
line.NodeEnd.TopLines.Add(line);
break;
case 1:
line.AnchorEnd = AnchorKind.Left;
line.NodeEnd.LeftLines.Add(line);
break;
case 2:
line.AnchorEnd = AnchorKind.Right;
line.NodeEnd.RightLines.Add(line);
break;
case 3:
line.AnchorEnd = AnchorKind.Bottom;
line.NodeEnd.BottomLines.Add(line);
break;
default:
break;
}
}
}
line.LineWidth = Convert.ToInt32(xnl.Item(9).InnerText);
line.LineColor = System.Drawing.Color.FromArgb(int.Parse(xnl.Item(10).InnerText));
line.Name = xnl.Item(11).InnerText;
}
this._itemManager.Items.Add(line);
}
// 新项目ID
this._itemManager.SetNewItemID(itemCount);
// 画布大小
this.canvasBox.SetCanvasSize(Consts.CANVAS_SIZE_DEFAULT);
}
///
/// 加载流程(1.1)
///
/// XML
private void LoadFlow_1_1(XmlNode root)
{
//// 根节点
//XmlNode flowSetting = xmlDoc.SelectSingleNode("FlowSetting");
//// 版本
//string version = flowSetting.Attributes["Version"].Value;
// 编码
this._itemManager.ManagerCode = root.Attributes["ManagerCode"].Value;
// 新项目ID
//this._itemManager.SetNewItemID(Convert.ToInt32(root.SelectSingleNode("NewItemID").InnerText));
this._itemManager.SetNewItemID(Convert.ToInt32(root.Attributes["NewItemID"].Value));
// 流程名称
this._flowName = root.SelectSingleNode("FlowName").InnerText;
// 画布大小
this.canvasBox.SetCanvasSize(Converter.ToObject(root.SelectSingleNode("CanvasSize").InnerText));
//// 画布背景
//XmlNode backgroundImage = flowSetting.SelectSingleNode("BackgroundImage");
//this.canvasBox.CanvasControl.BackgroundImage = Converter.ToImage(backgroundImage.InnerText);
// FlowItems
XmlNode flowItems = root.SelectSingleNode("FlowItems");
foreach (XmlNode item in flowItems.ChildNodes)
{
int itemID = Convert.ToInt32(item.Attributes["ItemID"].Value);
string itemCode = item.Attributes["ItemCode"].Value;
string itemType = item.Attributes["ItemType"].Value;
object ts = null;
XmlNode tsXmlNode = item.SelectSingleNode("TS");
if (tsXmlNode != null && !string.IsNullOrWhiteSpace(tsXmlNode.InnerText))
{
byte[] bytes = Convert.FromBase64String(tsXmlNode.InnerText);
using (MemoryStream memoryStream = new MemoryStream(bytes))
{
BinaryFormatter formatter = new BinaryFormatter();
ts = formatter.Deserialize(memoryStream);
}
}
if (typeof(FlowNode).Name == itemType)
{
FlowNode node = new FlowNode(this._itemManager, itemID, itemCode);
node.ID = Convert.ToInt32(item.SelectSingleNode("ID").InnerText);
node.Code = item.SelectSingleNode("Code").InnerText;
node.Name = item.SelectSingleNode("Name").InnerText;
node.Remark = item.SelectSingleNode("Remark").InnerText;
node.ShowName = Converter.ToObject(item.SelectSingleNode("ShowName").InnerText);
node.Font = Converter.ToObject(item.SelectSingleNode("Font").InnerText);
node.FontColor = Converter.ToObject(item.SelectSingleNode("FontColor").InnerText);
node.TagSerializable = ts;
node.Bounds = Converter.ToObject(item.SelectSingleNode("Bounds").InnerText);
node.BorderWidth = Convert.ToInt32(item.SelectSingleNode("BorderWidth").InnerText);
node.BorderColor = Converter.ToObject(item.SelectSingleNode("BorderColor").InnerText);
node.FillColor = Converter.ToObject(item.SelectSingleNode("FillColor").InnerText);
node.CanSkip = Converter.ToObject(item.SelectSingleNode("CanSkip").InnerText);
node.NodeImageType = Converter.ToObject(item.SelectSingleNode("NodeImageType").InnerText);
if (!node.NodeImageType.HasValue)
{
node.NodeImage = Converter.ToImage(item.SelectSingleNode("NodeImage").InnerText);
}
FlowNodeLoadingEventHandler flowNodeLoading = this.GetFlowNodeLoadingEventHandler();
if (flowNodeLoading != null)
{
flowNodeLoading(this, new NodeEventArgs(node));
}
this._itemManager.Items.Add(node);
this._itemManager.AllNodes.Add(node);
continue;
}
if (typeof(FlowLine).Name == itemType)
{
FlowLine line = new FlowLine(this._itemManager, itemID, itemCode);
line.ID = Convert.ToInt32(item.SelectSingleNode("ID").InnerText);
line.Code = item.SelectSingleNode("Code").InnerText;
line.Name = item.SelectSingleNode("Name").InnerText;
line.Remark = item.SelectSingleNode("Remark").InnerText;
line.ShowName = Converter.ToObject(item.SelectSingleNode("ShowName").InnerText);
line.Font = Converter.ToObject(item.SelectSingleNode("Font").InnerText);
line.FontColor = Converter.ToObject(item.SelectSingleNode("FontColor").InnerText);
line.TagSerializable = ts;
line.PointBegin = Converter.ToObject(item.SelectSingleNode("PointBegin").InnerText);
line.PointEnd = Converter.ToObject(item.SelectSingleNode("PointEnd").InnerText);
line.LineColor = Converter.ToObject(item.SelectSingleNode("LineColor").InnerText);
line.LineWidth = Convert.ToInt32(item.SelectSingleNode("LineWidth").InnerText);
XmlNode anchorBegin = item.SelectSingleNode("AnchorBegin");
line.AnchorBegin = Converter.ToObject(anchorBegin.Attributes["Kind"].Value);
if (line.AnchorBegin != AnchorKind.None)
{
line.NodeCodeBegin = anchorBegin.InnerText;
}
XmlNode anchorEnd = item.SelectSingleNode("AnchorEnd");
line.AnchorEnd = Converter.ToObject(anchorEnd.Attributes["Kind"].Value);
if (line.AnchorEnd != AnchorKind.None)
{
line.NodeCodeEnd = anchorEnd.InnerText;
}
this._itemManager.Items.Add(line);
continue;
}
}
// 连接
foreach (FlowItem item in this._itemManager.Items)
{
this.SetLineToNodeFromXml(item as FlowLine);
}
}
///
/// 从xml加载流程后,把line链接到node上。
///
/// 线段
private void SetLineToNodeFromXml(FlowLine line)
{
if (line == null)
{
return;
}
bool hasC1 = false;
bool hasC2 = false;
if (line.AnchorBegin != AnchorKind.None || line.AnchorEnd != AnchorKind.None)
{
foreach (FlowItem item in this._itemManager.Items)
{
FlowNode node = item as FlowNode;
if (node == null)
{
continue;
}
if (line.AnchorBegin != AnchorKind.None && node.ItemCode == line.NodeCodeBegin)
{
hasC1 = true;
line.NodeBegin = node;
node.OutLines.Add(line);
switch (line.AnchorBegin)
{
case AnchorKind.Top:
node.TopLines.Add(line);
break;
case AnchorKind.Left:
node.LeftLines.Add(line);
break;
case AnchorKind.Right:
node.RightLines.Add(line);
break;
case AnchorKind.Bottom:
node.BottomLines.Add(line);
break;
default:
break;
}
}
if (line.AnchorEnd != AnchorKind.None && node.ItemCode == line.NodeCodeEnd)
{
hasC2 = true;
line.NodeEnd = node;
node.InLines.Add(line);
switch (line.AnchorEnd)
{
case AnchorKind.Top:
node.TopLines.Add(line);
break;
case AnchorKind.Left:
node.LeftLines.Add(line);
break;
case AnchorKind.Right:
node.RightLines.Add(line);
break;
case AnchorKind.Bottom:
node.BottomLines.Add(line);
break;
default:
break;
}
}
}
if (!hasC1)
{
line.AnchorBegin = AnchorKind.None;
}
if (!hasC2)
{
line.AnchorEnd = AnchorKind.None;
}
}
}
#endregion 保存、读取
#endregion 私有方法
#region 事件声明
///
/// 双击流程节点事件
///
public event NodeDoubleClickEventHandler NodeDoubleClick
{
add
{
base.Events.AddHandler(FlowBox.EventNodeDoubleClick, value);
}
remove
{
base.Events.RemoveHandler(FlowBox.EventNodeDoubleClick, value);
}
}
///
/// 流程节点加载时事件
///
public event FlowNodeLoadingEventHandler FlowNodeLoading
{
add
{
base.Events.AddHandler(FlowBox.EventFlowNodeLoading, value);
}
remove
{
base.Events.RemoveHandler(FlowBox.EventFlowNodeLoading, value);
}
}
#endregion 事件声明
#region 键盘事件
///
/// 键盘事件
///
///
///
private void keyControl_KeyDown(object sender, KeyEventArgs e)
{
if (this._flowBoxMode == FlowBoxMode.Display)
{
return;
}
switch(e.KeyCode)
{
case Keys.Escape:
//this._itemManager.StopDrawingItem();
break;
case Keys.Up:
this._itemManager.MoveSelectedItems(0, -1);
break;
case Keys.Left:
this._itemManager.MoveSelectedItems(-1, 0);
break;
case Keys.Right:
this._itemManager.MoveSelectedItems(1, 0);
break;
case Keys.Down:
this._itemManager.MoveSelectedItems(0, 1);
break;
default:
return;
}
this._itemManager.RefreshItems();
}
private void contextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
}
private void tsmiAllSelect_Click(object sender, EventArgs e)
{
this.SelectAllItem();
}
private void tsmiDelete_Click(object sender, EventArgs e)
{
this.DeleteSelectedItem();
}
#endregion 键盘事件
}
}