#0024 修复浮动工具箱
This commit is contained in:
@@ -141,22 +141,30 @@ namespace XplorePlane.ViewModels
|
||||
|
||||
private void AddOperator(string operatorKey)
|
||||
{
|
||||
Serilog.Log.Debug("AddOperator 被调用,operatorKey={OperatorKey}", operatorKey);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(operatorKey))
|
||||
{
|
||||
StatusMessage = "算子键不能为空";
|
||||
Serilog.Log.Warning("AddOperator 失败:operatorKey 为空");
|
||||
return;
|
||||
}
|
||||
|
||||
var available = _imageProcessingService.GetAvailableProcessors();
|
||||
Serilog.Log.Debug("可用算子数量:{Count},包含 {Key}:{Contains}",
|
||||
available.Count(), operatorKey, available.Contains(operatorKey));
|
||||
|
||||
if (!available.Contains(operatorKey))
|
||||
{
|
||||
StatusMessage = $"算子 '{operatorKey}' 未注册";
|
||||
Serilog.Log.Warning("AddOperator 失败:算子 {Key} 未注册", operatorKey);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PipelineNodes.Count >= MaxPipelineLength)
|
||||
{
|
||||
StatusMessage = $"流水线节点数已达上限({MaxPipelineLength})";
|
||||
Serilog.Log.Warning("AddOperator 失败:节点数已达上限 {Max}", MaxPipelineLength);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -167,6 +175,8 @@ namespace XplorePlane.ViewModels
|
||||
};
|
||||
LoadNodeParameters(node);
|
||||
PipelineNodes.Add(node);
|
||||
Serilog.Log.Information("节点已添加到 PipelineNodes:{Key} ({DisplayName}),当前节点数={Count}",
|
||||
operatorKey, displayName, PipelineNodes.Count);
|
||||
StatusMessage = $"已添加算子:{displayName}";
|
||||
TriggerDebouncedExecution();
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Prism.Ioc;
|
||||
using Telerik.Windows.DragDrop;
|
||||
using Serilog;
|
||||
using XplorePlane.ViewModels;
|
||||
|
||||
namespace XplorePlane.Views
|
||||
{
|
||||
public partial class OperatorToolboxView : UserControl
|
||||
{
|
||||
private const string DragFormat = "OperatorDescriptor";
|
||||
public const string DragFormat = "PipelineOperatorKey";
|
||||
|
||||
private Point _dragStartPoint;
|
||||
private bool _isDragging;
|
||||
|
||||
public OperatorToolboxView()
|
||||
{
|
||||
@@ -21,29 +25,55 @@ namespace XplorePlane.Views
|
||||
if (DataContext == null)
|
||||
DataContext = ContainerLocator.Container.Resolve<OperatorToolboxViewModel>();
|
||||
|
||||
// 启用拖拽源 + 注册拖拽初始化事件
|
||||
DragDropManager.SetAllowDrag(ToolboxListBox, true);
|
||||
DragDropManager.AddDragInitializeHandler(ToolboxListBox, OnDragInitialize, true);
|
||||
ToolboxListBox.PreviewMouseLeftButtonDown += OnPreviewMouseDown;
|
||||
ToolboxListBox.PreviewMouseMove += OnPreviewMouseMove;
|
||||
Log.Debug("OperatorToolboxView 原生拖拽源已注册");
|
||||
}
|
||||
|
||||
private void OnDragInitialize(object sender, DragInitializeEventArgs e)
|
||||
private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (ToolboxListBox.SelectedItem is OperatorDescriptor descriptor)
|
||||
_dragStartPoint = e.GetPosition(null);
|
||||
_isDragging = false;
|
||||
}
|
||||
|
||||
private void OnPreviewMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.LeftButton != MouseButtonState.Pressed) return;
|
||||
|
||||
var pos = e.GetPosition(null);
|
||||
var diff = pos - _dragStartPoint;
|
||||
|
||||
if (!_isDragging
|
||||
&& (System.Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance
|
||||
|| System.Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
|
||||
{
|
||||
e.AllowedEffects = System.Windows.DragDropEffects.Copy;
|
||||
DragDropPayloadManager.SetData(e.Data, DragFormat, descriptor);
|
||||
e.DragVisual = new System.Windows.Controls.TextBlock
|
||||
_isDragging = true;
|
||||
|
||||
// 从鼠标位置 HitTest 找到 OperatorDescriptor
|
||||
var hitResult = System.Windows.Media.VisualTreeHelper.HitTest(
|
||||
ToolboxListBox, e.GetPosition(ToolboxListBox));
|
||||
|
||||
OperatorDescriptor? descriptor = null;
|
||||
var node = hitResult?.VisualHit as DependencyObject;
|
||||
while (node != null)
|
||||
{
|
||||
Text = descriptor.DisplayName,
|
||||
Padding = new Thickness(6, 3, 6, 3),
|
||||
Background = System.Windows.Media.Brushes.LightBlue,
|
||||
FontFamily = new System.Windows.Media.FontFamily("Microsoft YaHei UI"),
|
||||
FontSize = 11
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Cancel = true;
|
||||
if (node is FrameworkElement fe && fe.DataContext is OperatorDescriptor d)
|
||||
{
|
||||
descriptor = d;
|
||||
break;
|
||||
}
|
||||
node = System.Windows.Media.VisualTreeHelper.GetParent(node);
|
||||
}
|
||||
|
||||
if (descriptor == null)
|
||||
{
|
||||
Log.Warning("拖拽初始化失败:HitTest 未命中算子项");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Information("开始拖拽算子:{OperatorKey} ({DisplayName})", descriptor.Key, descriptor.DisplayName);
|
||||
var data = new DataObject(DragFormat, descriptor.Key);
|
||||
DragDrop.DoDragDrop(ToolboxListBox, data, DragDropEffects.Copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<FontFamily x:Key="CsdFont">Microsoft YaHei UI</FontFamily>
|
||||
|
||||
<!-- 节点项样式 -->
|
||||
<Style x:Key="PipelineNodeItemStyle" TargetType="telerik:RadListBoxItem">
|
||||
<Style x:Key="PipelineNodeItemStyle" TargetType="ListBoxItem">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
@@ -45,7 +45,7 @@
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="36" />
|
||||
<RowDefinition Height="40" />
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
@@ -110,19 +110,19 @@
|
||||
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
||||
<Button
|
||||
Command="{Binding NewPipelineCommand}"
|
||||
Content="新"
|
||||
Content="新建"
|
||||
Style="{StaticResource ToolbarBtn}"
|
||||
ToolTip="新建流水线" />
|
||||
<Button
|
||||
Command="{Binding SavePipelineCommand}"
|
||||
Content="存"
|
||||
Content="保存"
|
||||
Style="{StaticResource ToolbarBtn}"
|
||||
ToolTip="保存流水线" />
|
||||
<Button
|
||||
Command="{Binding SaveAsPipelineCommand}"
|
||||
Content="另"
|
||||
Content="另存为"
|
||||
Style="{StaticResource ToolbarBtn}"
|
||||
ToolTip="另存为" />
|
||||
ToolTip="另存为" Width="43" />
|
||||
<Button
|
||||
Command="{Binding ExecutePipelineCommand}"
|
||||
Content="▶"
|
||||
@@ -145,83 +145,52 @@
|
||||
|
||||
|
||||
<!-- 流水线节点列表(拖拽目标) -->
|
||||
<telerik:RadListBox
|
||||
<ListBox
|
||||
x:Name="PipelineListBox"
|
||||
Grid.Row="2"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
ItemContainerStyle="{StaticResource PipelineNodeItemStyle}"
|
||||
ItemsSource="{Binding PipelineNodes}"
|
||||
SelectedItem="{Binding SelectedNode, Mode=TwoWay}">
|
||||
<telerik:RadListBox.ItemTemplate>
|
||||
SelectedItem="{Binding SelectedNode, Mode=TwoWay}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid MinHeight="44">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20" />
|
||||
<ColumnDefinition Width="28" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 竖线连接 -->
|
||||
<Canvas Grid.Column="0" Width="20">
|
||||
<Line
|
||||
Stroke="#5B9BD5"
|
||||
StrokeThickness="2"
|
||||
X1="10"
|
||||
X2="10"
|
||||
Y1="0"
|
||||
Y2="40" />
|
||||
<Rectangle
|
||||
Canvas.Left="3"
|
||||
Canvas.Top="12"
|
||||
Width="14"
|
||||
Height="14"
|
||||
Fill="White"
|
||||
RadiusX="2"
|
||||
RadiusY="2"
|
||||
Stroke="#5B9BD5"
|
||||
StrokeThickness="1.5" />
|
||||
</Canvas>
|
||||
<!-- 竖线连接 + 节点方块 -->
|
||||
<Grid Grid.Column="0">
|
||||
<Line Stroke="#5B9BD5" StrokeThickness="2"
|
||||
X1="14" X2="14" Y1="0" Y2="44"
|
||||
HorizontalAlignment="Left" />
|
||||
<Border Width="16" Height="16"
|
||||
Background="White"
|
||||
BorderBrush="#5B9BD5" BorderThickness="1.5"
|
||||
CornerRadius="2"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Center" />
|
||||
</Grid>
|
||||
|
||||
<!-- 节点行 -->
|
||||
<Border
|
||||
Grid.Column="1"
|
||||
Padding="6,8"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="0">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSelected}" Value="True">
|
||||
<Setter Property="Background" Value="{StaticResource AccentBlue}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Border Grid.Column="1" Padding="6,8">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Border
|
||||
Width="28"
|
||||
Height="28"
|
||||
Margin="0,0,8,0"
|
||||
Background="#E8F0FE"
|
||||
CornerRadius="3">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="13"
|
||||
Text="⚙" />
|
||||
<Border Width="28" Height="28" Margin="0,0,8,0"
|
||||
Background="#E8F0FE" CornerRadius="3">
|
||||
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
FontSize="13" Text="⚙" />
|
||||
</Border>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="Microsoft YaHei UI"
|
||||
FontSize="12"
|
||||
Text="{Binding DisplayName}" />
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
FontFamily="Microsoft YaHei UI" FontSize="12"
|
||||
Text="{Binding DisplayName}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</telerik:RadListBox.ItemTemplate>
|
||||
</telerik:RadListBox>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<!-- 分隔线 -->
|
||||
<Rectangle
|
||||
Grid.Row="3"
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Prism.Ioc;
|
||||
using Telerik.Windows.DragDrop;
|
||||
using Serilog;
|
||||
using XplorePlane.ViewModels;
|
||||
|
||||
namespace XplorePlane.Views
|
||||
{
|
||||
public partial class PipelineEditorView : UserControl
|
||||
{
|
||||
private const string DragFormat = "OperatorDescriptor";
|
||||
|
||||
public PipelineEditorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -21,19 +19,47 @@ namespace XplorePlane.Views
|
||||
if (DataContext == null)
|
||||
DataContext = ContainerLocator.Container.Resolve<PipelineEditorViewModel>();
|
||||
|
||||
// 启用拖拽目标 + 注册 Drop 事件
|
||||
PipelineListBox.AllowDrop = true;
|
||||
DragDropManager.AddDropHandler(PipelineListBox, OnOperatorDropped, true);
|
||||
PipelineListBox.Drop += OnOperatorDropped;
|
||||
PipelineListBox.DragOver += OnDragOver;
|
||||
Log.Debug("PipelineEditorView 原生 Drop 目标已注册");
|
||||
}
|
||||
|
||||
private void OnOperatorDropped(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
|
||||
private void OnDragOver(object sender, DragEventArgs e)
|
||||
{
|
||||
if (DataContext is not PipelineEditorViewModel vm) return;
|
||||
if (e.Data.GetDataPresent(OperatorToolboxView.DragFormat))
|
||||
e.Effects = DragDropEffects.Copy;
|
||||
else
|
||||
e.Effects = DragDropEffects.None;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
var descriptor = DragDropPayloadManager.GetDataFromObject(e.Data, DragFormat) as OperatorDescriptor;
|
||||
if (descriptor == null) return;
|
||||
private void OnOperatorDropped(object sender, DragEventArgs e)
|
||||
{
|
||||
if (DataContext is not PipelineEditorViewModel vm)
|
||||
{
|
||||
Log.Warning("Drop 事件触发但 DataContext 不是 PipelineEditorViewModel");
|
||||
return;
|
||||
}
|
||||
|
||||
vm.AddOperatorCommand.Execute(descriptor.Key);
|
||||
if (!e.Data.GetDataPresent(OperatorToolboxView.DragFormat))
|
||||
{
|
||||
Log.Warning("Drop 事件触发但数据中无 {Format}", OperatorToolboxView.DragFormat);
|
||||
return;
|
||||
}
|
||||
|
||||
var operatorKey = e.Data.GetData(OperatorToolboxView.DragFormat) as string;
|
||||
if (string.IsNullOrEmpty(operatorKey))
|
||||
{
|
||||
Log.Warning("Drop 事件触发但 OperatorKey 为空");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Information("算子已放入流水线:{OperatorKey},VM HashCode={Hash},当前节点数(执行前)={Count}",
|
||||
operatorKey, vm.GetHashCode(), vm.PipelineNodes.Count);
|
||||
vm.AddOperatorCommand.Execute(operatorKey);
|
||||
Log.Information("AddOperator 执行后节点数={Count},PipelineListBox.Items.Count={ItemsCount}",
|
||||
vm.PipelineNodes.Count, PipelineListBox.Items.Count);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,8 @@
|
||||
2、硬件层射线源的集成 √
|
||||
3、图像层集成,包括复刻一个示例界面,优化界面布局及算子中文 √
|
||||
4、浮动图像处理工具箱调研 √
|
||||
5、修复图像工具箱拖拽事件,流水线列表没有生成对应的控件
|
||||
|
||||
|
||||
|
||||
5、各窗体间数据流的传递,全局数据结构的设计
|
||||
Reference in New Issue
Block a user