using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace Dongke.IBOSS.Basics.FlowSetting { /// /// 流程项目绘制管理器 /// internal class ItemManager { #region 成员变量 /// /// 流程项目自增ID /// private int _newItemID = 0; /// /// 管理器编码 /// private string _managerCode = Guid.NewGuid().ToString(); /// /// 画板 /// private CanvasBox _canvasBox = null; /// /// 流程设计器 /// private FlowBox _flowBox = null; /// /// 画布控件 /// private Control _canvasControl = null; /// /// 流程编辑模式 /// private FlowBoxMode _flowBoxMode = FlowBoxMode.Edit; #region 项目集合 // todo 自定义 list 管理 外部不能add,remove只能get,可以通过,itemid,onlycode,itemindex(显示顺序)取得。 /// /// 全部流程项目 /// private List _items = new List(); /// /// 选中的流程项目 /// private List _selectedItems = new List(); ///// ///// 删除的流程项目 ///// //private List _deletedItems = new List(); ///// ///// 选中的流程节点 ///// //private List _selectedNodes = new List(); /// /// 全部流程节点 /// private List _allNodes = new List(); /// /// 删除的流程项目 /// private List _deletedNodes = new List(); #endregion 项目集合 #region 新建项目 /// /// 鼠标操作,指定位置,新建Item /// private FlowItem _drawingItem = null; /// /// 鼠标操作,指定位置,新建节点 /// private FlowNode _drawingNode = null; /// /// 鼠标操作,指定位置,新建线段 /// private FlowLine _drawingLine = null; #endregion 新建项目 #region 鼠标操作 /// /// 鼠标动作 /// private MouseOperatingType _mouseOperatingType = MouseOperatingType.None; /// /// 鼠标框选范围 /// private Rectangle _mouseSelectRect = Rectangle.Empty; /// /// 鼠标按下的点 /// private Point _mouseDownPoint = Point.Empty; /// /// 鼠标移动的点 /// private Point _mouseMovePoint = Point.Empty; /// /// 鼠标抬起的点 /// private Point _mouseUpPoint = Point.Empty; /// /// 鼠标是否按下 /// private bool _isMouseDown = false; /// /// 鼠标是否移动 /// private bool _isMouseMove = false; /// /// 鼠标是否抬起 /// private bool _isMouseUp = false; /// /// 进行改变大小操作的节点 /// private FlowNode _nodeSizeChanging = null; /// /// 进行改变大小操作的线段 /// private FlowLine _linePointChanging = null; /// /// 正在显示锚点的节点 /// private FlowNode _nodeAnchorShowing = null; #endregion 鼠标操作 #region 绘制项目 // TODO 使用后销毁?? /// /// 画节点笔 /// private Pen _penDrawNode = new Pen(Consts.NODE_BORDERCOLOR_DEFAULT); /// /// 画线段笔 /// private Pen _penDrawLine = new Pen(Consts.LINE_COLOR_DEFAULT, Consts.LINE_WIDTH_DEFAULT); /// /// 写字笔 /// private Pen _penDrawString = new Pen(Consts.FONT_COLOR_DEFAULT); #endregion 绘制项目 #endregion 成员变量 #region 构造函数 /// /// 构造函数 /// /// 流程设计器 /// 画板 internal ItemManager(FlowBox flowBox, CanvasBox canvasBox) { this._flowBox = flowBox; this._canvasBox = canvasBox; this._canvasControl = canvasBox.CanvasControl; this._flowBoxMode = flowBox.BoxMode; // 线段连接线 以圆点开始,箭头结束 AdjustableArrowCap myArrow = new AdjustableArrowCap(4, 4); CustomLineCap customArrow = myArrow; this._penDrawLine.CustomEndCap = myArrow; //this._penDrawLine.StartCap = LineCap.RoundAnchor; this.SetDefaultCursor(); } #endregion 构造函数 #region 属性 /// /// 获取全部流程项目 /// public List Items { get { return this._items; } } /// /// 获取选择的流程项目 /// public List SelectedItems { get { return this._selectedItems; } } /// /// 获取删除的节点 /// public List DeletedNodes { get { return this._deletedNodes; } } /// /// 获取全部的节点(包括删除的) /// public List AllNodes { get { return this._allNodes; } } /// /// 获取或设置管理器编码 /// internal string ManagerCode { get { return this._managerCode; } set { this._managerCode = value; } } /// /// 获取或设置流程编辑模式 /// internal FlowBoxMode BoxMode { get { return this._flowBoxMode; } set { this._flowBoxMode = value; } } /// /// 获取或设置新的itemID /// internal int NewItemID { get { return ++this._newItemID; } } /// /// 获取或设置画板的鼠标样式 /// private Cursor CanvasCursor { get { return this._canvasControl.Cursor; } set { this._canvasControl.Cursor = value; } } #endregion 属性 #region 公有方法 #region 新建项目 /// /// 停止新建节点(鼠标操作) /// public void StopDrawingItem() { this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; this.SetDefaultCursor(); } /// /// 新建节点(鼠标操作,指定位置) /// public FlowNode DrawingNode() { this._drawingNode = new FlowNode(this); this._drawingLine = null; this._drawingItem = this._drawingNode; this.SetDrawingNodeCursor(); return this._drawingNode; } /// /// 新建线段(鼠标操作,指定位置) /// public FlowLine DrawingLine() { this._drawingNode = null; this._drawingLine = new FlowLine(this); this._drawingItem = this._drawingLine; this.SetDrawingLineCursor(); return this._drawingLine; } /// /// 新建节点(默认位置) /// /// 节点 public FlowNode NewNode() { this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; return this.NewNodeInternal(null); } /// /// 新建节点(指定位置) /// /// 节点位置 public FlowNode NewNode(Point location) { this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; return this.NewNodeInternal(location); } /// /// 新建线段(默认位置) /// /// 线段 public FlowLine NewLine() { this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; return this.NewLineInternal(null, null); } /// /// 新建线段(指定位置) /// /// 起始点 /// 结束点 /// 线段 public FlowLine NewLine(Point pointBegin, Point pointEnd) { this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; return this.NewLineInternal(pointBegin, pointEnd); } #endregion 新建项目 #region 刷项目 ///// ///// 刷新未激活Item的图片 ///// //public void RefreshStaticItems() //{ // // 清除画布 // Graphics graphics = this._canvasBox.Canvas; // graphics.Clear(Color.Transparent); // // 绘制未激活的Item // this.DrawStaticItems(graphics); // // 设定未激活的Item为图片 // this._canvasBox.SetItemsImage(this._canvasBox.CanvasImage); //} ///// ///// 刷新激活Item的图片 ///// //public void RefreshActiveItems() //{ // // 清除画布 // Graphics graphics = this._canvasBox.Canvas; // graphics.Clear(Color.Transparent); // // 绘制激活的Item // this.DrawActiveItems(graphics); // // 设定未激活的Item为图片 // this._canvasBox.SetItemsImage(this._canvasBox.CanvasImage); //} ///// ///// 刷新激活Item ///// ///// //public void RefreshActiveItems(Graphics graphics) //{ // // todo 在paint绘制事件中绘制激活的item,未激活item作为背景 // // 绘制激活的Item // this.DrawActiveItems(graphics); //} /// /// 刷新Item的图片 /// public void RefreshItems() { // 清除画布 Graphics graphics = this._canvasBox.Canvas; graphics.Clear(Color.Transparent); // 绘制激活的Item this.DrawItems(graphics); // 设定未激活的Item为图片 this._canvasBox.SetItemsImage(this._canvasBox.CanvasImage); GC.Collect(); } #endregion 刷新项目 #region 操作项目 /// /// 全部不选择 /// public void ClearSelection() { foreach (FlowItem item in this._selectedItems) { item.MouseOperating = false; item.Selected = false; } this._selectedItems.Clear(); } /// /// 全部选择 /// public void SelectAllItems() { foreach (FlowItem item in this._items) { if (!item.Selected) { this._selectedItems.Add(item); item.Selected = true; } } } /// /// 删除全部项目 /// public void DeleteAllItems() { foreach (FlowItem item in this._items) { item.MouseOperating = false; item.Selected = false; if (item is FlowNode) { FlowNode node = item as FlowNode; node.ShowAnchor = false; node.InLines.Clear(); node.OutLines.Clear(); node.TopLines.Clear(); node.LeftLines.Clear(); node.RightLines.Clear(); node.BottomLines.Clear(); node.PreNodes.Clear(); node.NextNodes.Clear(); if (node.NodeState == FlowNodeState.Added || node.NodeState == FlowNodeState.Detached) { node.NodeState = FlowNodeState.Detached; } else { node.NodeState = FlowNodeState.Deleted; } this._deletedNodes.Add(item as FlowNode); continue; } if (item is FlowLine) { FlowLine line = item as FlowLine; line.AnchorBegin = AnchorKind.None; line.AnchorEnd = AnchorKind.None; line.NodeBegin = null; line.NodeEnd = null; line.NodeCodeBegin = null; line.NodeCodeEnd = null; continue; } } this._selectedItems.Clear(); this._items.Clear(); } /// /// 删除选择项目 /// public void DeleteSelectedItems() { foreach (FlowItem item in this._selectedItems) { item.MouseOperating = false; item.Selected = false; if (item is FlowNode) { FlowNode node = item as FlowNode; node.ShowAnchor = false; foreach (FlowLine line in node.InLines) { //if (!line.Selected) { line.NodeEnd = null; line.AnchorEnd = AnchorKind.None; } } foreach (FlowLine line in node.OutLines) { //if (!line.Selected) { line.NodeBegin = null; line.AnchorBegin = AnchorKind.None; } } node.InLines.Clear(); node.OutLines.Clear(); node.TopLines.Clear(); node.LeftLines.Clear(); node.RightLines.Clear(); node.BottomLines.Clear(); node.PreNodes.Clear(); node.NextNodes.Clear(); if (node.NodeState == FlowNodeState.Added || node.NodeState == FlowNodeState.Detached) { node.NodeState = FlowNodeState.Detached; } else { node.NodeState = FlowNodeState.Deleted; } this._items.Remove(node); this._deletedNodes.Add(item as FlowNode); continue; } if (item is FlowLine) { FlowLine line = item as FlowLine; if (line.NodeBegin != null && !line.NodeBegin.Selected) { line.NodeBegin.OutLines.Remove(line); switch (line.AnchorBegin) { case AnchorKind.Top: line.NodeBegin.TopLines.Remove(line); break; case AnchorKind.Left: line.NodeBegin.LeftLines.Remove(line); break; case AnchorKind.Right: line.NodeBegin.RightLines.Remove(line); break; case AnchorKind.Bottom: line.NodeBegin.BottomLines.Remove(line); break; default: break; } } if (line.NodeEnd != null && !line.NodeEnd.Selected) { line.NodeEnd.InLines.Remove(line); switch (line.AnchorEnd) { case AnchorKind.Top: line.NodeEnd.TopLines.Remove(line); break; case AnchorKind.Left: line.NodeEnd.LeftLines.Remove(line); break; case AnchorKind.Right: line.NodeEnd.RightLines.Remove(line); break; case AnchorKind.Bottom: line.NodeEnd.BottomLines.Remove(line); break; default: break; } } line.AnchorBegin = AnchorKind.None; line.AnchorEnd = AnchorKind.None; line.NodeBegin = null; line.NodeEnd = null; this._items.Remove(line); continue; } } this._selectedItems.Clear(); } /// /// 对齐选定的节点 /// /// 对齐方式 public void ArrangeNodes(ArrangeType arrangeType) { switch (arrangeType) { case ArrangeType.Left: ArrangeNodesLeft(); break; case ArrangeType.Right: ArrangeNodesRight(); break; case ArrangeType.HorizontalCenter: ArrangeNodesHorizontalCenter(); break; case ArrangeType.Top: ArrangeNodesTop(); break; case ArrangeType.Bottom: ArrangeNodesBottom(); break; case ArrangeType.VerticalCenter: ArrangeNodesVerticalCenter(); break; default: break; } } /// /// 顶部对齐所有选中的节点 /// public void ArrangeNodesTop() { int minTop = this._canvasControl.Height; foreach (FlowItem item in this._selectedItems) { FlowNode node = item as FlowNode; if (node != null) { minTop = Math.Min(node.Top, minTop); } } foreach (FlowItem item in this._selectedItems) { FlowNode node = item as FlowNode; if (node != null) { node.Top = minTop; } } } /// /// 底部对齐所有选中的节点 /// public void ArrangeNodesBottom() { } /// /// 左侧对齐所有选中的节点 /// public void ArrangeNodesLeft() { } /// /// 右侧对齐所有选中的节点 /// public void ArrangeNodesRight() { } /// /// 垂直方向中心对齐所有选中的节点 /// public void ArrangeNodesVerticalCenter() { } /// /// 水平方向中心对齐所有选中的节点 /// public void ArrangeNodesHorizontalCenter() { } #endregion 操作项目 #endregion 公有方法 #region 内部方法 /// /// 获取新ItemID(用于流程保存) /// /// ItemID internal int GetNewItemID() { return this._newItemID; } /// /// 设置新ItemID(用于流程读取) /// /// ItemID internal void SetNewItemID(int itemID) { this._newItemID = itemID; } #region 刷新项目 /// /// 刷新鼠标框选范围 /// internal void RefreshMouseSelectRect(Graphics graphics) { if (this._mouseOperatingType == MouseOperatingType.RectSelect) { ControlPaint.DrawFocusRectangle(graphics, this._mouseSelectRect, this._canvasControl.BackColor, Color.Transparent); } } #endregion 刷新项目 #region 鼠标操作 /// /// 处理鼠标按下事件 /// /// internal void MouseDown(MouseEventArgs e) { if (e.Button != MouseButtons.Left) { this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; this.SetDefaultCursor(); return; } this._mouseDownPoint = e.Location; this._mouseMovePoint = e.Location; this._isMouseDown = true; this._isMouseMove = false; this._isMouseUp = false; if (this._mouseOperatingType != MouseOperatingType.Move) { this.CanvasCursor = Cursors.Cross; } // 鼠标绘制item if (this._drawingItem != null) { //// 节点 //if (this._drawingItem is FlowNode) //{ // FlowNode node = this._drawingItem as FlowNode; // node.Location = e.Location; // node.Size = Size.Empty; // return; //} //// 线段 //if (this._drawingItem is FlowLine) //{ // FlowLine line = this._drawingItem as FlowLine; // line.PointBegin = e.Location; // line.PointEnd = e.Location; // return; //} return; } // 改变节点大小 if (this._mouseOperatingType == MouseOperatingType.NodeTopAndLeft || this._mouseOperatingType == MouseOperatingType.NodeTopAndRight || this._mouseOperatingType == MouseOperatingType.NodeBottomAndLeft || this._mouseOperatingType == MouseOperatingType.NodeBottomAndRight || this._mouseOperatingType == MouseOperatingType.NodeTop || this._mouseOperatingType == MouseOperatingType.NodeBottom || this._mouseOperatingType == MouseOperatingType.NodeLeft || this._mouseOperatingType == MouseOperatingType.NodeRight) { // 选择的节点随着改变 begin //foreach (FlowItem selectedItem in this._selectedItems) //{ // if (selectedItem is FlowNode) // { // FlowNode node = selectedItem as FlowNode; // node.MouseDownRect = node.Bounds; // } //} // 选择的节点随着改变 end // 只改变当前节点 begin this.ClearSelection(); if (this._nodeSizeChanging != null) { this._nodeSizeChanging.Selected = true; this._selectedItems.Add(this._nodeSizeChanging); this._nodeSizeChanging.MouseDownRect = this._nodeSizeChanging.Bounds; } this.RefreshItems(); // 只改变当前节点 end return; } // 改变线段端点位置 if (this._mouseOperatingType == MouseOperatingType.LineBegin || this._mouseOperatingType == MouseOperatingType.LineEnd) { if (this._flowBoxMode != FlowBoxMode.Edit) { return; } // 取消其他item选择状态 begin this.ClearSelection(); if (this._linePointChanging != null) { this._linePointChanging.Selected = true; this._selectedItems.Add(this._linePointChanging); } this.RefreshItems(); // 取消其他item选择状态 end return; } // 正在进行其他操作 if (this._mouseOperatingType != MouseOperatingType.None) { return; } // 选择item FlowItem item = this.SelectItemByPoint(e.Location); if (item != null) { // 点选 if (!item.Selected) { this.ClearSelection(); item.Selected = true; this._selectedItems.Add(item); } this.SetMoveCursor(); this.RefreshItems(); return; } else { // 框选 this._mouseSelectRect = new Rectangle(e.Location, Size.Empty); this.SetRectSelectCursor(); // 框选开始就清空选择 begin //this.ClearSelectItem(); //this.RefreshItems(); // 框选开始就清空选择 end return; } } /// /// 处理鼠标移动事件 /// /// internal void MouseMove(MouseEventArgs e) { if (e.Button == MouseButtons.None && this._drawingItem == null) { this.SetMouseCursorByMove(e.Location); return; } if (e.Button != MouseButtons.Left) { return; } Point mouseBeginPoint = this._mouseMovePoint; this._mouseMovePoint = e.Location; this._isMouseMove = true; bool hasRefreshItems = false; #region 鼠标绘制item if (this._drawingItem != null) { // 节点 if (this._mouseOperatingType == MouseOperatingType.DrawingNode) { //FlowNode node = this._drawingItem as FlowNode; this._drawingNode.Location = mouseBeginPoint; this._drawingNode.Size = Size.Empty; this._drawingNode.Selected = true; this._drawingNode.NodeState = FlowNodeState.Added; this.ClearSelection(); this._items.Add(this._drawingNode); this._allNodes.Add(this._drawingNode); this._selectedItems.Add(this._drawingNode); this._drawingNode.MouseDownRect = this._drawingNode.Bounds; this._nodeSizeChanging = this._drawingNode; this._drawingItem = null; } // 线段 if (this._mouseOperatingType == MouseOperatingType.DrawingLine) { //FlowLine line = this._drawingItem as FlowLine; this._drawingLine.PointBegin = mouseBeginPoint; this._drawingLine.PointEnd = e.Location; this._drawingLine.Selected = true; this.ClearSelection(); this._items.Add(this._drawingLine); this._selectedItems.Add(this._drawingLine); this._linePointChanging = this._drawingLine; this._drawingItem = null; } } #endregion 鼠标绘制item #region 激活item if (this._isMouseDown) { hasRefreshItems = true; foreach (FlowItem item in this._selectedItems) { item.MouseOperating = true; } this._isMouseDown = false; // todo 在paint绘制事件中绘制激活的item,未激活item作为背景 //this.RefreshStaticItems(); } //// 取消激活item //if (this._isMouseUp) //{ // hasRefreshItems = true; // foreach (FlowItem item in this._selectedItems) // { // item.MouseOperating = false; // } // this._isMouseUp = false; // // todo 在paint绘制事件中绘制激活的item,未激活item作为背景 // //this.RefreshStaticItems(); //} #endregion 激活item #region 框选 if (this._mouseOperatingType == MouseOperatingType.RectSelect) { this._mouseSelectRect = this.GetNewRect(this._mouseSelectRect, this._mouseDownPoint, e.Location); this._canvasControl.Invalidate(); return; } #endregion 框选 #region 移动 if (this._mouseOperatingType == MouseOperatingType.Move) { int xMove = e.X - mouseBeginPoint.X; int yMove = e.Y - mouseBeginPoint.Y; this.MoveSelectedItems(xMove, yMove); this.RefreshItems(); return; } #endregion 移动 #region 左上角 if (this._mouseOperatingType == MouseOperatingType.NodeTopAndLeft) { if (this._nodeSizeChanging == null) { return; } Point point = this.GetRectTopAndLeft(this._nodeSizeChanging.MouseDownRect); int xRect = e.X - point.X; int yRect = e.Y - point.Y; foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; Point fixedPoint = this.GetRectBottomAndRight(node.MouseDownRect); node.Bounds = new Rectangle(fixedPoint, new Size(xRect - node.MouseDownRect.Width, yRect - node.MouseDownRect.Height)); // 移动连接线 foreach (FlowLine line in node.InLines) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } // 移动连接线 foreach (FlowLine line in node.OutLines) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } } this.RefreshItems(); return; } #endregion 左上角 #region 右上角 if (this._mouseOperatingType == MouseOperatingType.NodeTopAndRight) { if (this._nodeSizeChanging == null) { return; } Point point = this.GetRectTopAndRight(this._nodeSizeChanging.MouseDownRect); int xRect = e.X - point.X; int yRect = e.Y - point.Y; foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; Point fixedPoint = this.GetRectBottomAndLeft(node.MouseDownRect); node.Bounds = new Rectangle(fixedPoint, new Size(xRect + node.MouseDownRect.Width, yRect - node.MouseDownRect.Height)); // 移动连接线 foreach (FlowLine line in node.InLines) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } // 移动连接线 foreach (FlowLine line in node.OutLines) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } } this.RefreshItems(); return; } #endregion 右上角 #region 左下角 if (this._mouseOperatingType == MouseOperatingType.NodeBottomAndLeft) { if (this._nodeSizeChanging == null) { return; } Point point = this.GetRectBottomAndLeft(this._nodeSizeChanging.MouseDownRect); int xRect = e.X - point.X; int yRect = e.Y - point.Y; foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; Point fixedPoint = this.GetRectTopAndRight(node.MouseDownRect); node.Bounds = new Rectangle(fixedPoint, new Size(xRect - node.MouseDownRect.Width, yRect + node.MouseDownRect.Height)); // 移动连接线 foreach (FlowLine line in node.InLines) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } // 移动连接线 foreach (FlowLine line in node.OutLines) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } } this.RefreshItems(); return; } #endregion 左下角 #region 右下角 if (this._mouseOperatingType == MouseOperatingType.NodeBottomAndRight || this._mouseOperatingType == MouseOperatingType.DrawingNode) { if (this._nodeSizeChanging == null) { return; } Point point = this.GetRectBottomAndRight(this._nodeSizeChanging.MouseDownRect); int xRect = e.X - point.X; int yRect = e.Y - point.Y; foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; Point fixedPoint = this.GetRectTopAndLeft(node.MouseDownRect); node.Bounds = new Rectangle(fixedPoint, new Size(xRect + node.MouseDownRect.Width, yRect + node.MouseDownRect.Height)); // 移动连接线 foreach (FlowLine line in node.InLines) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } // 移动连接线 foreach (FlowLine line in node.OutLines) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } } this.RefreshItems(); return; } #endregion 右下角 #region 上中 if (this._mouseOperatingType == MouseOperatingType.NodeTop) { if (this._nodeSizeChanging == null) { return; } Point point = this.GetRectTop(this._nodeSizeChanging.MouseDownRect); int xRect = 0; int yRect = e.Y - point.Y; foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; Point fixedPoint = this.GetRectBottomAndLeft(node.MouseDownRect); node.Bounds = new Rectangle(fixedPoint, new Size(xRect + node.MouseDownRect.Width, yRect - node.MouseDownRect.Height)); // 移动连接线 foreach (FlowLine line in node.InLines) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } // 移动连接线 foreach (FlowLine line in node.OutLines) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } } this.RefreshItems(); return; } #endregion 上中 #region 下中 if (this._mouseOperatingType == MouseOperatingType.NodeBottom) { if (this._nodeSizeChanging == null) { return; } Point point = this.GetRectBottom(this._nodeSizeChanging.MouseDownRect); int xRect = 0; int yRect = e.Y - point.Y; foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; Point fixedPoint = this.GetRectTopAndLeft(node.MouseDownRect); node.Bounds = new Rectangle(fixedPoint, new Size(xRect + node.MouseDownRect.Width, yRect + node.MouseDownRect.Height)); // 移动连接线 foreach (FlowLine line in node.InLines) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } // 移动连接线 foreach (FlowLine line in node.OutLines) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } } this.RefreshItems(); return; } #endregion 下中 #region 左中 if (this._mouseOperatingType == MouseOperatingType.NodeLeft) { if (this._nodeSizeChanging == null) { return; } Point point = this.GetRectLeft(this._nodeSizeChanging.MouseDownRect); int xRect = e.X - point.X; int yRect = 0; foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; Point fixedPoint = this.GetRectTopAndRight(node.MouseDownRect); node.Bounds = new Rectangle(fixedPoint, new Size(xRect - node.MouseDownRect.Width, yRect + node.MouseDownRect.Height)); // 移动连接线 foreach (FlowLine line in node.InLines) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } // 移动连接线 foreach (FlowLine line in node.OutLines) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } } this.RefreshItems(); return; } #endregion 左中 #region 右中 if (this._mouseOperatingType == MouseOperatingType.NodeRight) { if (this._nodeSizeChanging == null) { return; } Point point = this.GetRectRight(this._nodeSizeChanging.MouseDownRect); int xRect = e.X - point.X; int yRect = 0; foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; Point fixedPoint = this.GetRectTopAndLeft(node.MouseDownRect); node.Bounds = new Rectangle(fixedPoint, new Size(xRect + node.MouseDownRect.Width, yRect + node.MouseDownRect.Height)); // 移动连接线 foreach (FlowLine line in node.InLines) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } // 移动连接线 foreach (FlowLine line in node.OutLines) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } } this.RefreshItems(); return; } #endregion 右中 #region 线段开始点 if (this._mouseOperatingType == MouseOperatingType.LineBegin) { if (this._linePointChanging == null) { return; } FlowLine line = this._linePointChanging; line.PointBegin = e.Location; // 断开连接 if (line.NodeBegin != null) { this.DisconnectL2NPointBegin(line); } // 查询可连接的锚点 FlowNode rectNode = this.GetL2N(e.Location); this._nodeAnchorShowing = rectNode; // 连接 if (rectNode != null) { rectNode.ShowAnchor = true; Rectangle[] rects = rectNode.GetAnchorRects(); for (int i = 0; i < rects.Length; i++) { Rectangle rect = rects[i]; rect.Inflate(Consts.L2N_PRECISION_EDGE, Consts.L2N_PRECISION_EDGE); if (rect.Contains(e.Location)) { AnchorKind anchorKind = (AnchorKind)i; this.ConnectL2NPointBegin(line, rectNode, anchorKind); } } } this.RefreshItems(); return; } #endregion 线段开始点 #region 线段结束点 if (this._mouseOperatingType == MouseOperatingType.LineEnd || this._mouseOperatingType == MouseOperatingType.DrawingLine) { if (this._linePointChanging == null) { return; } FlowLine line = this._linePointChanging; line.PointEnd = e.Location; // 断开连接 if (line.NodeEnd != null) { this.DisconnectL2NPointEnd(line); } // 查询可连接的锚点 FlowNode rectNode = this.GetL2N(e.Location); this._nodeAnchorShowing = rectNode; // 连接 if (rectNode != null) { rectNode.ShowAnchor = true; Rectangle[] rects = rectNode.GetAnchorRects(); for (int i = 0; i < rects.Length; i++) { Rectangle rect = rects[i]; rect.Inflate(Consts.L2N_PRECISION_EDGE, Consts.L2N_PRECISION_EDGE); if (rect.Contains(e.Location)) { AnchorKind anchorKind = (AnchorKind)i; this.ConnectL2NPointEnd(line, rectNode, anchorKind); } } } this.RefreshItems(); return; } #endregion 线段结束点 // todo 在paint绘制事件中绘制激活的item,未激活item作为背景 //this._canvasControl.Invalidate(); if (hasRefreshItems) { this.RefreshItems(); } } /// /// 处理鼠标抬起事件 /// /// internal void MouseUp(MouseEventArgs e) { if (e.Button != MouseButtons.Left) { this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; return; } this._mouseUpPoint = e.Location; this._isMouseDown = false; this._isMouseUp = true; bool hasRefreshItems = false; #region 取消激活item if (this._isMouseMove) { hasRefreshItems = true; foreach (FlowItem item in this._selectedItems) { item.MouseOperating = false; } this._isMouseMove = false; if (this._nodeAnchorShowing != null) { this._nodeAnchorShowing.ShowAnchor = false; this._nodeAnchorShowing = null; } this._nodeSizeChanging = null; this._linePointChanging = null; // todo 在paint绘制事件中绘制激活的item,未激活item作为背景 //this.RefreshStaticItems(); } #endregion 取消激活item #region 鼠标绘制item if (this._drawingItem != null) { if (this._mouseOperatingType == MouseOperatingType.DrawingNode) { this.NewNodeInternal(e.Location); } if (this._mouseOperatingType == MouseOperatingType.DrawingLine) { Point pBegin = e.Location; Point pEnd = pBegin; pEnd.Offset(Consts.LINE_POINT_END_DEFAULT); this.NewLineInternal(pBegin, pEnd); } this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; this.RefreshItems(); return; } else { // 用新加线段连接节点 if (this._mouseOperatingType == MouseOperatingType.DrawingLine) { Point pBegin = this._drawingLine.PointBegin; Point pEnd = this._drawingLine.PointEnd; FlowNode nodeBegin = this.SelectNodeByPoint(pBegin); FlowNode nodeEnd = this._drawingLine.NodeEnd; if (nodeEnd == null) { nodeEnd = this.SelectNodeByPoint(pEnd); } if ((nodeBegin == null && nodeEnd != null) || (nodeBegin != null && nodeEnd == null) || (nodeBegin != null && nodeEnd != null && nodeBegin.ItemCode != nodeEnd.ItemCode)) { if (nodeBegin != null) { Point np1 = this.GetRectTopAndLeft(nodeBegin.Bounds); Point np2 = this.GetRectTopAndRight(nodeBegin.Bounds); Point np3 = this.GetRectBottomAndLeft(nodeBegin.Bounds); Point np4 = this.GetRectBottomAndRight(nodeBegin.Bounds); if (this.IsSegmentIntersect(pBegin, pEnd, np1, np2)) { this.ConnectL2NPointBegin(this._drawingLine, nodeBegin, AnchorKind.Top); } else if (this.IsSegmentIntersect(pBegin, pEnd, np3, np4)) { this.ConnectL2NPointBegin(this._drawingLine, nodeBegin, AnchorKind.Bottom); } else if (this.IsSegmentIntersect(pBegin, pEnd, np1, np3)) { this.ConnectL2NPointBegin(this._drawingLine, nodeBegin, AnchorKind.Left); } else if (this.IsSegmentIntersect(pBegin, pEnd, np2, np4)) { this.ConnectL2NPointBegin(this._drawingLine, nodeBegin, AnchorKind.Right); } } if (this._drawingLine.AnchorEnd == AnchorKind.None && nodeEnd != null) { Point np1 = this.GetRectTopAndLeft(nodeEnd.Bounds); Point np2 = this.GetRectTopAndRight(nodeEnd.Bounds); Point np3 = this.GetRectBottomAndLeft(nodeEnd.Bounds); Point np4 = this.GetRectBottomAndRight(nodeEnd.Bounds); if (this.IsSegmentIntersect(pBegin, pEnd, np1, np2)) { this.ConnectL2NPointEnd(this._drawingLine, nodeEnd, AnchorKind.Top); } else if (this.IsSegmentIntersect(pBegin, pEnd, np3, np4)) { this.ConnectL2NPointEnd(this._drawingLine, nodeEnd, AnchorKind.Bottom); } else if (this.IsSegmentIntersect(pBegin, pEnd, np1, np3)) { this.ConnectL2NPointEnd(this._drawingLine, nodeEnd, AnchorKind.Left); } else if (this.IsSegmentIntersect(pBegin, pEnd, np2, np4)) { this.ConnectL2NPointEnd(this._drawingLine, nodeEnd, AnchorKind.Right); } } } this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; this.RefreshItems(); return; } this._drawingNode = null; this._drawingLine = null; } #endregion 鼠标绘制item #region 框选 if (this._mouseOperatingType == MouseOperatingType.RectSelect) { this.SelectItemByRect(this._mouseSelectRect); this._mouseSelectRect = Rectangle.Empty; this.RefreshItems(); //this._canvasControl.Invalidate(); return; } #endregion 框选 //this.SetDefaultCursor(); if (hasRefreshItems) { this.RefreshItems(); } } /// /// 鼠标双击 /// /// /// internal FlowNode MouseDoubleClick(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (this._selectedItems.Count == 1) { FlowItem item = this._selectedItems[0]; if (item is FlowNode) { return item as FlowNode; } } } return null; } /// /// 移动选择的项目 /// /// X轴的移动量 /// Y轴的移动量 internal void MoveSelectedItems(int xMove, int yMove) { foreach (FlowItem item in this._selectedItems) { if (item is FlowNode) { FlowNode node = item as FlowNode; node.Left += xMove; node.Top += yMove; // 移动连接线 foreach (FlowLine line in node.InLines) { if (!line.Selected) { line.PointEnd = node.GetAnchor(line.AnchorEnd); } } // 移动连接线 foreach (FlowLine line in node.OutLines) { if (!line.Selected) { line.PointBegin = node.GetAnchor(line.AnchorBegin); } } continue; } if (item is FlowLine) { FlowLine line = item as FlowLine; Point p = line.PointBegin; p.X += xMove; p.Y += yMove; line.PointBegin = p; p = line.PointEnd; p.X += xMove; p.Y += yMove; line.PointEnd = p; // 断开连接 if (line.NodeBegin != null && !line.NodeBegin.Selected) { this.DisconnectL2NPointBegin(line); } if (line.NodeEnd != null && !line.NodeEnd.Selected) { this.DisconnectL2NPointEnd(line); } continue; } } } #endregion 鼠标操作 #endregion 内部方法 #region 私有方法 #region 新建项目 /// /// 新建节点 /// /// 节点位置 /// 节点 private FlowNode NewNodeInternal(Point? location) { //FlowNode node = this._drawingItem as FlowNode; FlowNode newNode = (this._drawingNode == null) ? new FlowNode(this) : this._drawingNode; newNode.Selected = true; if (location.HasValue) { newNode.Location = location.Value; } if (newNode.Bounds.IsEmpty) { newNode.Bounds = Consts.NODE_BOUNDS_DEFAULT; } if (newNode.Size.IsEmpty) { newNode.Size = Consts.NODE_BOUNDS_DEFAULT.Size; } newNode.NodeState = FlowNodeState.Added; this.ClearSelection(); this._items.Add(newNode); this._allNodes.Add(newNode); this._selectedItems.Add(newNode); this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; this.SetDefaultCursor(); return newNode; } /// /// 新建线段 /// /// 起始点 /// 结算点 /// 线段 private FlowLine NewLineInternal(Point? pointBegin, Point? pointEnd) { //FlowLine line = this._drawingItem as FlowLine; FlowLine newLine = (this._drawingLine == null) ? new FlowLine(this) : this._drawingLine; newLine.Selected = true; if (pointBegin.HasValue) { newLine.PointBegin = pointBegin.Value; newLine.PointEnd = pointEnd.Value; } else { newLine.PointBegin = Consts.LINE_POINT_Begin_DEFAULT; newLine.PointEnd = Consts.LINE_POINT_END_DEFAULT; } this.ClearSelection(); this._items.Add(newLine); this._selectedItems.Add(newLine); this._drawingItem = null; this._drawingNode = null; this._drawingLine = null; this.SetDefaultCursor(); return newLine; } #endregion 新建项目 #region 绘制项目 /// /// 绘制Item /// /// Graphics private void DrawItems(Graphics graphics) { foreach (FlowItem item in this._items) { this.DrawItem(graphics, item); } foreach (FlowItem item in this._items) { this.DrawSelectedItem(graphics, item); } } ///// ///// 绘制未激活的Item ///// ///// Graphics //private void DrawStaticItems(Graphics graphics) //{ // foreach (FlowItem item in this._items) // { // // 不绘制激活的item // if (item.MouseOperating) // { // continue; // } // this.DrawItem(graphics, item); // } //} ///// ///// 绘制激活的Item ///// ///// Graphics //private void DrawActiveItems(Graphics graphics) //{ // foreach (FlowItem item in this._items) // { // // 绘制激活的item // if (!item.MouseOperating) // { // continue; // } // this.DrawItem(graphics, item); // } //} /// /// 绘制图片 /// /// /// /// private void DrawImage(Graphics graphics, Image image, Rectangle rect) { graphics.DrawImage(image, rect); } /// /// 绘制Item /// /// Graphics /// item private void DrawItem(Graphics graphics, FlowItem item) { if (item is FlowNode) { FlowNode node = item as FlowNode; this.DrawNode(graphics, node); return; } if (item is FlowLine) { FlowLine line = item as FlowLine; this.DrawLine(graphics, line); return; } } /// /// 绘制选中状态Item的附属 /// /// Graphics /// item private void DrawSelectedItem(Graphics graphics, FlowItem item) { if (item is FlowNode) { FlowNode node = item as FlowNode; this.DrawSelectedNode(graphics, node); return; } if (item is FlowLine) { FlowLine line = item as FlowLine; this.DrawSelectedLine(graphics, line); return; } } /// /// 绘制节点 /// /// Graphics /// 节点 private void DrawNode(Graphics graphics, FlowNode node) { // 填充颜色 if (node.FillColor.HasValue && node.FillColor != Color.Transparent) { this._penDrawNode.Color = node.FillColor.Value; graphics.FillRectangle(this._penDrawNode.Brush, node.Bounds); } // 画图 if (node.NodeImage != null) { this.DrawImage(graphics, node.NodeImage, node.Bounds); } // 画边框 if (node.BorderWidth > 0 && node.BorderColor != Color.Transparent) { this._penDrawNode.Color = node.BorderColor; this._penDrawNode.Width = node.BorderWidth; graphics.DrawRectangle(this._penDrawNode, node.Bounds); } // 显示名称 if (node.ShowName) { Point p5 = this.GetRectBottom(node.Bounds); SizeF size = graphics.MeasureString(node.Name, node.Font); this._penDrawString.Color = node.FontColor; graphics.DrawString(node.Name, node.Font, this._penDrawString.Brush, p5.X - size.Width / 2, p5.Y + Consts.NODE_STRING_MARGIN); } // this.DrawSelectedNode(graphics, node); } /// /// 绘制选中节点的附属 /// /// Graphics /// 节点 private void DrawSelectedNode(Graphics graphics, FlowNode node) { Rectangle[] rects = node.GetSelectedStyle(); // 画激活状态 if (node.MouseOperating) { for (int i = 0; i < rects.Length; i++) { bool isAnchor = false; switch ((NodePointKind)i) { case NodePointKind.Top: if (node.TopLines != null && node.TopLines.Count > 0) { isAnchor = true; } break; case NodePointKind.Bottom: if (node.BottomLines != null && node.BottomLines.Count > 0) { isAnchor = true; } break; case NodePointKind.Left: if (node.LeftLines != null && node.LeftLines.Count > 0) { isAnchor = true; } break; case NodePointKind.Right: if (node.RightLines != null && node.RightLines.Count > 0) { isAnchor = true; } break; default: break; } this.DrawSelected(graphics, rects[i], isAnchor, true); } } // 画选择状态 else if (node.Selected) { for (int i = 0; i < rects.Length; i++) { bool isAnchor = false; switch ((NodePointKind)i) { case NodePointKind.Top: if (node.TopLines != null && node.TopLines.Count > 0) { isAnchor = true; } break; case NodePointKind.Bottom: if (node.BottomLines != null && node.BottomLines.Count > 0) { isAnchor = true; } break; case NodePointKind.Left: if (node.LeftLines != null && node.LeftLines.Count > 0) { isAnchor = true; } break; case NodePointKind.Right: if (node.RightLines != null && node.RightLines.Count > 0) { isAnchor = true; } break; default: break; } this.DrawSelected(graphics, rects[i], isAnchor, false); } } if (node.ShowAnchor) { Rectangle[] anchorRects = node.GetAnchorRects(); foreach (Rectangle rect in anchorRects) { this.DrawSelected(graphics, rect, true, true); } } } /// /// 绘制线段 /// /// Graphics /// 线段 private void DrawLine(Graphics graphics, FlowLine line) { this._penDrawLine.Color = line.LineColor; this._penDrawLine.Width = line.LineWidth; // 画线段 graphics.DrawLine(this._penDrawLine, line.PointBegin, line.PointEnd); // 显示名称 if (line.ShowName) { Point mp = this.GetLineMidpoint(line.PointBegin, line.PointEnd); SizeF size = graphics.MeasureString(line.Name, line.Font); this._penDrawString.Color = line.FontColor; graphics.DrawString(line.Name, line.Font, this._penDrawString.Brush, mp.X - size.Width / 2, mp.Y - size.Height / 2); } // this.DrawSelectedLine(graphics, node); } /// /// 绘制选中线段的附属 /// /// Graphics /// 线段 private void DrawSelectedLine(Graphics graphics, FlowLine line) { Rectangle[] rects = line.GetSelectedStyle(); // 画激活状态 if (line.MouseOperating) { if (line.NodeBegin != null) { if (!line.NodeBegin.Selected) { this.DrawSelected(graphics, rects[0], true, true); } } else { this.DrawSelected(graphics, rects[0], false, true); } if (line.NodeEnd != null) { if (!line.NodeEnd.Selected) { this.DrawSelected(graphics, rects[1], true, true); } } else { this.DrawSelected(graphics, rects[1], false, true); } } // 画选择状态 else if (line.Selected) { if (line.NodeBegin != null) { if (!line.NodeBegin.Selected) { this.DrawSelected(graphics, rects[0], true, false); } } else { this.DrawSelected(graphics, rects[0], false, false); } if (line.NodeEnd != null) { if (!line.NodeEnd.Selected) { this.DrawSelected(graphics, rects[1], true, false); } } else { this.DrawSelected(graphics, rects[1], false, false); } } } /// /// 绘制折线 /// /// /// private void DrawPolyline(Graphics graphics, FlowPolyline line) { } /// /// 绘制选择Item的附属 /// /// /// /// /// private void DrawSelected(Graphics graphics, Rectangle rect, bool isAnchor, bool operating) { if (operating) { if (isAnchor) { graphics.FillEllipse(Consts.SELECT_POINT_BRUSH_LINE_TO_NODE, rect); graphics.DrawEllipse(Consts.SELECT_POINT_PEN, rect); } else { graphics.FillEllipse(Consts.SELECT_POINT_BRUSH, rect); graphics.DrawEllipse(Consts.SELECT_POINT_PEN, rect); } } else { if (isAnchor) { graphics.FillRectangle(Consts.SELECT_POINT_BRUSH_LINE_TO_NODE, rect); graphics.DrawRectangle(Consts.SELECT_POINT_PEN, rect); } else { graphics.FillRectangle(Consts.SELECT_POINT_BRUSH, rect); graphics.DrawRectangle(Consts.SELECT_POINT_PEN, rect); } } } #endregion 绘制项目 #region 鼠标样式 /// /// 设置鼠标样式 /// /// private void SetCursor(MouseOperatingType type) { this._mouseOperatingType = type; switch (type) { case MouseOperatingType.None: this.CanvasCursor = Cursors.Default; break; case MouseOperatingType.RectSelect: this.CanvasCursor = Cursors.Cross; break; case MouseOperatingType.Move: this.CanvasCursor = Cursors.SizeAll; break; case MouseOperatingType.NodeTopAndLeft: case MouseOperatingType.NodeBottomAndRight: this.CanvasCursor = Cursors.SizeNWSE; break; case MouseOperatingType.NodeTopAndRight: case MouseOperatingType.NodeBottomAndLeft: this.CanvasCursor = Cursors.SizeNESW; break; case MouseOperatingType.NodeTop: case MouseOperatingType.NodeBottom: this.CanvasCursor = Cursors.SizeNS; break; case MouseOperatingType.NodeLeft: case MouseOperatingType.NodeRight: this.CanvasCursor = Cursors.SizeWE; break; case MouseOperatingType.LineBegin: case MouseOperatingType.LineEnd: this.CanvasCursor = Cursors.Hand; break; case MouseOperatingType.DrawingNode: this.CanvasCursor = ItemCursor.NodeCursor; break; case MouseOperatingType.DrawingLine: this.CanvasCursor = ItemCursor.LineCursor; break; default: this.CanvasCursor = Cursors.Default; break; } } /// /// 设置手动画节点时鼠标样式 /// private void SetDrawingNodeCursor() { this.SetCursor(MouseOperatingType.DrawingNode); } /// /// 设置手动画节点时鼠标样式 /// private void SetDrawingLineCursor() { this.SetCursor(MouseOperatingType.DrawingLine); } /// /// 设置框选时鼠标样式 /// private void SetRectSelectCursor() { this.SetCursor(MouseOperatingType.RectSelect); } /// /// 设置默认鼠标样式 /// private void SetDefaultCursor() { this.SetCursor(MouseOperatingType.None); } /// /// 设置移动时鼠标样式 /// private void SetMoveCursor() { this.SetCursor(MouseOperatingType.Move); } /// /// 设置改变节点大小时鼠标样式 /// /// 节点端点 private void SetNodeResizeCursor(NodePointKind kind) { MouseOperatingType type = MouseOperatingType.None; switch (kind) { case NodePointKind.TopAndLeft: type = MouseOperatingType.NodeTopAndLeft; break; case NodePointKind.TopAndRight: type = MouseOperatingType.NodeTopAndRight; break; case NodePointKind.BottomAndLeft: type = MouseOperatingType.NodeBottomAndLeft; break; case NodePointKind.BottomAndRight: type = MouseOperatingType.NodeBottomAndRight; break; case NodePointKind.Top: type = MouseOperatingType.NodeTop; break; case NodePointKind.Bottom: type = MouseOperatingType.NodeBottom; break; case NodePointKind.Left: type = MouseOperatingType.NodeLeft; break; case NodePointKind.Right: type = MouseOperatingType.NodeRight; break; default: type = MouseOperatingType.None; break; } this.SetCursor(type); } /// /// 设置改变线段端点时鼠标样式 /// /// 线段端点 private void SetLineResizeCursor(LinePointKind kind) { MouseOperatingType type = MouseOperatingType.None; switch (kind) { case LinePointKind.Begin: type = MouseOperatingType.LineBegin; break; case LinePointKind.End: type = MouseOperatingType.LineEnd; break; default: type = MouseOperatingType.None; break; } this.SetCursor(type); } /// /// 鼠标移动时,根据鼠标位置设置鼠标样式 /// /// 鼠标位置 private void SetMouseCursorByMove(Point point) { this._nodeSizeChanging = null; this._linePointChanging = null; // item附属判断 for (int i = this._items.Count - 1; i >= 0; i--) { FlowItem item = this._items[i]; if (!item.Selected) { continue; } Rectangle[] rects = item.GetSelectedStyle(); if (item is FlowNode) { FlowNode node = item as FlowNode; for (int index = 0; index < rects.Length; index++) { if (rects[index].Contains(point)) { NodePointKind kind = (NodePointKind)index; // 优先操作连接节点的线段 switch (kind) { case NodePointKind.Top: if (!this.CanOperateNode(node.TopLines)) { continue; } break; case NodePointKind.Bottom: if (!this.CanOperateNode(node.BottomLines)) { continue; } break; case NodePointKind.Left: if (!this.CanOperateNode(node.LeftLines)) { continue; } break; case NodePointKind.Right: if (!this.CanOperateNode(node.RightLines)) { continue; } break; default: break; } this.SetNodeResizeCursor(kind); this._nodeSizeChanging = node; return; } } } if (this._flowBoxMode != FlowBoxMode.Edit) { continue; } if (item is FlowLine) { for (int index = 0; index < rects.Length; index++) { if (rects[index].Contains(point)) { LinePointKind kind = (LinePointKind)index; this.SetLineResizeCursor(kind); this._linePointChanging = item as FlowLine; return; } } } } // item内部判断 for (int i = this._items.Count - 1; i >= 0; i--) { FlowItem item = this._items[i]; if (!item.Selected) { continue; } if (item is FlowNode) { if (this.IsPointOnNode(point, item as FlowNode)) { this.SetMoveCursor(); return; } } if (this._flowBoxMode != FlowBoxMode.Edit) { continue; } if (item is FlowLine) { if (this.IsPointOnLine(point, item as FlowLine)) { this.SetMoveCursor(); return; } } } this._nodeSizeChanging = null; this._linePointChanging = null; this.SetDefaultCursor(); } #endregion 鼠标样式 #region 流程控制 /// /// 连接PointBegin到节点 /// /// 线段 /// 节点 /// 锚点 private void ConnectL2NPointBegin(FlowLine line, FlowNode node, AnchorKind anchorKind) { line.AnchorBegin = anchorKind; // 连接节点 line.PointBegin = node.GetAnchor(anchorKind); line.NodeBegin = node; node.OutLines.Add(line); switch (anchorKind) { case AnchorKind.Top: node.TopLines.Add(line); break; case AnchorKind.Bottom: node.BottomLines.Add(line); break; case AnchorKind.Left: node.LeftLines.Add(line); break; case AnchorKind.Right: node.RightLines.Add(line); break; default: break; } } /// /// 连接PointEnd到节点 /// /// 线段 /// 节点 /// 锚点 private void ConnectL2NPointEnd(FlowLine line, FlowNode node, AnchorKind anchorKind) { line.AnchorEnd = anchorKind; // 连接节点 line.PointEnd = node.GetAnchor(anchorKind); line.NodeEnd = node; node.InLines.Add(line); switch (anchorKind) { case AnchorKind.Top: node.TopLines.Add(line); break; case AnchorKind.Bottom: node.BottomLines.Add(line); break; case AnchorKind.Left: node.LeftLines.Add(line); break; case AnchorKind.Right: node.RightLines.Add(line); break; default: break; } } /// /// 断开PointBegin的连接 /// /// 线段 private void DisconnectL2NPointBegin(FlowLine line) { switch (line.AnchorBegin) { case AnchorKind.Top: line.NodeBegin.TopLines.Remove(line); break; case AnchorKind.Bottom: line.NodeBegin.BottomLines.Remove(line); break; case AnchorKind.Left: line.NodeBegin.LeftLines.Remove(line); break; case AnchorKind.Right: line.NodeBegin.RightLines.Remove(line); break; default: break; } line.NodeBegin.OutLines.Remove(line); line.NodeBegin = null; line.AnchorBegin = AnchorKind.None; } /// /// 断开PointEnd的连接 /// /// 线段 private void DisconnectL2NPointEnd(FlowLine line) { switch (line.AnchorEnd) { case AnchorKind.Top: line.NodeEnd.TopLines.Remove(line); break; case AnchorKind.Bottom: line.NodeEnd.BottomLines.Remove(line); break; case AnchorKind.Left: line.NodeEnd.LeftLines.Remove(line); break; case AnchorKind.Right: line.NodeEnd.RightLines.Remove(line); break; default: break; } line.NodeEnd.InLines.Remove(line); line.NodeEnd = null; line.AnchorEnd = AnchorKind.None; } /// /// 获得可连接的节点 /// /// 鼠标位置 /// 可连接的节点 private FlowNode GetL2N(Point point) { FlowNode inNode = null; FlowNode edgeNode = null; for (int i = this._items.Count - 1; i >= 0; i--) { FlowNode node = this._items[i] as FlowNode; if (node == null) { continue; } node.ShowAnchor = false; // 在节点范围内 if (node.Bounds.Contains(point)) { inNode = node; } // 在节点边缘 Rectangle rect = node.Bounds; rect.Inflate(Consts.L2N_PRECISION_EDGE, Consts.L2N_PRECISION_EDGE); if (rect.Contains(point)) { edgeNode = node; } } if (inNode != null) { inNode.ShowAnchor = true; return inNode; } if (edgeNode != null) { edgeNode.ShowAnchor = true; return edgeNode; } return null; } #endregion 流程控制 #region 鼠标操作 /// /// 框选Item /// /// 框选范围 private void SelectItemByRect(Rectangle rect) { this.ClearSelection(); foreach (FlowItem item in this._items) { if (item is FlowNode) { FlowNode node = item as FlowNode; if (rect.IntersectsWith(node.Bounds)) { node.Selected = true; this._selectedItems.Add(node); } else { node.Selected = false; } continue; } if (this._flowBoxMode != FlowBoxMode.Edit) { continue; } if (item is FlowLine) { FlowLine line = item as FlowLine; if (rect.Contains(line.PointBegin) || rect.Contains(line.PointEnd)) { line.Selected = true; this._selectedItems.Add(line); } else { line.Selected = false; } continue; } } } /// /// 点选Item /// /// 鼠标点 /// 选中的item private FlowItem SelectItemByPoint(Point point) { for (int i = this._items.Count - 1; i >= 0; i--) { FlowItem item = this._items[i]; if (item is FlowNode) { if (this.IsPointOnNode(point, item as FlowNode)) { return item; } } if (this._flowBoxMode != FlowBoxMode.Edit) { continue; } if (item is FlowLine) { if (this.IsPointOnLine(point, item as FlowLine)) { return item; } } //if (item is FlowPolyline) //{ // if (this.IsPointOnPolyLine(point, item as FlowPolyline)) // { // return item; // } //} } return null; } /// /// 点选节点 /// /// 鼠标点 /// 选中的节点 private FlowNode SelectNodeByPoint(Point point) { for (int i = this._items.Count - 1; i >= 0; i--) { FlowItem item = this._items[i]; if (item is FlowNode) { FlowNode node = item as FlowNode; if (this.IsPointOnNode(point, node)) { return node; } } } return null; } /// /// 能否操作节点(鼠标在锚点) /// /// 连接的线段 /// 能否操作节点 private bool CanOperateNode(List lines) { if (lines != null && lines.Count > 0) { foreach (FlowLine line in lines) { if (line.Selected) { return false; } } } return true; } #endregion 鼠标操作 #region 工具 /// /// 判断线段是否相交 /// /// 线段1的开始点 /// 线段1的结束点 /// 线段2的开始点 /// 线段2的结束点 /// 是否相交 private bool IsSegmentIntersect(Point p1, Point p2, Point p3, Point p4) { double d1 = this.GetDirection(p3, p4, p1); double d2 = this.GetDirection(p3, p4, p2); double d3 = this.GetDirection(p1, p2, p3); double d4 = this.GetDirection(p1, p2, p4); if (d1 * d2 < 0 && d3 * d4 < 0) { return true; } else if (d1 == 0 && this.IsOnSegment(p3, p4, p1)) { return true; } else if (d2 == 0 && this.IsOnSegment(p3, p4, p2)) { return true; } else if (d3 == 0 && this.IsOnSegment(p1, p2, p3)) { return true; } else if (d4 == 0 && this.IsOnSegment(p1, p2, p4)) { return true; } else { return false; } } /// /// 获取点1到点2和点3的向量的叉乘 /// /// 点1 /// 点2 /// 点3 /// private int GetDirection(Point p1, Point p2, Point p3) { Point v1 = new Point(p3.X - p1.X, p3.Y - p1.Y); Point v2 = new Point(p2.X - p1.X, p2.Y - p1.Y); return v1.X * v2.Y - v1.Y * v2.X; } /// /// 点3在线上时,判断点3在线段上,还是在线段的延长线上 /// /// 线段的开始点 /// 线段的结束点 /// 点3 /// private bool IsOnSegment(Point p1, Point p2, Point p3) { int x_min, x_max, y_min, y_max; if (p1.X < p2.X) { x_min = p1.X; x_max = p2.X; } else { x_min = p2.X; x_max = p1.X; } if (p1.Y < p2.Y) { y_min = p1.Y; y_max = p2.Y; } else { y_min = p2.Y; y_max = p1.Y; } if (p3.X < x_min || p3.X > x_max || p3.Y < y_min || p3.Y > y_max) { return false; } else { return true; } } /// /// 点是否在节点上 /// /// 点 /// 节点 /// 是否在节点上 private bool IsPointOnNode(Point point, FlowNode node) { return node.Bounds.Contains(point); } /// /// 点是否在线段上 /// /// 点 /// 线段 /// 否在线段上 private bool IsPointOnLine(Point point, FlowLine line) { double p2ls = this.GetP2LSDistance(point, line.PointBegin, line.PointEnd); //if (p2ls <= (line.LineWidth - 1) / 2 + Consts.P2L_PRECISION) if (p2ls <= (line.LineWidth) / 2 + Consts.P2L_PRECISION) { return true; } return false; } /// /// 获取点到线段的距离 /// /// 点 /// 线段的端点 /// 线段的端点 /// 点到线段的距离 private double GetP2LSDistance(Point p, Point pBegin, Point pEnd) { // 点在线段端点 double pp1 = this.GetP2PDistance(p, pBegin); if (pp1 < Consts.DOUBLE_PRECISION) { return pp1; } double pp2 = this.GetP2PDistance(p, pEnd); if (pp2 < Consts.DOUBLE_PRECISION) { return pp2; } double p1p2 = this.GetP2PDistance(pBegin, pEnd); // 线段端点相同 if (p1p2 < Consts.DOUBLE_PRECISION) { return pp1; } // 点在线段端点外 double pp12 = pp1 * pp1; double pp22 = pp2 * pp2; double p1p22 = p1p2 * p1p2; if (pp12 >= pp22 + p1p22) { return pp22; } if (pp22 >= pp12 + p1p22) { return pp12; } // 点在线段端点内 // 周长的一半 double l = (pp1 + pp2 + p1p2) / 2; // 海伦公式求面积,也可以用矢量求 double s = Math.Sqrt(l * (l - pp1) * (l - pp2) * (l - p1p2)); return 2 * s / p1p2; } /// /// 获取两点间的距离 /// /// /// /// 两点间的距离 private double GetP2PDistance(Point point1, Point point2) { return Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) + (point1.Y - point2.Y) * (point1.Y - point2.Y)); } /// /// 获取鼠标操作后的新范围 /// /// 源范围 /// 固定点 /// 移动点 /// 新范围 private Rectangle GetNewRect(Rectangle rect, Point fixedPoint, Point newPoint) { int xRect = newPoint.X - fixedPoint.X; int yRect = newPoint.Y - fixedPoint.Y; if (xRect < 0) { rect.X = newPoint.X; rect.Width = -xRect; } else { rect.X = fixedPoint.X; rect.Width = xRect; } if (yRect < 0) { rect.Y = newPoint.Y; rect.Height = -yRect; } else { rect.Y = fixedPoint.Y; rect.Height = yRect; } return rect; } /// /// 获取鼠标操作后的新范围 /// /// 源范围 /// 固定点 /// x方向移动距离 /// y方向移动距离 /// 新范围 private Rectangle GetNewRect(Rectangle rect, Point fixedPoint, int xRect, int yRect) { if (xRect < 0) { rect.X = fixedPoint.X + xRect; rect.Width = -xRect; } else { rect.X = fixedPoint.X; rect.Width = xRect; } if (yRect < 0) { rect.Y = fixedPoint.Y + yRect; rect.Height = -yRect; } else { rect.Y = fixedPoint.Y; rect.Height = yRect; } return rect; } /// /// 获得矩形的左上角 /// /// 矩形 /// 左上角 private Point GetRectTopAndLeft(Rectangle rect) { return rect.Location; } /// /// 获得矩形的右上角 /// /// 矩形 /// 右上角 private Point GetRectTopAndRight(Rectangle rect) { return new Point(rect.Right, rect.Top); } /// /// 获得矩形的左下角 /// /// 矩形 /// 左下角 private Point GetRectBottomAndLeft(Rectangle rect) { return new Point(rect.Left, rect.Bottom); } /// /// 获得矩形的右下角 /// /// 矩形 /// 右下角 private Point GetRectBottomAndRight(Rectangle rect) { return new Point(rect.Right, rect.Bottom); } /// /// 获得矩形的上中点 /// /// 矩形 /// 上中点 private Point GetRectTop(Rectangle rect) { return new Point(rect.Left + rect.Width / 2, rect.Top); } /// /// 获得矩形的下中点 /// /// 矩形 /// 下中点 private Point GetRectBottom(Rectangle rect) { return new Point(rect.Left + rect.Width / 2, rect.Bottom); } /// /// 获得矩形的左中点 /// /// 矩形 /// 左中点 private Point GetRectLeft(Rectangle rect) { return new Point(rect.Left, rect.Top + rect.Height / 2); } /// /// 获得矩形的右中点 /// /// 矩形 /// 右中点 private Point GetRectRight(Rectangle rect) { return new Point(rect.Right, rect.Top + rect.Height / 2); } /// /// 获得线段的中点 /// /// 线段开始点 /// 线段结束点 /// 中点 private Point GetLineMidpoint(Point pointBegin, Point pointEnd) { return new Point((pointBegin.X + pointEnd.X) / 2, (pointBegin.Y + pointEnd.Y) / 2); } #endregion 工具 #endregion 私有方法 } }