This commit is contained in:
GukSang.Jin
2026-05-28 13:40:07 +08:00
parent a5cdb1d9d5
commit a700cab0b2
4 changed files with 163 additions and 18 deletions

View File

@@ -1,16 +1,11 @@
using System.Windows.Input;
namespace ConeCalorimeter.ViewModels;
public sealed class SmokeDensityCalibrationViewModel
{
public SmokeDensityCalibrationViewModel(string label, ICommand command)
public SmokeDensityCalibrationViewModel(string label)
{
Label = label;
Command = command;
}
public string Label { get; }
public ICommand Command { get; }
}

View File

@@ -21,6 +21,7 @@ public sealed class SmokeDensitySettingsViewModel : PageViewModel
private readonly DispatcherTimer _refreshTimer;
private readonly HashSet<ushort> _loggedFloatDiagnostics = [];
private readonly HashSet<ushort> _loggedInvalidFloatDiagnostics = [];
private readonly HashSet<string> _pressedCalibrationLabels = [];
private double? _stableAbsorbance;
private double? _pendingAbsorbance;
private int _pendingAbsorbanceReadCount;
@@ -34,15 +35,14 @@ public sealed class SmokeDensitySettingsViewModel : PageViewModel
_closeAction = closeAction;
_tcpDeviceConnectionService = tcpDeviceConnectionService;
CloseCommand = new RelayCommand(_closeAction);
CalibrationCommand = new RelayCommand<string>(Calibrate);
CalibrationActions =
[
new SmokeDensityCalibrationViewModel("0%校准", CalibrationCommand),
new SmokeDensityCalibrationViewModel("25%校准", CalibrationCommand),
new SmokeDensityCalibrationViewModel("50%校准", CalibrationCommand),
new SmokeDensityCalibrationViewModel("75%校准", CalibrationCommand),
new SmokeDensityCalibrationViewModel("100%校准", CalibrationCommand)
new SmokeDensityCalibrationViewModel("0%校准"),
new SmokeDensityCalibrationViewModel("25%校准"),
new SmokeDensityCalibrationViewModel("50%校准"),
new SmokeDensityCalibrationViewModel("75%校准"),
new SmokeDensityCalibrationViewModel("100%校准")
];
RefreshDeviceValues();
@@ -58,8 +58,6 @@ public sealed class SmokeDensitySettingsViewModel : PageViewModel
public IRelayCommand CloseCommand { get; }
public IRelayCommand<string> CalibrationCommand { get; }
public string AbsorbanceText
{
get => _absorbanceText;
@@ -72,13 +70,18 @@ public sealed class SmokeDensitySettingsViewModel : PageViewModel
private set => SetProperty(ref _lastCalibration, value);
}
private void Calibrate(string? label)
public void PressCalibration(string? label)
{
if (string.IsNullOrWhiteSpace(label))
{
return;
}
if (_pressedCalibrationLabels.Contains(label))
{
return;
}
LastCalibration = label;
if (!TryGetCalibrationCoil(label, out var coilAddress))
@@ -89,7 +92,34 @@ public sealed class SmokeDensitySettingsViewModel : PageViewModel
if (!_tcpDeviceConnectionService.TryWriteCoil(coilAddress, true))
{
LastCalibration = $"{label}失败";
Debug.WriteLine($"Smoke density calibration '{label}' write failed.");
Debug.WriteLine($"Smoke density calibration '{label}' press write failed.");
return;
}
_pressedCalibrationLabels.Add(label);
}
public void ReleaseCalibration(string? label)
{
if (string.IsNullOrWhiteSpace(label))
{
return;
}
if (!_pressedCalibrationLabels.Remove(label))
{
return;
}
if (!TryGetCalibrationCoil(label, out var coilAddress))
{
return;
}
if (!_tcpDeviceConnectionService.TryWriteCoil(coilAddress, false))
{
LastCalibration = $"{label}复位失败";
Debug.WriteLine($"Smoke density calibration '{label}' release write failed.");
}
}

View File

@@ -78,8 +78,14 @@
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Label}"
Command="{Binding Command}"
CommandParameter="{Binding Label}"
PreviewMouseLeftButtonDown="CalibrationButton_PreviewMouseLeftButtonDown"
PreviewMouseLeftButtonUp="CalibrationButton_PreviewMouseLeftButtonUp"
MouseLeave="CalibrationButton_MouseLeave"
LostMouseCapture="CalibrationButton_LostMouseCapture"
TouchDown="CalibrationButton_TouchDown"
TouchUp="CalibrationButton_TouchUp"
TouchLeave="CalibrationButton_TouchLeave"
LostTouchCapture="CalibrationButton_LostTouchCapture"
Width="128"
Height="42"
Margin="0,8,24,8"

View File

@@ -1,4 +1,7 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using ConeCalorimeter.ViewModels;
namespace ConeCalorimeter.Views;
@@ -8,4 +11,115 @@ public partial class SmokeDensitySettingsView : UserControl
{
InitializeComponent();
}
private void CalibrationButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
StartCalibration(sender);
if (sender is Button button)
{
button.CaptureMouse();
}
}
private void CalibrationButton_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
StopCalibration(sender);
ReleaseMouseCapture(sender);
}
private void CalibrationButton_MouseLeave(object sender, MouseEventArgs e)
{
if (sender is Button { IsMouseCaptured: true })
{
StopCalibration(sender);
ReleaseMouseCapture(sender);
}
}
private void CalibrationButton_LostMouseCapture(object sender, MouseEventArgs e)
{
StopCalibration(sender);
}
private void CalibrationButton_TouchDown(object sender, TouchEventArgs e)
{
StartCalibration(sender);
if (sender is Button button)
{
button.CaptureTouch(e.TouchDevice);
}
e.Handled = true;
}
private void CalibrationButton_TouchUp(object sender, TouchEventArgs e)
{
StopCalibration(sender);
ReleaseTouchCapture(sender, e.TouchDevice);
e.Handled = true;
}
private void CalibrationButton_TouchLeave(object sender, TouchEventArgs e)
{
StopCalibration(sender);
ReleaseTouchCapture(sender, e.TouchDevice);
}
private void CalibrationButton_LostTouchCapture(object sender, TouchEventArgs e)
{
StopCalibration(sender);
}
private void StartCalibration(object sender)
{
if (TryGetCalibrationContext(sender, out var viewModel, out var action))
{
viewModel.PressCalibration(action.Label);
}
}
private void StopCalibration(object sender)
{
if (TryGetCalibrationContext(sender, out var viewModel, out var action))
{
viewModel.ReleaseCalibration(action.Label);
}
}
private bool TryGetCalibrationContext(
object sender,
out SmokeDensitySettingsViewModel viewModel,
out SmokeDensityCalibrationViewModel action)
{
viewModel = null!;
action = null!;
if (DataContext is not SmokeDensitySettingsViewModel smokeDensitySettingsViewModel
|| sender is not Button { DataContext: SmokeDensityCalibrationViewModel calibrationAction })
{
return false;
}
viewModel = smokeDensitySettingsViewModel;
action = calibrationAction;
return true;
}
private static void ReleaseMouseCapture(object sender)
{
if (sender is Button { IsMouseCaptured: true } button)
{
button.ReleaseMouseCapture();
}
}
private static void ReleaseTouchCapture(object sender, TouchDevice touchDevice)
{
if (sender is Button button)
{
button.ReleaseTouchCapture(touchDevice);
}
}
}