CNC运行与底部状态栏提醒
This commit is contained in:
@@ -42,6 +42,9 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
private bool _pendingInsertAfterAnchor;
|
private bool _pendingInsertAfterAnchor;
|
||||||
private CancellationTokenSource _cts;
|
private CancellationTokenSource _cts;
|
||||||
private bool _isRunning;
|
private bool _isRunning;
|
||||||
|
private string _statusMessage = "就绪";
|
||||||
|
private string _executionError;
|
||||||
|
private bool _hasExecutionError;
|
||||||
|
|
||||||
public CncEditorViewModel(
|
public CncEditorViewModel(
|
||||||
ICncProgramService cncProgramService,
|
ICncProgramService cncProgramService,
|
||||||
@@ -159,6 +162,24 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string StatusMessage
|
||||||
|
{
|
||||||
|
get => _statusMessage;
|
||||||
|
private set => SetProperty(ref _statusMessage, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ExecutionError
|
||||||
|
{
|
||||||
|
get => _executionError;
|
||||||
|
private set => SetProperty(ref _executionError, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasExecutionError
|
||||||
|
{
|
||||||
|
get => _hasExecutionError;
|
||||||
|
private set => SetProperty(ref _hasExecutionError, value);
|
||||||
|
}
|
||||||
|
|
||||||
public DelegateCommand InsertReferencePointCommand { get; }
|
public DelegateCommand InsertReferencePointCommand { get; }
|
||||||
public DelegateCommand InsertSaveNodeWithImageCommand { get; }
|
public DelegateCommand InsertSaveNodeWithImageCommand { get; }
|
||||||
public DelegateCommand InsertSaveNodeCommand { get; }
|
public DelegateCommand InsertSaveNodeCommand { get; }
|
||||||
@@ -435,14 +456,28 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
{
|
{
|
||||||
_cts = new CancellationTokenSource();
|
_cts = new CancellationTokenSource();
|
||||||
IsRunning = true;
|
IsRunning = true;
|
||||||
|
HasExecutionError = false;
|
||||||
|
ExecutionError = null;
|
||||||
|
StatusMessage = $"正在执行:{_currentProgram?.Name ?? "程序"}(共 {_currentProgram?.Nodes?.Count ?? 0} 个节点)";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var progress = new Progress<CncNodeExecutionProgress>(OnExecutionProgress);
|
var progress = new Progress<CncNodeExecutionProgress>(OnExecutionProgress);
|
||||||
await _cncExecutionService.ExecuteAsync(_currentProgram, progress, _cts.Token);
|
await _cncExecutionService.ExecuteAsync(_currentProgram, progress, _cts.Token);
|
||||||
|
if (_cts.IsCancellationRequested)
|
||||||
|
StatusMessage = "执行已停止";
|
||||||
|
else
|
||||||
|
StatusMessage = $"执行完成:{_currentProgram?.Name}";
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
StatusMessage = "执行已取消";
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error(ex, "CNC execution failed");
|
_logger.Error(ex, "CNC execution failed");
|
||||||
|
ExecutionError = ex.Message;
|
||||||
|
HasExecutionError = true;
|
||||||
|
StatusMessage = $"执行失败:{ex.Message}";
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -462,7 +497,17 @@ namespace XplorePlane.ViewModels.Cnc
|
|||||||
{
|
{
|
||||||
var nodeVm = Nodes.FirstOrDefault(n => n.Id == progress.NodeId);
|
var nodeVm = Nodes.FirstOrDefault(n => n.Id == progress.NodeId);
|
||||||
if (nodeVm != null)
|
if (nodeVm != null)
|
||||||
|
{
|
||||||
nodeVm.ExecutionState = progress.State;
|
nodeVm.ExecutionState = progress.State;
|
||||||
|
if (progress.State == NodeExecutionState.Running)
|
||||||
|
StatusMessage = $"正在执行节点:{nodeVm.Name}({nodeVm.Index + 1}/{_currentProgram?.Nodes?.Count ?? 0})";
|
||||||
|
else if (progress.State == NodeExecutionState.Failed)
|
||||||
|
{
|
||||||
|
HasExecutionError = true;
|
||||||
|
ExecutionError = $"节点 [{nodeVm.Name}] 执行失败";
|
||||||
|
StatusMessage = $"错误:节点 [{nodeVm.Name}] 执行失败";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetAllNodeStates()
|
private void ResetAllNodeStates()
|
||||||
|
|||||||
@@ -57,6 +57,20 @@ namespace XplorePlane.ViewModels
|
|||||||
_cncPageView = new CncPageView { DataContext = _cncEditorViewModel };
|
_cncPageView = new CncPageView { DataContext = _cncEditorViewModel };
|
||||||
|
|
||||||
_mainViewportService.StateChanged += OnMainViewportStateChanged;
|
_mainViewportService.StateChanged += OnMainViewportStateChanged;
|
||||||
|
_cncEditorViewModel.PropertyChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (e.PropertyName == nameof(CncEditorViewModel.StatusMessage))
|
||||||
|
RaisePropertyChanged(nameof(CncStatusMessage));
|
||||||
|
else if (e.PropertyName == nameof(CncEditorViewModel.HasExecutionError))
|
||||||
|
RaisePropertyChanged(nameof(CncHasExecutionError));
|
||||||
|
else if (e.PropertyName == nameof(CncEditorViewModel.IsRunning))
|
||||||
|
{
|
||||||
|
RunCncCommand.RaiseCanExecuteChanged();
|
||||||
|
StopCncCommand.RaiseCanExecuteChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_cncEditorViewModel.RunCncCommand.CanExecuteChanged += (s, e) => RunCncCommand.RaiseCanExecuteChanged();
|
||||||
|
_cncEditorViewModel.StopCncCommand.CanExecuteChanged += (s, e) => StopCncCommand.RaiseCanExecuteChanged();
|
||||||
|
|
||||||
NavigationTree = new ObservableCollection<object>();
|
NavigationTree = new ObservableCollection<object>();
|
||||||
|
|
||||||
@@ -87,8 +101,12 @@ namespace XplorePlane.ViewModels
|
|||||||
InsertSaveNodeCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertSaveNodeCommand.Execute()));
|
InsertSaveNodeCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertSaveNodeCommand.Execute()));
|
||||||
InsertPauseDialogCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertPauseDialogCommand.Execute()));
|
InsertPauseDialogCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertPauseDialogCommand.Execute()));
|
||||||
InsertWaitDelayCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertWaitDelayCommand.Execute()));
|
InsertWaitDelayCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.InsertWaitDelayCommand.Execute()));
|
||||||
RunCncCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.RunCncCommand.Execute()));
|
RunCncCommand = new DelegateCommand(
|
||||||
StopCncCommand = new DelegateCommand(() => ExecuteCncEditorAction(vm => vm.StopCncCommand.Execute()));
|
() => ExecuteCncEditorAction(vm => vm.RunCncCommand.Execute()),
|
||||||
|
() => _cncEditorViewModel.RunCncCommand.CanExecute());
|
||||||
|
StopCncCommand = new DelegateCommand(
|
||||||
|
() => ExecuteCncEditorAction(vm => vm.StopCncCommand.Execute()),
|
||||||
|
() => _cncEditorViewModel.StopCncCommand.CanExecute());
|
||||||
|
|
||||||
PointDistanceMeasureCommand = new DelegateCommand(ExecutePointDistanceMeasure);
|
PointDistanceMeasureCommand = new DelegateCommand(ExecutePointDistanceMeasure);
|
||||||
PointLineDistanceMeasureCommand = new DelegateCommand(ExecutePointLineDistanceMeasure);
|
PointLineDistanceMeasureCommand = new DelegateCommand(ExecutePointLineDistanceMeasure);
|
||||||
@@ -121,6 +139,9 @@ namespace XplorePlane.ViewModels
|
|||||||
set => SetProperty(ref _licenseInfo, value);
|
set => SetProperty(ref _licenseInfo, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string CncStatusMessage => _cncEditorViewModel.StatusMessage;
|
||||||
|
public bool CncHasExecutionError => _cncEditorViewModel.HasExecutionError;
|
||||||
|
|
||||||
public ObservableCollection<object> NavigationTree { get; set; }
|
public ObservableCollection<object> NavigationTree { get; set; }
|
||||||
|
|
||||||
public DelegateCommand NavigateHomeCommand { get; set; }
|
public DelegateCommand NavigateHomeCommand { get; set; }
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
<StackPanel>
|
<StackPanel>
|
||||||
<telerik:RadRibbonButton
|
<telerik:RadRibbonButton
|
||||||
telerik:ScreenTip.Title="运行"
|
telerik:ScreenTip.Title="运行"
|
||||||
|
Command="{Binding RunCncCommand}"
|
||||||
Size="Large"
|
Size="Large"
|
||||||
SmallImage="/Assets/Icons/run.png"
|
SmallImage="/Assets/Icons/run.png"
|
||||||
Text="运行" />
|
Text="运行" />
|
||||||
@@ -114,6 +115,7 @@
|
|||||||
<telerik:RadRibbonButton
|
<telerik:RadRibbonButton
|
||||||
telerik:ScreenTip.Description="停止"
|
telerik:ScreenTip.Description="停止"
|
||||||
telerik:ScreenTip.Title="停止"
|
telerik:ScreenTip.Title="停止"
|
||||||
|
Command="{Binding StopCncCommand}"
|
||||||
Size="Large"
|
Size="Large"
|
||||||
SmallImage="/Assets/Icons/stop.png"
|
SmallImage="/Assets/Icons/stop.png"
|
||||||
Text="停止" />
|
Text="停止" />
|
||||||
@@ -554,7 +556,19 @@
|
|||||||
FontFamily="Microsoft YaHei UI"
|
FontFamily="Microsoft YaHei UI"
|
||||||
FontSize="11"
|
FontSize="11"
|
||||||
Foreground="White"
|
Foreground="White"
|
||||||
Text="就绪" />
|
Text="{Binding CncStatusMessage}">
|
||||||
|
<TextBlock.Style>
|
||||||
|
<Style TargetType="TextBlock">
|
||||||
|
<Setter Property="Foreground" Value="White" />
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding CncHasExecutionError}" Value="True">
|
||||||
|
<Setter Property="Foreground" Value="#FF9090" />
|
||||||
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
@@ -563,7 +577,7 @@
|
|||||||
FontFamily="Consolas"
|
FontFamily="Consolas"
|
||||||
FontSize="11"
|
FontSize="11"
|
||||||
Foreground="White"
|
Foreground="White"
|
||||||
Text="x: 0 y: 0 RGB: 0 0 0" />
|
Text="x: 0 y: 0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
Reference in New Issue
Block a user