mirror of
https://gitee.com/wang-yin1/wpf-visual-process-framework
synced 2026-03-02 15:50:51 +08:00
1114 lines
36 KiB
C#
1114 lines
36 KiB
C#
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|||
|
|
using CommunityToolkit.Mvvm.Input;
|
|||
|
|
using Microsoft.Win32;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Collections.ObjectModel;
|
|||
|
|
using System.Diagnostics;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Reflection;
|
|||
|
|
using System.Text;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using System.Windows;
|
|||
|
|
using System.Windows.Controls;
|
|||
|
|
using System.Windows.Input;
|
|||
|
|
using System.Windows.Media;
|
|||
|
|
using System.Windows.Media.Imaging;
|
|||
|
|
using System.Windows.Media.Media3D;
|
|||
|
|
using System.Xml.Linq;
|
|||
|
|
using VisionFrame.Base;
|
|||
|
|
using VisionFrame.Base.Models;
|
|||
|
|
using VisionFrame.Models;
|
|||
|
|
using VisionFrame.Nodes;
|
|||
|
|
|
|||
|
|
namespace VisionFrame.ViewModels
|
|||
|
|
{
|
|||
|
|
public class FlowTabViewModel : ObservableObject, IFlowContext
|
|||
|
|
{
|
|||
|
|
private bool _isCurrent;
|
|||
|
|
|
|||
|
|
public bool IsCurrent
|
|||
|
|
{
|
|||
|
|
get { return _isCurrent; }
|
|||
|
|
set
|
|||
|
|
{
|
|||
|
|
SetProperty<bool>(ref _isCurrent, value);
|
|||
|
|
|
|||
|
|
if (!value) TitleEditVisible = Visibility.Hidden;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region Title与编辑
|
|||
|
|
private string _title;
|
|||
|
|
|
|||
|
|
public string Title
|
|||
|
|
{
|
|||
|
|
get { return _title; }
|
|||
|
|
set { SetProperty<string>(ref _title, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
private Visibility _titleEditVisible = Visibility.Hidden;
|
|||
|
|
|
|||
|
|
public Visibility TitleEditVisible
|
|||
|
|
{
|
|||
|
|
get { return _titleEditVisible; }
|
|||
|
|
set { SetProperty<Visibility>(ref _titleEditVisible, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
public ICommand SelectCommand { get; set; }
|
|||
|
|
public ICommand EditTitleCommand { get; set; }
|
|||
|
|
public ICommand AcceptTitleCommand { get; set; }
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 节点创建
|
|||
|
|
public ObservableCollection<NodeModelBase> NodeList { get; set; } =
|
|||
|
|
new ObservableCollection<NodeModelBase>();
|
|||
|
|
|
|||
|
|
public ICommand DragDropCommand { get; set; }
|
|||
|
|
|
|||
|
|
public ICommand DeleteElementCommand { get; set; }
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 连线集合
|
|||
|
|
public ObservableCollection<LinkModel> LinkList { get; set; } =
|
|||
|
|
new ObservableCollection<LinkModel>();
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 节点移动相关动作
|
|||
|
|
public ICommand NodeMouseDownCommand { get; set; }
|
|||
|
|
public ICommand NodeMouseMoveCommand { get; set; }
|
|||
|
|
public ICommand NodeMouseUpCommand { get; set; }
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 锚点操作
|
|||
|
|
public ICommand AnchorDownCommand { get; set; }
|
|||
|
|
public ICommand AnchorUpCommand { get; set; }
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 流程控制
|
|||
|
|
public ICommand RunCommand { get; set; }
|
|||
|
|
public ICommand CircleCommand { get; set; }
|
|||
|
|
public ICommand StopCommand { get; set; }
|
|||
|
|
public ICommand StepCommand { get; set; }
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 流程参数管理
|
|||
|
|
public ObservableCollection<FlowArgModel> ArgumentList { get; set; } =
|
|||
|
|
new ObservableCollection<FlowArgModel>();
|
|||
|
|
|
|||
|
|
public ICommand AddArgumentCommand { get; set; }
|
|||
|
|
public ICommand DelArgumentCommand { get; set; }
|
|||
|
|
|
|||
|
|
public List<string> ArgTypeList { get; set; } = new List<string>
|
|||
|
|
{
|
|||
|
|
"Int32","IntPtr","Double","String","Boolean"
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 参数处理相关命令
|
|||
|
|
public ICommand SelectFolderCommand { get; set; }
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
private ImageSource _previewImage;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 预览图像
|
|||
|
|
/// </summary>
|
|||
|
|
public ImageSource PreviewImage
|
|||
|
|
{
|
|||
|
|
get { return _previewImage; }
|
|||
|
|
set { SetProperty<ImageSource>(ref _previewImage, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
public ObservableCollection<LogModel> LogList { get; set; } =
|
|||
|
|
new ObservableCollection<LogModel>();
|
|||
|
|
|
|||
|
|
|
|||
|
|
//画布缩放
|
|||
|
|
#region 画布缩放
|
|||
|
|
private double _mainZoom = 1.0;
|
|||
|
|
|
|||
|
|
public double MainZoom
|
|||
|
|
{
|
|||
|
|
get { return _mainZoom; }
|
|||
|
|
set { SetProperty<double>(ref _mainZoom, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private double _dragX = 0;
|
|||
|
|
|
|||
|
|
public double DragX
|
|||
|
|
{
|
|||
|
|
get { return _dragX; }
|
|||
|
|
set { SetProperty<double>(ref _dragX, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private double _dragY = 0;
|
|||
|
|
|
|||
|
|
public double DragY
|
|||
|
|
{
|
|||
|
|
get { return _dragY; }
|
|||
|
|
set { SetProperty<double>(ref _dragY, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public ICommand MouseWheelCommand { get; set; }
|
|||
|
|
|
|||
|
|
public ICommand CanvasMouseDownCommand { get; set; }
|
|||
|
|
public ICommand CanvasMouseUpCommand { get; set; }
|
|||
|
|
public ICommand CanvasMouseMoveCommand { get; set; }
|
|||
|
|
|
|||
|
|
public ICommand ZoomIncreaseCommand { get; set; }
|
|||
|
|
public ICommand ZoomReduceCommand { get; set; }
|
|||
|
|
public ICommand ZoomResetCommand { get; set; }
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 鹰眼视图
|
|||
|
|
private double _hwakeyeZoom = 1.0;
|
|||
|
|
|
|||
|
|
public double HwakeyeZoom
|
|||
|
|
{
|
|||
|
|
get { return _hwakeyeZoom; }
|
|||
|
|
set { SetProperty<double>(ref _hwakeyeZoom, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private double _hwakeyeDragX;
|
|||
|
|
|
|||
|
|
public double HwakeyeDragX
|
|||
|
|
{
|
|||
|
|
get { return _hwakeyeDragX; }
|
|||
|
|
set { SetProperty<double>(ref _hwakeyeDragX, value); }
|
|||
|
|
}
|
|||
|
|
private double _hwakeyeDragY;
|
|||
|
|
|
|||
|
|
public double HwakeyeDragY
|
|||
|
|
{
|
|||
|
|
get { return _hwakeyeDragY; }
|
|||
|
|
set { SetProperty<double>(ref _hwakeyeDragY, value); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
|
|||
|
|
public List<string> Operator { get; set; } = new List<string>
|
|||
|
|
{
|
|||
|
|
"=","<",">","<=",">=","!="
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
public FlowTabViewModel()
|
|||
|
|
{
|
|||
|
|
SelectCommand = new RelayCommand(() =>
|
|||
|
|
{
|
|||
|
|
this.IsCurrent = true;
|
|||
|
|
});
|
|||
|
|
DragDropCommand = new RelayCommand<object>(OnDragDrop);
|
|||
|
|
|
|||
|
|
DeleteElementCommand = new RelayCommand<object>(DoElementDelete);
|
|||
|
|
|
|||
|
|
#region Tab Title编辑动作
|
|||
|
|
EditTitleCommand = new RelayCommand(() =>
|
|||
|
|
{
|
|||
|
|
TitleEditVisible = Visibility.Visible;
|
|||
|
|
});
|
|||
|
|
AcceptTitleCommand = new RelayCommand(() =>
|
|||
|
|
{
|
|||
|
|
TitleEditVisible = Visibility.Hidden;
|
|||
|
|
});
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 节点移动动作
|
|||
|
|
NodeMouseDownCommand = new RelayCommand<object>(OnNodeMouseDown);
|
|||
|
|
NodeMouseMoveCommand = new RelayCommand<object>(OnNodeMove);
|
|||
|
|
NodeMouseUpCommand = new RelayCommand(OnNodeMouseUp);
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
//默认起始节点添加
|
|||
|
|
string node_name = "VisionFrame.Nodes.StartNode";
|
|||
|
|
//INodeBase node = Activator.CreateInstance(Assembly.GetExecutingAssembly().GetType(node_name)) as INodeBase;
|
|||
|
|
//node.AnchorDownCommand = new RelayCommand<object>(OnAnchorDown);
|
|||
|
|
NodeList.Add(new StartNodeModel
|
|||
|
|
{
|
|||
|
|
IsStart = true,
|
|||
|
|
TargetNodeObject = node_name,
|
|||
|
|
X = 600,
|
|||
|
|
Y = 450,
|
|||
|
|
W = 100,
|
|||
|
|
H = 34,
|
|||
|
|
FlowLevel = new List<int> { 0 }
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 流程控制
|
|||
|
|
RunCommand = new RelayCommand(DoRunFlowchart);
|
|||
|
|
CircleCommand = new RelayCommand(DoCircleExecute);
|
|||
|
|
StopCommand = new RelayCommand(DoStopExecute);
|
|||
|
|
StepCommand = new RelayCommand(DoStepExecute);
|
|||
|
|
|
|||
|
|
// 添加参数
|
|||
|
|
AddArgumentCommand = new RelayCommand(DoAddArgument);
|
|||
|
|
DelArgumentCommand = new RelayCommand<object>(DoDelArgument);
|
|||
|
|
|
|||
|
|
// 参数列表命令
|
|||
|
|
SelectFolderCommand = new RelayCommand<object>(DoSelectFolder);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 锚点控制
|
|||
|
|
AnchorDownCommand = new RelayCommand<object>(DoAnchorDown);
|
|||
|
|
AnchorUpCommand = new RelayCommand<object>(DoAnchorUp);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 缩放操作
|
|||
|
|
//MouseWheelCommand = new RelayCommand<object>(DoMainZoom);
|
|||
|
|
|
|||
|
|
CanvasMouseDownCommand = new RelayCommand<object>(DoCanvasMouseDown);
|
|||
|
|
CanvasMouseUpCommand = new RelayCommand<object>(DoCanvasMouseUp);
|
|||
|
|
//CanvasMouseMoveCommand = new RelayCommand<object>(DoCanvasMouseMove);
|
|||
|
|
|
|||
|
|
ZoomIncreaseCommand = new RelayCommand<object>(DoZoomIncrease);
|
|||
|
|
ZoomReduceCommand = new RelayCommand<object>(DoZoomReduce);
|
|||
|
|
ZoomResetCommand = new RelayCommand<object>(DoZoomReset);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 这个命令是ItemsControl执行
|
|||
|
|
private void OnDragDrop(object obj)
|
|||
|
|
{
|
|||
|
|
var e = obj as DragEventArgs;
|
|||
|
|
|
|||
|
|
var component_model = e.Data.GetData(typeof(ComponentModel)) as ComponentModel;
|
|||
|
|
|
|||
|
|
// 动态创建出来的节点对象
|
|||
|
|
//object instance = GetInstance(component_model.TargetNode);
|
|||
|
|
// 关联锚点动作事件命令
|
|||
|
|
//(instance as INodeBase).AnchorDownCommand =
|
|||
|
|
// new RelayCommand<object>(OnAnchorDown);
|
|||
|
|
//(instance as INodeBase).AnchorUpCommand =
|
|||
|
|
// new RelayCommand<object>(OnAnchorUp);
|
|||
|
|
|
|||
|
|
// 获取鼠标松开时的坐标
|
|||
|
|
Point point = e.GetPosition((IInputElement)e.Source);
|
|||
|
|
|
|||
|
|
// 创建每个显示节点所对应的数据Model
|
|||
|
|
string model_str = component_model.TargetModel;
|
|||
|
|
NodeModelBase node_model =
|
|||
|
|
(NodeModelBase)this.GetInstance(component_model.TargetModel);
|
|||
|
|
|
|||
|
|
//node_model.TargetNodeObject = instance;
|
|||
|
|
node_model.TargetNodeObject = component_model.TargetNode;
|
|||
|
|
node_model.IsDecision = node_model is DecisionNodeModelBase;
|
|||
|
|
|
|||
|
|
node_model.X = point.X - component_model.W / 2;
|
|||
|
|
node_model.Y = point.Y - component_model.H / 2;
|
|||
|
|
node_model.W = component_model.W;
|
|||
|
|
node_model.H = component_model.H;
|
|||
|
|
|
|||
|
|
|
|||
|
|
NodeList.Add(node_model);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private object GetInstance(string target)
|
|||
|
|
{
|
|||
|
|
string[] _info = target.Split(";");
|
|||
|
|
|
|||
|
|
Assembly assembly =
|
|||
|
|
Assembly.LoadFile(Environment.CurrentDirectory + "/Activities/" + _info[0] + ".dll");
|
|||
|
|
if (assembly == null) return null;
|
|||
|
|
|
|||
|
|
Type type = assembly.GetType(_info[1]);
|
|||
|
|
if (type == null) return null;
|
|||
|
|
|
|||
|
|
return Activator.CreateInstance(type);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DoElementDelete(object obj)
|
|||
|
|
{
|
|||
|
|
if (obj is NodeModelBase model)
|
|||
|
|
{
|
|||
|
|
var links = this.LinkList.Where(l => l.StartId == model.NodeId || l.EndId == model.NodeId)
|
|||
|
|
.ToList();
|
|||
|
|
int len = links.Count;
|
|||
|
|
for (int i = len - 1; i >= 0; i--)
|
|||
|
|
{
|
|||
|
|
this.LinkList.Remove(links[i]);
|
|||
|
|
|
|||
|
|
RestAnchorShow(links[i]);
|
|||
|
|
}
|
|||
|
|
this.NodeList.Remove(model);
|
|||
|
|
|
|||
|
|
// 后续节点的Level信息的同步更新
|
|||
|
|
|
|||
|
|
// .....
|
|||
|
|
}
|
|||
|
|
else if (obj is LinkModel linkModel)
|
|||
|
|
{
|
|||
|
|
this.LinkList.Remove(linkModel);
|
|||
|
|
|
|||
|
|
RestAnchorShow(linkModel);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
isCanvasDrag = false;
|
|||
|
|
isLinking = false;
|
|||
|
|
is_hwakeye_drag = false;
|
|||
|
|
}
|
|||
|
|
private void RestAnchorShow(LinkModel model)
|
|||
|
|
{
|
|||
|
|
var start_node = NodeList.FirstOrDefault(n => n.NodeId == model.StartId);
|
|||
|
|
start_node?.SetAnchorShow(model.StartAnchor, true);
|
|||
|
|
|
|||
|
|
var end_node = NodeList.FirstOrDefault(n => n.NodeId == model.EndId);
|
|||
|
|
end_node?.SetAnchorShow(model.EndAnchor, true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
#region 处理节点移动
|
|||
|
|
bool _is_moving = false;
|
|||
|
|
public NodeModelBase CurrentNodeModel { get; set; } = new NodeModelBase();
|
|||
|
|
|
|||
|
|
Point _node_point = new Point();
|
|||
|
|
// 这个命令是由创建出来的节点触发的
|
|||
|
|
private void OnNodeMouseDown(object obj)
|
|||
|
|
{
|
|||
|
|
var e = obj as MouseEventArgs;
|
|||
|
|
|
|||
|
|
if (CurrentNodeModel != null)
|
|||
|
|
{
|
|||
|
|
CurrentNodeModel.IsShowProperties = false;
|
|||
|
|
CurrentNodeModel.IsSelected = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CurrentNodeModel = (e.Source as FrameworkElement).DataContext as NodeModelBase;
|
|||
|
|
|
|||
|
|
if (CurrentNodeModel != null)
|
|||
|
|
{
|
|||
|
|
CurrentNodeModel.IsSelected = true;
|
|||
|
|
|
|||
|
|
// 修改Model中X和Y 至使页面节点进行位置更新
|
|||
|
|
// 什么时候?鼠标移动的时候
|
|||
|
|
//model.X
|
|||
|
|
_node_point = e.GetPosition((IInputElement)e.Source);
|
|||
|
|
|
|||
|
|
_is_moving = true;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
CurrentNodeModel = new NodeModelBase();
|
|||
|
|
this.OnPropertyChanged(nameof(CurrentNodeModel));
|
|||
|
|
|
|||
|
|
e.Handled = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 命令是由ItemsControl触发的
|
|||
|
|
private void OnNodeMove(object obj)
|
|||
|
|
{
|
|||
|
|
var e = obj as MouseEventArgs;
|
|||
|
|
Point current_point = e.GetPosition((IInputElement)e.Source);
|
|||
|
|
// 节点移动的时候
|
|||
|
|
if (_is_moving)
|
|||
|
|
{
|
|||
|
|
// 根据光标位置 将节点进行移动
|
|||
|
|
CurrentNodeModel.X = current_point.X - _node_point.X;
|
|||
|
|
CurrentNodeModel.Y = current_point.Y - _node_point.Y;
|
|||
|
|
|
|||
|
|
#region 更新连线坐标
|
|||
|
|
var start_list = LinkList.Where(ll => ll.StartId == CurrentNodeModel.NodeId);
|
|||
|
|
var end_list = LinkList.Where(ll => ll.EndId == CurrentNodeModel.NodeId);
|
|||
|
|
|
|||
|
|
// 更新连线的起始端坐标
|
|||
|
|
var node = start_list.FirstOrDefault(sl => sl.StartAnchor == "T");
|
|||
|
|
if (node != null)
|
|||
|
|
{
|
|||
|
|
node.StartX = CurrentNodeModel.X + CurrentNodeModel.W / 2;
|
|||
|
|
node.StartY = CurrentNodeModel.Y + 3;
|
|||
|
|
}
|
|||
|
|
node = start_list.FirstOrDefault(sl => sl.StartAnchor == "B");
|
|||
|
|
if (node != null)
|
|||
|
|
{
|
|||
|
|
node.StartX = CurrentNodeModel.X + CurrentNodeModel.W / 2;
|
|||
|
|
node.StartY = CurrentNodeModel.Y + CurrentNodeModel.H - 3;
|
|||
|
|
}
|
|||
|
|
node = start_list.FirstOrDefault(sl => sl.StartAnchor == "L");
|
|||
|
|
if (node != null)
|
|||
|
|
{
|
|||
|
|
node.StartX = CurrentNodeModel.X + 3;
|
|||
|
|
node.StartY = CurrentNodeModel.Y + CurrentNodeModel.H / 2;
|
|||
|
|
}
|
|||
|
|
node = start_list.FirstOrDefault(sl => sl.StartAnchor == "R");
|
|||
|
|
if (node != null)
|
|||
|
|
{
|
|||
|
|
node.StartX = CurrentNodeModel.X + CurrentNodeModel.W - 3;
|
|||
|
|
node.StartY = CurrentNodeModel.Y + CurrentNodeModel.H / 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新连线的终止端坐标
|
|||
|
|
node = end_list.FirstOrDefault(sl => sl.EndAnchor == "T");
|
|||
|
|
if (node != null)
|
|||
|
|
{
|
|||
|
|
node.EndX = CurrentNodeModel.X + CurrentNodeModel.W / 2;
|
|||
|
|
node.EndY = CurrentNodeModel.Y + 3;
|
|||
|
|
}
|
|||
|
|
node = end_list.FirstOrDefault(sl => sl.EndAnchor == "B");
|
|||
|
|
if (node != null)
|
|||
|
|
{
|
|||
|
|
node.EndX = CurrentNodeModel.X + CurrentNodeModel.W / 2;
|
|||
|
|
node.EndY = CurrentNodeModel.Y + CurrentNodeModel.H - 3;
|
|||
|
|
}
|
|||
|
|
node = end_list.FirstOrDefault(sl => sl.EndAnchor == "L");
|
|||
|
|
if (node != null)
|
|||
|
|
{
|
|||
|
|
node.EndX = CurrentNodeModel.X + 3;
|
|||
|
|
node.EndY = CurrentNodeModel.Y + CurrentNodeModel.H / 2;
|
|||
|
|
}
|
|||
|
|
node = end_list.FirstOrDefault(sl => sl.EndAnchor == "R");
|
|||
|
|
if (node != null)
|
|||
|
|
{
|
|||
|
|
node.EndX = CurrentNodeModel.X + CurrentNodeModel.W - 3;
|
|||
|
|
node.EndY = CurrentNodeModel.Y + CurrentNodeModel.H / 2;
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
e.Handled = true;
|
|||
|
|
}
|
|||
|
|
if (isLinking)
|
|||
|
|
{
|
|||
|
|
// 更新当前LinkModel的终点坐标?
|
|||
|
|
linkModel.EndX = current_point.X;
|
|||
|
|
linkModel.EndY = current_point.Y;
|
|||
|
|
|
|||
|
|
e.Handled = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 鼠标左键在画布上弹起
|
|||
|
|
private void OnNodeMouseUp()
|
|||
|
|
{
|
|||
|
|
_is_moving = false;
|
|||
|
|
|
|||
|
|
// 清除临时Link
|
|||
|
|
if (isLinking && linkModel != null)
|
|||
|
|
{
|
|||
|
|
LinkList.Remove(linkModel);
|
|||
|
|
linkModel = null;
|
|||
|
|
isLinking = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 锚点处理
|
|||
|
|
LinkModel linkModel;
|
|||
|
|
bool isLinking = false;
|
|||
|
|
// 当在锚点按下的时候
|
|||
|
|
private void DoAnchorDown(object obj)
|
|||
|
|
{
|
|||
|
|
string[] info = obj.ToString().Split(";");
|
|||
|
|
string id = info[0];
|
|||
|
|
// 确定对应的节点(Model)
|
|||
|
|
NodeModelBase model = NodeList.FirstOrDefault(n => n.NodeId == id);
|
|||
|
|
if (model == null) return;
|
|||
|
|
|
|||
|
|
linkModel = new LinkModel
|
|||
|
|
{
|
|||
|
|
StartId = id,
|
|||
|
|
StartAnchor = info[1]
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (info[1] == "T")
|
|||
|
|
{
|
|||
|
|
linkModel.StartX = model.X + (model.W / 2);
|
|||
|
|
linkModel.StartY = model.Y + 3;
|
|||
|
|
}
|
|||
|
|
else if (info[1] == "B")
|
|||
|
|
{
|
|||
|
|
linkModel.StartX = model.X + (model.W / 2);
|
|||
|
|
linkModel.StartY = model.Y + model.H - 3;
|
|||
|
|
}
|
|||
|
|
else if (info[1] == "L")
|
|||
|
|
{
|
|||
|
|
linkModel.StartX = model.X + 3;
|
|||
|
|
linkModel.StartY = model.Y + model.H / 2;
|
|||
|
|
}
|
|||
|
|
else if (info[1] == "R")
|
|||
|
|
{
|
|||
|
|
linkModel.StartX = model.X + model.W - 3;
|
|||
|
|
linkModel.StartY = model.Y + model.H / 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (model is DecisionNodeModelBase dnmb)
|
|||
|
|
{
|
|||
|
|
// T/F
|
|||
|
|
linkModel.Condition = info[2];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
linkModel.EndAnchor = "N";
|
|||
|
|
linkModel.EndX = linkModel.StartX;
|
|||
|
|
linkModel.EndY = linkModel.StartY;
|
|||
|
|
//
|
|||
|
|
LinkList.Add(linkModel);
|
|||
|
|
isLinking = true;
|
|||
|
|
|
|||
|
|
isCanvasDrag = false;
|
|||
|
|
}
|
|||
|
|
// 当在锚点释放鼠标的时候
|
|||
|
|
private void DoAnchorUp(object obj)
|
|||
|
|
{
|
|||
|
|
string[] info = obj.ToString().Split(";");
|
|||
|
|
string id = info[0];
|
|||
|
|
// 确定对应的节点(Model)
|
|||
|
|
NodeModelBase model = NodeList.FirstOrDefault(n => n.NodeId == id);
|
|||
|
|
if (model == null || linkModel == null)
|
|||
|
|
{
|
|||
|
|
//LinkList.Remove(linkModel);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
linkModel.EndId = id;
|
|||
|
|
linkModel.EndAnchor = info[1];
|
|||
|
|
|
|||
|
|
if (info[1] == "T")
|
|||
|
|
{
|
|||
|
|
var result = SetLinkTopPoint(model);
|
|||
|
|
linkModel.EndX = result.x;
|
|||
|
|
linkModel.EndY = result.y;
|
|||
|
|
}
|
|||
|
|
else if (info[1] == "B")
|
|||
|
|
{
|
|||
|
|
linkModel.EndX = model.X + (model.W / 2);
|
|||
|
|
linkModel.EndY = model.Y + model.H - 3;
|
|||
|
|
}
|
|||
|
|
else if (info[1] == "L")
|
|||
|
|
{
|
|||
|
|
linkModel.EndX = model.X + 3;
|
|||
|
|
linkModel.EndY = model.Y + model.H / 2;
|
|||
|
|
}
|
|||
|
|
else if (info[1] == "R")
|
|||
|
|
{
|
|||
|
|
linkModel.EndX = model.X + model.W - 3;
|
|||
|
|
linkModel.EndY = model.Y + model.H / 2;
|
|||
|
|
}
|
|||
|
|
//LinkList.Add(linkModel);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 处理连接成功的节点中当前连线的锚点状态
|
|||
|
|
// 设置终节点的对应的锚点显示
|
|||
|
|
model.SetAnchorShow(info[1], false);
|
|||
|
|
// 设置起始节点的对应铁锚点显示
|
|||
|
|
var start = NodeList.FirstOrDefault(n => n.NodeId == linkModel.StartId);
|
|||
|
|
if (start != null)
|
|||
|
|
start.SetAnchorShow(linkModel.StartAnchor, false);
|
|||
|
|
|
|||
|
|
model.FlowLevel.Add(start.FlowLevel[0] + 1);
|
|||
|
|
|
|||
|
|
isLinking = false;
|
|||
|
|
|
|||
|
|
isCanvasDrag = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private (double x, double y) SetLinkTopPoint(NodeModelBase model)
|
|||
|
|
{
|
|||
|
|
double X = model.X + (model.W / 2);
|
|||
|
|
double Y = model.Y + 3;
|
|||
|
|
return (X, Y);
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
|
|||
|
|
#region 执行节点逻辑
|
|||
|
|
private void DoRunFlowchart()
|
|||
|
|
{
|
|||
|
|
if (cts != null && cts.IsCancellationRequested)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
this.Log("流程", "[开始]");
|
|||
|
|
Task.Run(() =>
|
|||
|
|
{
|
|||
|
|
//Thread.Sleep(2000);
|
|||
|
|
|
|||
|
|
DoRunFirst();
|
|||
|
|
|
|||
|
|
this.Log("流程", "[结束]");
|
|||
|
|
|
|||
|
|
ReleaseIntPrt();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ReleaseIntPrt()
|
|||
|
|
{
|
|||
|
|
var args = this.ArgumentList.Where(a => a.ArgType == "IntPtr").ToList();
|
|||
|
|
foreach (var item in args)
|
|||
|
|
{
|
|||
|
|
object v = item.Value ?? 0;
|
|||
|
|
if (IntPtr.TryParse(v.ToString(), out IntPtr ptr))
|
|||
|
|
{
|
|||
|
|
DeleteObject(ptr);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DoRunFirst()
|
|||
|
|
{
|
|||
|
|
// 开始按顺序执行每个节点中的逻辑
|
|||
|
|
var node = this.NodeList.FirstOrDefault(n => n.IsStart);
|
|||
|
|
if (node == null)
|
|||
|
|
{
|
|||
|
|
this.Log(node.NodeName, "流程异常,未发现起始节点!");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (cts != null && cts.IsCancellationRequested)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
DoRun(node);
|
|||
|
|
|
|||
|
|
if (cts != null && cts.IsCancellationRequested)
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DoRun(NodeModelBase node)
|
|||
|
|
{
|
|||
|
|
if (cts != null && cts.IsCancellationRequested)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
//Thread.Sleep(2000);
|
|||
|
|
|
|||
|
|
Stopwatch stopwatch = Stopwatch.StartNew();
|
|||
|
|
|
|||
|
|
// 这里是每个节点执行的逻辑
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (cts != null && cts.IsCancellationRequested)
|
|||
|
|
return;
|
|||
|
|
if (node is DecisionNodeModelBase dnmb)
|
|||
|
|
{
|
|||
|
|
// True / False
|
|||
|
|
bool result = dnmb.Decision(this);
|
|||
|
|
|
|||
|
|
// 找线
|
|||
|
|
var lm = this.LinkList.FirstOrDefault(l => l.StartId == node.NodeId && (l.Condition == "T") == result);
|
|||
|
|
if (lm == null)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
// 找线另一端的节点
|
|||
|
|
var next_node = this.NodeList.FirstOrDefault(n => n.NodeId == lm.EndId);
|
|||
|
|
if (next_node != null)
|
|||
|
|
this.DoRun(next_node);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (!node.IsStart)
|
|||
|
|
{
|
|||
|
|
// 执行节点中对应的逻辑
|
|||
|
|
node.IsRunning = true;
|
|||
|
|
stopwatch.Restart();
|
|||
|
|
this.Log(node.NodeName, "[执行]");
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (cts != null && cts.IsCancellationRequested)
|
|||
|
|
return;
|
|||
|
|
node.Execute(this);
|
|||
|
|
|
|||
|
|
if (cts != null && cts.IsCancellationRequested)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
|
|||
|
|
Thread.Sleep(1000);
|
|||
|
|
|
|||
|
|
stopwatch.Stop();
|
|||
|
|
node.Duration = stopwatch.ElapsedMilliseconds;
|
|||
|
|
node.IsRunning = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (cts != null && cts.IsCancellationRequested)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
// 执行完成后,继续下个节点
|
|||
|
|
var ls = this.LinkList.Where(l => l.StartId == node.NodeId);
|
|||
|
|
foreach (var l in ls)
|
|||
|
|
{
|
|||
|
|
var next_node = this.NodeList.FirstOrDefault(n => n.NodeId == l.EndId);
|
|||
|
|
if (next_node != null)
|
|||
|
|
this.DoRun(next_node);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
stopwatch.Stop();
|
|||
|
|
node.Duration = stopwatch.ElapsedMilliseconds;
|
|||
|
|
node.IsRunning = false;
|
|||
|
|
|
|||
|
|
this.Log(node.NodeName, ex.Message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CancellationTokenSource cts;
|
|||
|
|
private void DoCircleExecute()
|
|||
|
|
{
|
|||
|
|
this.Log("流程", "[开始]");
|
|||
|
|
cts = new CancellationTokenSource();
|
|||
|
|
Task.Run(() =>
|
|||
|
|
{
|
|||
|
|
do
|
|||
|
|
{
|
|||
|
|
DoRunFirst();
|
|||
|
|
} while (!cts.IsCancellationRequested);
|
|||
|
|
|
|||
|
|
|
|||
|
|
this.Log("流程", "[结束]");
|
|||
|
|
|
|||
|
|
this.ReleaseIntPrt();
|
|||
|
|
}, cts.Token);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DoStopExecute()
|
|||
|
|
{
|
|||
|
|
cts?.Cancel();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
NodeModelBase _currentStepNode;
|
|||
|
|
bool _decisionResult = false;
|
|||
|
|
private void DoStepExecute()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
//if (_currentStepNode == null)
|
|||
|
|
//{
|
|||
|
|
// var start = this.NodeList.First();
|
|||
|
|
// var link = this.LinkList.FirstOrDefault(l => l.StartId == _currentStepNode.NodeId);
|
|||
|
|
// _currentStepNode = this.NodeList.FirstOrDefault(n => n.NodeId == link.EndId);
|
|||
|
|
//}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
//if (_currentStepNode is DecisionNodeModelBase dnmb)
|
|||
|
|
//{
|
|||
|
|
// _decisionResult = dnmb.Decision(this);
|
|||
|
|
//}
|
|||
|
|
//else
|
|||
|
|
//{
|
|||
|
|
// _currentStepNode.Execute(this);
|
|||
|
|
// var ls = this.LinkList.Where(l => l.StartId == _currentStepNode.NodeId).ToList();
|
|||
|
|
// _currentStepNode = this.NodeList.FirstOrDefault(n => n.NodeId == ls[0].EndId);
|
|||
|
|
//}
|
|||
|
|
|
|||
|
|
var ns = this.NodeList.Where(n => n.FlowLevel.Contains(_currentLevel)).ToList();
|
|||
|
|
|
|||
|
|
var ids = this.LinkList.ToList()
|
|||
|
|
.Where(l => l.EndId == ns[_subIndex].NodeId &&
|
|||
|
|
(l.Condition == "T") == _decisionResult).ToList()
|
|||
|
|
.Select(ll => ll.EndId).ToList();
|
|||
|
|
ns = ns.Where(n => ids.Contains(n.NodeId)).ToList();
|
|||
|
|
|
|||
|
|
//if (this.LinkList.ToList().Exists(l => l.EndId == ns[_subIndex].NodeId &&
|
|||
|
|
// (l.Condition == "T") == _decisionResult))
|
|||
|
|
{
|
|||
|
|
if (ns[_subIndex] is DecisionNodeModelBase dnmb)
|
|||
|
|
{
|
|||
|
|
_decisionResult = dnmb.Decision(this);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ns[_subIndex].Execute(this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_subIndex++;
|
|||
|
|
if (_subIndex >= ns.Count)
|
|||
|
|
{
|
|||
|
|
_currentLevel = ns[_subIndex - 1].FlowLevel[0] + 1;
|
|||
|
|
if (_currentLevel > this.NodeList.Max(n => n.FlowLevel.Max(fl => fl)))
|
|||
|
|
_currentLevel = 1;
|
|||
|
|
_subIndex = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
int _currentLevel = 1;
|
|||
|
|
int _subIndex = 0;
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
#region 添加参数
|
|||
|
|
private void DoAddArgument()
|
|||
|
|
{
|
|||
|
|
ArgumentList.Add(new FlowArgModel());
|
|||
|
|
}
|
|||
|
|
private void DoDelArgument(object obj)
|
|||
|
|
{
|
|||
|
|
ArgumentList.Remove(obj as FlowArgModel);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DoSelectFolder(object obj)
|
|||
|
|
{
|
|||
|
|
var model = obj as NodeArgModel;
|
|||
|
|
|
|||
|
|
OpenFolderDialog dialog = new OpenFolderDialog();
|
|||
|
|
if (dialog.ShowDialog() == true)
|
|||
|
|
model.ArgValue = dialog.FolderName;
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 这里内存一直增长 需要优化
|
|||
|
|
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
|
|||
|
|
public static extern bool DeleteObject(IntPtr hObject);
|
|||
|
|
|
|||
|
|
public void ShowImage(IntPtr img_handler)
|
|||
|
|
{
|
|||
|
|
BitmapImage bitmapImage = new BitmapImage();
|
|||
|
|
using (var ms = new MemoryStream())
|
|||
|
|
{
|
|||
|
|
System.Drawing.Bitmap bitmap =
|
|||
|
|
System.Drawing.Bitmap.FromHbitmap(img_handler);
|
|||
|
|
|
|||
|
|
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
|
|||
|
|
ms.Position = 0;
|
|||
|
|
|
|||
|
|
bitmapImage.BeginInit();
|
|||
|
|
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
|||
|
|
bitmapImage.StreamSource = ms;
|
|||
|
|
bitmapImage.EndInit();
|
|||
|
|
bitmapImage.Freeze();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PreviewImage = bitmapImage;
|
|||
|
|
//DeleteObject(img_handler);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
public string FilePath { get; set; }
|
|||
|
|
|
|||
|
|
public void Save()
|
|||
|
|
{
|
|||
|
|
// 选择保存地址---再保存的进候需要选择?
|
|||
|
|
if (string.IsNullOrEmpty(FilePath))
|
|||
|
|
{
|
|||
|
|
SaveFileDialog dialog = new SaveFileDialog();
|
|||
|
|
dialog.Filter = "流程文件(*.flw)|*.flw";
|
|||
|
|
if (dialog.ShowDialog() == true)
|
|||
|
|
{
|
|||
|
|
FilePath = dialog.FileName;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// Bug:简单的Json文件保存会导致实例丢失 无法执行实例中的方法
|
|||
|
|
// 需要处理!!!!!
|
|||
|
|
|
|||
|
|
// 每个子项单独保存 记录类型名称
|
|||
|
|
// 通信序列化对象进行多态对象的序列化与反序列,需要对基类进行配置
|
|||
|
|
string node_json = System.Text.Json.JsonSerializer.Serialize(this.NodeList);
|
|||
|
|
string link_json = System.Text.Json.JsonSerializer.Serialize(this.LinkList);
|
|||
|
|
string arg_json = System.Text.Json.JsonSerializer.Serialize(this.ArgumentList);
|
|||
|
|
|
|||
|
|
string temp =
|
|||
|
|
this.Title + "@#$#@" +
|
|||
|
|
node_json + "@#$#@" +
|
|||
|
|
link_json + "@#$#@" +
|
|||
|
|
arg_json;
|
|||
|
|
|
|||
|
|
System.IO.File.WriteAllText(FilePath, temp);
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
this.Log("流程保存", ex.Message);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
#region 画布缩放
|
|||
|
|
public void DoMainZoom(object sender, MouseWheelEventArgs e)
|
|||
|
|
{
|
|||
|
|
//e.GetPosition
|
|||
|
|
this.MainZoom += e.Delta > 0 ? 0.05 : -0.05;
|
|||
|
|
|
|||
|
|
// 检查放缩放比, 在1.5和0.5之间缩放 倍数
|
|||
|
|
if (MainZoom < 0.5)
|
|||
|
|
MainZoom = 0.5;
|
|||
|
|
if (MainZoom > 1.5)
|
|||
|
|
MainZoom = 1.5;
|
|||
|
|
|
|||
|
|
|
|||
|
|
var hwakeye = (sender as FrameworkElement).Tag;
|
|||
|
|
this.CheckCanvasLocation(sender, hwakeye);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
public void DoCanvasMouseMove(object? sender, MouseEventArgs e)
|
|||
|
|
{
|
|||
|
|
if (isCanvasDrag && !isLinking && !_is_moving)
|
|||
|
|
{
|
|||
|
|
Point p = e.GetPosition((IInputElement)e.Source);
|
|||
|
|
//
|
|||
|
|
double x = p.X - startCanvas.X;
|
|||
|
|
double y = p.Y - startCanvas.Y;
|
|||
|
|
|
|||
|
|
DragX += x;
|
|||
|
|
DragY += y;
|
|||
|
|
|
|||
|
|
var hwakeye = (sender as FrameworkElement).Tag;
|
|||
|
|
CheckCanvasLocation(sender, hwakeye);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void CheckCanvasLocation(object? sender, object hwakeye)
|
|||
|
|
{
|
|||
|
|
var canvas = sender as FrameworkElement;
|
|||
|
|
|
|||
|
|
var parent = canvas.Parent as FrameworkElement;
|
|||
|
|
// -250 -200
|
|||
|
|
Point left_top = canvas.TranslatePoint(new Point(0, 0), parent);
|
|||
|
|
Point right_bottom = canvas.TranslatePoint(new Point(canvas.ActualWidth, canvas.ActualHeight), parent);
|
|||
|
|
double trans_w = right_bottom.X - left_top.X;
|
|||
|
|
double trans_h = right_bottom.Y - left_top.Y;
|
|||
|
|
|
|||
|
|
if (left_top.X > 0)
|
|||
|
|
{
|
|||
|
|
DragX = (trans_w - parent.ActualWidth) / 2;
|
|||
|
|
}
|
|||
|
|
if (left_top.Y > 0)
|
|||
|
|
{
|
|||
|
|
DragY = (trans_h - parent.ActualHeight) / 2;
|
|||
|
|
}
|
|||
|
|
if (right_bottom.X < parent.ActualWidth)
|
|||
|
|
{
|
|||
|
|
DragX = (trans_w - parent.ActualWidth) / 2 * -1;
|
|||
|
|
}
|
|||
|
|
if (right_bottom.Y < parent.ActualHeight)
|
|||
|
|
{
|
|||
|
|
DragY = (trans_h - parent.ActualHeight) / 2 * -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 鹰眼缩放
|
|||
|
|
this.HwakeyeZoom = parent.ActualWidth / trans_w / 0.5;
|
|||
|
|
|
|||
|
|
// 鹰眼位移
|
|||
|
|
var fe = hwakeye as FrameworkElement;
|
|||
|
|
this.HwakeyeDragX = (DragX * -1 / canvas.ActualWidth) * fe.ActualWidth;
|
|||
|
|
this.HwakeyeDragY = (DragY * -1 / canvas.ActualHeight) * fe.ActualHeight;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DoCanvasMouseUp(object? obj)
|
|||
|
|
{
|
|||
|
|
isCanvasDrag = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool isCanvasDrag = false;
|
|||
|
|
Point startCanvas = new Point(0, 0);
|
|||
|
|
private void DoCanvasMouseDown(object? obj)
|
|||
|
|
{
|
|||
|
|
var e = obj as MouseButtonEventArgs;
|
|||
|
|
isCanvasDrag = true;
|
|||
|
|
startCanvas = e.GetPosition((IInputElement)e.Source);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
bool is_hwakeye_drag = false;
|
|||
|
|
Point hwakeye_down_p = new Point(0, 0);
|
|||
|
|
FrameworkElement fe_hwakeye_view = null;
|
|||
|
|
public void HwakeyeViewMouseDown(object sender, MouseButtonEventArgs e)
|
|||
|
|
{
|
|||
|
|
is_hwakeye_drag = true;
|
|||
|
|
hwakeye_down_p = e.GetPosition((IInputElement)sender);
|
|||
|
|
fe_hwakeye_view = sender as FrameworkElement;
|
|||
|
|
}
|
|||
|
|
public void HwakeyeMouseMove(object sender, MouseEventArgs e)
|
|||
|
|
{
|
|||
|
|
if (is_hwakeye_drag)
|
|||
|
|
{
|
|||
|
|
Point p = e.GetPosition((IInputElement)e.Source);
|
|||
|
|
|
|||
|
|
double x = p.X - hwakeye_down_p.X;
|
|||
|
|
double y = p.Y - hwakeye_down_p.Y;
|
|||
|
|
|
|||
|
|
HwakeyeDragX += x;
|
|||
|
|
HwakeyeDragY += y;
|
|||
|
|
|
|||
|
|
// 边缘检测
|
|||
|
|
var parent = sender as FrameworkElement;
|
|||
|
|
Point left_top = fe_hwakeye_view.TranslatePoint(new Point(0, 0), parent);
|
|||
|
|
Point right_bottom = fe_hwakeye_view.TranslatePoint(new Point(fe_hwakeye_view.ActualWidth, fe_hwakeye_view.ActualHeight), parent);
|
|||
|
|
double trans_w = right_bottom.X - left_top.X;
|
|||
|
|
double trans_h = right_bottom.Y - left_top.Y;
|
|||
|
|
|
|||
|
|
if (left_top.X < 0)
|
|||
|
|
{
|
|||
|
|
HwakeyeDragX = (trans_w - parent.ActualWidth) / 2;
|
|||
|
|
}
|
|||
|
|
if (left_top.Y < 0)
|
|||
|
|
{
|
|||
|
|
HwakeyeDragY = (trans_h - parent.ActualHeight) / 2;
|
|||
|
|
}
|
|||
|
|
if (right_bottom.X > parent.ActualWidth)
|
|||
|
|
{
|
|||
|
|
HwakeyeDragX = (trans_w - parent.ActualWidth) / 2 * -1;
|
|||
|
|
}
|
|||
|
|
if (right_bottom.Y > parent.ActualHeight)
|
|||
|
|
{
|
|||
|
|
HwakeyeDragY = (trans_h - parent.ActualHeight) / 2 * -1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 同步画布的位移
|
|||
|
|
var canvas = (sender as FrameworkElement).Tag as FrameworkElement;
|
|||
|
|
DragX = HwakeyeDragX * -1 / parent.ActualWidth * canvas.ActualWidth;
|
|||
|
|
DragY = HwakeyeDragY * -1 / parent.ActualHeight * canvas.ActualHeight;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
public void HwakeyeMouseUp(object sender, MouseButtonEventArgs e)
|
|||
|
|
{
|
|||
|
|
is_hwakeye_drag = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
private void DoZoomIncrease(object? obj)
|
|||
|
|
{
|
|||
|
|
this.MainZoom += 0.05;
|
|||
|
|
|
|||
|
|
// 检查放缩放比, 在1.5和0.5之间缩放 倍数
|
|||
|
|
if (MainZoom > 1.5)
|
|||
|
|
MainZoom = 1.5;
|
|||
|
|
|
|||
|
|
var hwakeye = (obj as FrameworkElement).Tag;
|
|||
|
|
this.CheckCanvasLocation(obj, hwakeye);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DoZoomReduce(object? obj)
|
|||
|
|
{
|
|||
|
|
this.MainZoom -= 0.05;
|
|||
|
|
|
|||
|
|
// 检查放缩放比, 在1.5和0.5之间缩放 倍数
|
|||
|
|
if (MainZoom < 0.5)
|
|||
|
|
MainZoom = 0.5;
|
|||
|
|
|
|||
|
|
var hwakeye = (obj as FrameworkElement).Tag;
|
|||
|
|
this.CheckCanvasLocation(obj, hwakeye);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void DoZoomReset(object? obj)
|
|||
|
|
{
|
|||
|
|
this.MainZoom = 1;
|
|||
|
|
|
|||
|
|
var hwakeye = (obj as FrameworkElement).Tag;
|
|||
|
|
this.CheckCanvasLocation(obj, hwakeye);
|
|||
|
|
}
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
private void Log(string node_name, string message)
|
|||
|
|
{
|
|||
|
|
Application.Current.Dispatcher.Invoke(new Action(() =>
|
|||
|
|
{
|
|||
|
|
// 数据量增大
|
|||
|
|
this.LogList.Add(new LogModel
|
|||
|
|
{
|
|||
|
|
Time = DateTime.Now,
|
|||
|
|
NodeName = node_name,
|
|||
|
|
LogMessage = message,
|
|||
|
|
});
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|