mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-02 07:40:48 +08:00
取消缩放功能(有问题)
This commit is contained in:
118
.editorconfig
118
.editorconfig
@@ -2,3 +2,121 @@
|
||||
|
||||
# CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
|
||||
dotnet_diagnostic.CS8618.severity = warning
|
||||
|
||||
[*.cs]
|
||||
#### 命名样式 ####
|
||||
|
||||
# 命名规则
|
||||
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||
|
||||
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||
|
||||
# 符号规范
|
||||
|
||||
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.interface.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.types.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
# 命名样式
|
||||
|
||||
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||
dotnet_naming_style.begins_with_i.required_suffix =
|
||||
dotnet_naming_style.begins_with_i.word_separator =
|
||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
csharp_using_directive_placement = outside_namespace:silent
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_lambdas = true:silent
|
||||
csharp_style_expression_bodied_local_functions = false:silent
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_indent_labels = one_less_than_current
|
||||
|
||||
[*.vb]
|
||||
#### 命名样式 ####
|
||||
|
||||
# 命名规则
|
||||
|
||||
dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion
|
||||
dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface
|
||||
dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始
|
||||
|
||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion
|
||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型
|
||||
dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
|
||||
|
||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion
|
||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员
|
||||
dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法
|
||||
|
||||
# 符号规范
|
||||
|
||||
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
|
||||
dotnet_naming_symbols.interface.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum
|
||||
dotnet_naming_symbols.类型.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
|
||||
dotnet_naming_symbols.类型.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected
|
||||
dotnet_naming_symbols.非字段成员.required_modifiers =
|
||||
|
||||
# 命名样式
|
||||
|
||||
dotnet_naming_style.以_i_开始.required_prefix = I
|
||||
dotnet_naming_style.以_i_开始.required_suffix =
|
||||
dotnet_naming_style.以_i_开始.word_separator =
|
||||
dotnet_naming_style.以_i_开始.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.帕斯卡拼写法.required_prefix =
|
||||
dotnet_naming_style.帕斯卡拼写法.required_suffix =
|
||||
dotnet_naming_style.帕斯卡拼写法.word_separator =
|
||||
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.帕斯卡拼写法.required_prefix =
|
||||
dotnet_naming_style.帕斯卡拼写法.required_suffix =
|
||||
dotnet_naming_style.帕斯卡拼写法.word_separator =
|
||||
dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case
|
||||
|
||||
[*.{cs,vb}]
|
||||
end_of_line = crlf
|
||||
dotnet_style_qualification_for_field = false:silent
|
||||
dotnet_style_qualification_for_property = false:silent
|
||||
dotnet_style_qualification_for_method = false:silent
|
||||
dotnet_style_qualification_for_event = false:silent
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
@@ -15,68 +15,43 @@ namespace Serein.NodeFlow.Tool
|
||||
|
||||
public class TcsSignal<TSignal> where TSignal : struct, Enum
|
||||
{
|
||||
//public ConcurrentDictionary<TSignal, Queue<TaskCompletionSource<object>>> TcsEvent { get; } = new();
|
||||
public ConcurrentDictionary<TSignal, TaskCompletionSource<object>> TcsEvent { get; } = new();
|
||||
public ConcurrentDictionary<TSignal, object> TcsValue { get; } = new();
|
||||
|
||||
public ConcurrentDictionary<TSignal, Stack<TaskCompletionSource<object>>> TcsEvent { get; } = new();
|
||||
|
||||
// public object tcsObj = new object();
|
||||
|
||||
public bool TriggerSignal<T>(TSignal signal, T state)
|
||||
/// <summary>
|
||||
/// 触发信号
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="signal">信号</param>
|
||||
/// <param name="value">传递的参数</param>
|
||||
/// <returns>是否成功触发</returns>
|
||||
public bool TriggerSignal<T>(TSignal signal, T value)
|
||||
{
|
||||
if (TcsEvent.TryRemove(signal, out var waitTcss))
|
||||
if (TcsEvent.TryRemove(signal, out var waitTcs))
|
||||
{
|
||||
while (waitTcss.Count > 0)
|
||||
{
|
||||
|
||||
waitTcss.Pop().SetResult(state);
|
||||
|
||||
}
|
||||
waitTcs.SetResult(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public TaskCompletionSource<object> CreateTcs(TSignal signal)
|
||||
{
|
||||
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
TcsEvent.GetOrAdd(signal, _ => new Stack<TaskCompletionSource<object>>()).Push(tcs);
|
||||
var tcs = TcsEvent.GetOrAdd(signal,_ = new TaskCompletionSource<object>());
|
||||
return tcs;
|
||||
|
||||
|
||||
|
||||
}
|
||||
//public TaskCompletionSource<object> GetOrCreateTcs(TSignal signal)
|
||||
//{
|
||||
// lock (tcsObj)
|
||||
// {
|
||||
// var tcs = TcsEvent.GetOrAdd(signal, _ => new TaskCompletionSource<object>());
|
||||
// if (tcs.Task.IsCompleted)
|
||||
// {
|
||||
// TcsEvent.TryRemove(signal, out _);
|
||||
// tcs = new TaskCompletionSource<object>();
|
||||
// TcsEvent[signal] = tcs;
|
||||
// }
|
||||
// return tcs;
|
||||
// }
|
||||
//}
|
||||
|
||||
public void CancelTask()
|
||||
{
|
||||
lock (TcsEvent)
|
||||
{
|
||||
|
||||
foreach (var tcss in TcsEvent.Values)
|
||||
foreach (var tcs in TcsEvent.Values)
|
||||
{
|
||||
while (tcss.Count > 0)
|
||||
{
|
||||
tcss.Pop().SetException(new TcsSignalException("Task Cancel"));
|
||||
}
|
||||
tcs.SetException(new TcsSignalException("任务取消"));
|
||||
}
|
||||
TcsEvent.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:custom="clr-namespace:Serein.WorkBench.Node.View"
|
||||
Title="Dynamic Node Flow" Height="700" Width="1200"
|
||||
AllowDrop="True" Drop="Window_Drop" DragOver="Window_DragOver"
|
||||
SizeChanged ="Window_SizeChanged"
|
||||
Loaded="Window_Loaded"
|
||||
Closing="Window_Closing">
|
||||
|
||||
@@ -77,17 +78,19 @@
|
||||
x:Name="FlowChartScrollViewer"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
|
||||
<Canvas x:Name="FlowChartCanvas"
|
||||
Background="#F2EEE8"
|
||||
AllowDrop="True"
|
||||
MouseDown="FlowChartCanvas_MouseDown"
|
||||
MouseMove="FlowChartCanvas_MouseMove"
|
||||
MouseUp="FlowChartCanvas_MouseUp"
|
||||
MouseWheel="FlowChartCanvas_MouseWheel"
|
||||
Drop="FlowChartCanvas_Drop"
|
||||
DragOver="FlowChartCanvas_DragOver"/>
|
||||
<Canvas
|
||||
x:Name="FlowChartCanvas"
|
||||
Background="#F2EEE8"
|
||||
AllowDrop="True"
|
||||
MouseDown="FlowChartCanvas_MouseDown"
|
||||
MouseMove="FlowChartCanvas_MouseMove"
|
||||
MouseUp="FlowChartCanvas_MouseUp"
|
||||
MouseWheel="FlowChartCanvas_MouseWheel"
|
||||
Drop="FlowChartCanvas_Drop"
|
||||
DragOver="FlowChartCanvas_DragOver"/>
|
||||
</ScrollViewer>
|
||||
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
@@ -1294,8 +1294,9 @@ namespace Serein.WorkBench
|
||||
if (e.MiddleButton == MouseButtonState.Pressed)
|
||||
{
|
||||
IsCanvasDragging = true;
|
||||
startPoint = e.GetPosition(this);
|
||||
startPoint = e.GetPosition(FlowChartScrollViewer);
|
||||
FlowChartCanvas.CaptureMouse();
|
||||
e.Handled = true; // 防止事件传播影响其他控件
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1305,80 +1306,131 @@ namespace Serein.WorkBench
|
||||
{
|
||||
IsCanvasDragging = false;
|
||||
FlowChartCanvas.ReleaseMouseCapture();
|
||||
|
||||
foreach(var line in connections)
|
||||
{
|
||||
line.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 缩放功能有问题
|
||||
private void FlowChartCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
|
||||
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
||||
{
|
||||
double scale = e.Delta > 0 ? 1.1 : 0.9;
|
||||
scaleTransform.ScaleX *= scale;
|
||||
scaleTransform.ScaleY *= scale;
|
||||
//double scale = e.Delta > 0 ? 0.1 : -0.1;
|
||||
//scaleTransform.ScaleX += scale;
|
||||
//scaleTransform.ScaleY += scale;
|
||||
//AdjustCanvasSize();
|
||||
|
||||
|
||||
//double zoomFactor = e.Delta > 0 ? 1.1 : 0.9;
|
||||
|
||||
//// 获取鼠标相对于Canvas的位置
|
||||
//Point mousePosition = e.GetPosition(FlowChartCanvas);
|
||||
|
||||
//// 计算缩放后的Canvas中心位置
|
||||
//double absoluteX = mousePosition.X * scaleTransform.ScaleX;
|
||||
//double absoluteY = mousePosition.Y * scaleTransform.ScaleY;
|
||||
|
||||
//// 应用缩放
|
||||
//scaleTransform.ScaleX *= zoomFactor;
|
||||
//scaleTransform.ScaleY *= zoomFactor;
|
||||
|
||||
//// 平移,使缩放中心保持在鼠标光标处
|
||||
//translateTransform.X = mousePosition.X - absoluteX * zoomFactor;
|
||||
//translateTransform.Y = mousePosition.Y - absoluteY * zoomFactor;
|
||||
|
||||
// 调整画布大小,使其始终占据整个容器
|
||||
//AdjustCanvasSizeToContainer();
|
||||
}
|
||||
}
|
||||
|
||||
private void AdjustCanvasSizeToContainer()
|
||||
{
|
||||
// 获取当前缩放后的画布大小
|
||||
double newWidth = FlowChartCanvas.Width * scaleTransform.ScaleX;
|
||||
double newHeight = FlowChartCanvas.Height * scaleTransform.ScaleY;
|
||||
|
||||
// 设置画布大小,使其至少与ScrollViewer的可视区域大小相同
|
||||
FlowChartCanvas.Width = Math.Max(FlowChartScrollViewer.Width, newWidth);
|
||||
FlowChartCanvas.Height = Math.Max(FlowChartScrollViewer.Height, newHeight);
|
||||
}
|
||||
|
||||
private void AdjustCanvasSize()
|
||||
{
|
||||
// 获取 ScrollViewer 可视区域的宽度和高度
|
||||
double scrollViewerWidth = FlowChartScrollViewer.Width * scaleTransform.ScaleX;
|
||||
double scrollViewerHeight = FlowChartScrollViewer.Height * scaleTransform.ScaleY;
|
||||
|
||||
// 调整 Canvas 大小
|
||||
if (scrollViewerWidth > 0 && scrollViewerHeight > 0)
|
||||
{
|
||||
FlowChartCanvas.Width = scrollViewerWidth;
|
||||
FlowChartCanvas.Height = scrollViewerHeight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void AdjustCanvasSizeAndContent(double deltaX, double deltaY)
|
||||
{
|
||||
var myCanvas = FlowChartCanvas;
|
||||
|
||||
|
||||
|
||||
// 获取画布的边界框
|
||||
Rect transformedBounds = myCanvas.RenderTransform.TransformBounds(new Rect(myCanvas.RenderSize));
|
||||
Rect transformedBounds = FlowChartCanvas.RenderTransform.TransformBounds(new Rect(FlowChartCanvas.RenderSize));
|
||||
// Debug.Print($" {FlowChartScrollViewer.ActualWidth} / {FlowChartScrollViewer.ActualHeight} -- {transformedBounds.Right} / {transformedBounds.Bottom}");
|
||||
// Debug.Print($" {transformedBounds.Left} / {transformedBounds.Top} -- {deltaX} / {deltaY}");
|
||||
|
||||
|
||||
|
||||
|
||||
// 检查画布的左边缘是否超出视图
|
||||
if (transformedBounds.Left > 0)
|
||||
if (deltaX > 0 && transformedBounds.Left > 0)
|
||||
{
|
||||
double offsetX = transformedBounds.Left;
|
||||
myCanvas.Width += offsetX;
|
||||
FlowChartCanvas.Width += offsetX;
|
||||
translateTransform.X -= offsetX;
|
||||
|
||||
Debug.Print($" offsetX : {offsetX}");
|
||||
// 移动所有控件的位置
|
||||
foreach (UIElement child in myCanvas.Children)
|
||||
foreach (UIElement child in FlowChartCanvas.Children)
|
||||
{
|
||||
Canvas.SetLeft(child, Canvas.GetLeft(child) + offsetX);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查画布的上边缘是否超出视图
|
||||
if (transformedBounds.Top > 0)
|
||||
//if (transformedBounds.Top > 0)
|
||||
if (deltaY > 0 & transformedBounds.Top > 0)
|
||||
{
|
||||
double offsetY = transformedBounds.Top;
|
||||
myCanvas.Height += offsetY;
|
||||
FlowChartCanvas.Height += offsetY;
|
||||
translateTransform.Y -= offsetY;
|
||||
Debug.Print($" offsetY : {offsetY}");
|
||||
|
||||
// 移动所有控件的位置
|
||||
foreach (UIElement child in myCanvas.Children)
|
||||
foreach (UIElement child in FlowChartCanvas.Children)
|
||||
{
|
||||
Canvas.SetTop(child, Canvas.GetTop(child) + offsetY);
|
||||
}
|
||||
}
|
||||
|
||||
//Debug.Print($" {FlowChartScrollViewer.ActualWidth} / {FlowChartScrollViewer.ActualHeight} -- {transformedBounds.Right} / {transformedBounds.Bottom}");
|
||||
|
||||
var size = 50;
|
||||
// 检查画布的右边缘是否超出当前宽度
|
||||
if (transformedBounds.Right + size < FlowChartScrollViewer.ActualWidth)
|
||||
if ( transformedBounds.Right + size < FlowChartScrollViewer.ActualWidth)
|
||||
{
|
||||
|
||||
double extraWidth = FlowChartScrollViewer.ActualWidth - transformedBounds.Right;
|
||||
FlowChartCanvas.Width += extraWidth;
|
||||
this.FlowChartCanvas.Width += extraWidth;
|
||||
}
|
||||
|
||||
// 检查画布的下边缘是否超出当前高度
|
||||
if (transformedBounds.Bottom + size < FlowChartScrollViewer.ActualHeight)
|
||||
{
|
||||
double extraHeight = FlowChartScrollViewer.ActualHeight - transformedBounds.Bottom;
|
||||
FlowChartCanvas.Height += extraHeight;
|
||||
this.FlowChartCanvas.Height += extraHeight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -1398,10 +1450,9 @@ namespace Serein.WorkBench
|
||||
currentLine.X2 = position.X;
|
||||
currentLine.Y2 = position.Y;
|
||||
}
|
||||
|
||||
if (IsCanvasDragging)
|
||||
{
|
||||
Point currentMousePosition = e.GetPosition(this);
|
||||
Point currentMousePosition = e.GetPosition(FlowChartScrollViewer);
|
||||
double deltaX = currentMousePosition.X - startPoint.X;
|
||||
double deltaY = currentMousePosition.Y - startPoint.Y;
|
||||
|
||||
@@ -1410,9 +1461,15 @@ namespace Serein.WorkBench
|
||||
|
||||
startPoint = currentMousePosition;
|
||||
|
||||
// Adjust canvas size and content if necessary
|
||||
AdjustCanvasSizeAndContent(deltaX, deltaY);
|
||||
foreach (var line in connections)
|
||||
{
|
||||
line.Refresh();
|
||||
}
|
||||
|
||||
e.Handled = true; // 防止事件传播影响其他控件
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1550,19 +1607,19 @@ namespace Serein.WorkBench
|
||||
/// <param name="e"></param>
|
||||
private void FlowChartScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
// 确保 FlowChartCanvas 的最小尺寸等于 ScrollViewer 的可见尺寸
|
||||
var scrollViewerViewportWidth = FlowChartScrollViewer.ViewportWidth;
|
||||
var scrollViewerViewportHeight = FlowChartScrollViewer.ViewportHeight;
|
||||
//// 确保 FlowChartCanvas 的最小尺寸等于 ScrollViewer 的可见尺寸
|
||||
//var scrollViewerViewportWidth = FlowChartScrollViewer.ViewportWidth;
|
||||
//var scrollViewerViewportHeight = FlowChartScrollViewer.ViewportHeight;
|
||||
|
||||
if (FlowChartCanvas.Width < scrollViewerViewportWidth)
|
||||
{
|
||||
FlowChartCanvas.Width = scrollViewerViewportWidth;
|
||||
}
|
||||
//if (FlowChartCanvas.Width < scrollViewerViewportWidth)
|
||||
//{
|
||||
// FlowChartCanvas.Width = scrollViewerViewportWidth;
|
||||
//}
|
||||
|
||||
if (FlowChartCanvas.Height < scrollViewerViewportHeight)
|
||||
{
|
||||
FlowChartCanvas.Height = scrollViewerViewportHeight;
|
||||
}
|
||||
//if (FlowChartCanvas.Height < scrollViewerViewportHeight)
|
||||
//{
|
||||
// FlowChartCanvas.Height = scrollViewerViewportHeight;
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@@ -2124,7 +2181,10 @@ namespace Serein.WorkBench
|
||||
return Uri.UnescapeDataString(relativeUri.ToString().Replace('/', System.IO.Path.DirectorySeparatorChar));
|
||||
}
|
||||
|
||||
|
||||
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
AdjustCanvasSize();
|
||||
}
|
||||
}
|
||||
#region 创建两个控件之间的连接关系,在UI层面上显示为 带箭头指向的贝塞尔曲线
|
||||
|
||||
|
||||
Reference in New Issue
Block a user