diff --git a/XplorePlane/Models/PipelineModels.cs b/XplorePlane/Models/PipelineModels.cs index 8b3ad26..0cf474e 100644 --- a/XplorePlane/Models/PipelineModels.cs +++ b/XplorePlane/Models/PipelineModels.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace XplorePlane.Models { - public class PipelineModel + public class PipelineModel //流程图 { public Guid Id { get; set; } = Guid.NewGuid(); public string Name { get; set; } = string.Empty; @@ -13,7 +13,7 @@ namespace XplorePlane.Models public List Nodes { get; set; } = new(); } - public class PipelineNodeModel + public class PipelineNodeModel //节点 { public Guid Id { get; set; } = Guid.NewGuid(); public string OperatorKey { get; set; } = string.Empty; diff --git a/XplorePlane/ViewModels/Cnc/CncInspectionModulePipelineViewModel.cs b/XplorePlane/ViewModels/Cnc/CncInspectionModulePipelineViewModel.cs index b6dc7d7..af75a44 100644 --- a/XplorePlane/ViewModels/Cnc/CncInspectionModulePipelineViewModel.cs +++ b/XplorePlane/ViewModels/Cnc/CncInspectionModulePipelineViewModel.cs @@ -1,4 +1,4 @@ -using Microsoft.Win32; +using Microsoft.Win32; using Prism.Commands; using Prism.Mvvm; using System; @@ -44,6 +44,8 @@ namespace XplorePlane.ViewModels.Cnc AddOperatorCommand = new DelegateCommand(AddOperator, _ => HasActiveModule); RemoveOperatorCommand = new DelegateCommand(RemoveOperator); + ReorderOperatorCommand = new DelegateCommand(ReorderOperator); + ToggleOperatorEnabledCommand = new DelegateCommand(ToggleOperatorEnabled); MoveNodeUpCommand = new DelegateCommand(MoveNodeUp); MoveNodeDownCommand = new DelegateCommand(MoveNodeDown); NewPipelineCommand = new DelegateCommand(NewPipeline); @@ -79,6 +81,10 @@ namespace XplorePlane.ViewModels.Cnc public ICommand RemoveOperatorCommand { get; } + public ICommand ReorderOperatorCommand { get; } + + public ICommand ToggleOperatorEnabledCommand { get; } + public ICommand MoveNodeUpCommand { get; } public ICommand MoveNodeDownCommand { get; } @@ -152,13 +158,10 @@ namespace XplorePlane.ViewModels.Cnc if (!HasActiveModule || node == null || !PipelineNodes.Contains(node)) return; + var removedIndex = PipelineNodes.IndexOf(node); PipelineNodes.Remove(node); RenumberNodes(); - - if (SelectedNode == node) - { - SelectedNode = PipelineNodes.LastOrDefault(); - } + SelectNeighborAfterRemoval(removedIndex); PersistActiveModule($"已移除算子:{node.DisplayName}"); } @@ -177,6 +180,26 @@ namespace XplorePlane.ViewModels.Cnc PersistActiveModule($"已上移算子:{node.DisplayName}"); } + private void ReorderOperator(PipelineReorderArgs args) + { + if (!HasActiveModule || args == null) + return; + + var oldIndex = args.OldIndex; + var newIndex = args.NewIndex; + if (oldIndex < 0 || oldIndex >= PipelineNodes.Count) + return; + + if (newIndex < 0 || newIndex >= PipelineNodes.Count || oldIndex == newIndex) + return; + + var node = PipelineNodes[oldIndex]; + PipelineNodes.Move(oldIndex, newIndex); + RenumberNodes(); + SelectedNode = node; + PersistActiveModule($"已调整算子顺序:{node.DisplayName}"); + } + private void MoveNodeDown(PipelineNodeViewModel node) { if (!HasActiveModule || node == null) @@ -191,6 +214,18 @@ namespace XplorePlane.ViewModels.Cnc PersistActiveModule($"已下移算子:{node.DisplayName}"); } + private void ToggleOperatorEnabled(PipelineNodeViewModel node) + { + if (!HasActiveModule || node == null || !PipelineNodes.Contains(node)) + return; + + node.IsEnabled = !node.IsEnabled; + SelectedNode = node; + PersistActiveModule(node.IsEnabled + ? $"已启用算子:{node.DisplayName}" + : $"已停用算子:{node.DisplayName}"); + } + private void NewPipeline() { if (!HasActiveModule) @@ -359,6 +394,20 @@ namespace XplorePlane.ViewModels.Cnc } } + private void SelectNeighborAfterRemoval(int removedIndex) + { + if (PipelineNodes.Count == 0) + { + SelectedNode = null; + return; + } + + var nextIndex = removedIndex < PipelineNodes.Count + ? removedIndex + : PipelineNodes.Count - 1; + SelectedNode = PipelineNodes[nextIndex]; + } + private void RaiseModuleVisibilityChanged() { RaisePropertyChanged(nameof(HasActiveModule)); diff --git a/XplorePlane/ViewModels/ImageProcessing/IPipelineEditorHostViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/IPipelineEditorHostViewModel.cs index 6bdcc74..8460667 100644 --- a/XplorePlane/ViewModels/ImageProcessing/IPipelineEditorHostViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/IPipelineEditorHostViewModel.cs @@ -15,6 +15,10 @@ namespace XplorePlane.ViewModels ICommand RemoveOperatorCommand { get; } + ICommand ReorderOperatorCommand { get; } + + ICommand ToggleOperatorEnabledCommand { get; } + ICommand MoveNodeUpCommand { get; } ICommand MoveNodeDownCommand { get; } diff --git a/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs b/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs index 618f111..9730488 100644 --- a/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessing/PipelineEditorViewModel.cs @@ -1,4 +1,4 @@ -using Microsoft.Win32; +using Microsoft.Win32; using Prism.Events; using Prism.Commands; using Prism.Mvvm; @@ -59,6 +59,7 @@ namespace XplorePlane.ViewModels AddOperatorCommand = new DelegateCommand(AddOperator, CanAddOperator); RemoveOperatorCommand = new DelegateCommand(RemoveOperator); ReorderOperatorCommand = new DelegateCommand(ReorderOperator); + ToggleOperatorEnabledCommand = new DelegateCommand(ToggleOperatorEnabled); ExecutePipelineCommand = new DelegateCommand(async () => await ExecutePipelineAsync(), () => !IsExecuting && SourceImage != null); CancelExecutionCommand = new DelegateCommand(CancelExecution, () => IsExecuting); NewPipelineCommand = new DelegateCommand(NewPipeline); @@ -152,6 +153,7 @@ namespace XplorePlane.ViewModels public DelegateCommand AddOperatorCommand { get; } public DelegateCommand RemoveOperatorCommand { get; } public DelegateCommand ReorderOperatorCommand { get; } + public DelegateCommand ToggleOperatorEnabledCommand { get; } public DelegateCommand ExecutePipelineCommand { get; } public DelegateCommand CancelExecutionCommand { get; } public DelegateCommand NewPipelineCommand { get; } @@ -168,6 +170,8 @@ namespace XplorePlane.ViewModels ICommand IPipelineEditorHostViewModel.AddOperatorCommand => AddOperatorCommand; ICommand IPipelineEditorHostViewModel.RemoveOperatorCommand => RemoveOperatorCommand; + ICommand IPipelineEditorHostViewModel.ReorderOperatorCommand => ReorderOperatorCommand; + ICommand IPipelineEditorHostViewModel.ToggleOperatorEnabledCommand => ToggleOperatorEnabledCommand; ICommand IPipelineEditorHostViewModel.MoveNodeUpCommand => MoveNodeUpCommand; ICommand IPipelineEditorHostViewModel.MoveNodeDownCommand => MoveNodeDownCommand; ICommand IPipelineEditorHostViewModel.NewPipelineCommand => NewPipelineCommand; @@ -217,6 +221,7 @@ namespace XplorePlane.ViewModels }; LoadNodeParameters(node); PipelineNodes.Add(node); + SelectedNode = node; _logger.Info("节点已添加到 PipelineNodes:{Key} ({DisplayName}),当前节点数={Count}", operatorKey, displayName, PipelineNodes.Count); StatusMessage = $"已添加算子:{displayName}"; @@ -227,11 +232,10 @@ namespace XplorePlane.ViewModels { if (node == null || !PipelineNodes.Contains(node)) return; + var removedIndex = PipelineNodes.IndexOf(node); PipelineNodes.Remove(node); RenumberNodes(); - - if (SelectedNode == node) - SelectedNode = null; + SelectNeighborAfterRemoval(removedIndex); StatusMessage = $"已移除算子:{node.DisplayName}"; TriggerDebouncedExecution(); @@ -271,6 +275,20 @@ namespace XplorePlane.ViewModels PipelineNodes.RemoveAt(oldIndex); PipelineNodes.Insert(newIndex, node); RenumberNodes(); + SelectedNode = node; + StatusMessage = $"已调整算子顺序:{node.DisplayName}"; + TriggerDebouncedExecution(); + } + + private void ToggleOperatorEnabled(PipelineNodeViewModel node) + { + if (node == null || !PipelineNodes.Contains(node)) return; + + node.IsEnabled = !node.IsEnabled; + SelectedNode = node; + StatusMessage = node.IsEnabled + ? $"已启用算子:{node.DisplayName}" + : $"已停用算子:{node.DisplayName}"; TriggerDebouncedExecution(); } @@ -280,6 +298,20 @@ namespace XplorePlane.ViewModels PipelineNodes[i].Order = i; } + private void SelectNeighborAfterRemoval(int removedIndex) + { + if (PipelineNodes.Count == 0) + { + SelectedNode = null; + return; + } + + var nextIndex = removedIndex < PipelineNodes.Count + ? removedIndex + : PipelineNodes.Count - 1; + SelectedNode = PipelineNodes[nextIndex]; + } + private void LoadNodeParameters(PipelineNodeViewModel node) { var paramDefs = _imageProcessingService.GetProcessorParameters(node.OperatorKey); diff --git a/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml b/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml index 5f4d2f1..55dcb2c 100644 --- a/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml +++ b/XplorePlane/Views/ImageProcessing/PipelineEditorView.xaml @@ -4,7 +4,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" d:DesignHeight="700" d:DesignWidth="350" mc:Ignorable="d"> @@ -13,13 +12,27 @@ - + + + + Microsoft YaHei UI