Files
wpf-visual-process-framework/VisionFrame/ViewModels/FlowTabViewModel.cs

1114 lines
36 KiB
C#
Raw Normal View History

2025-07-14 21:08:46 +08:00
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,
});
}));
}
}
}