Files
HC_APTBS/MainWindow.xaml
LucianoDev 4891eb6812 feat: redesign bench calibration (factor/offset), add Ttank/P2 displays, fix sensor calibration
- Replace P1-P6 rational transfer function with factor/offset model for bench params
- Add explicit rx/tx direction flags in bench XML configuration
- Add T.Tank (BenchTemp) and P2 (AnalogSensor2) to temperature/pressure display
- Apply SensorConfiguration calibration to pressure channels, fix empty sensors.xml fallback
- Add live value labels to flowmeter charts
- Hide pump live values and PSG encoder standalone label
- Add K-Line connection state model, improve KWP service and status displays
- Restructure .claude/skills into subdirectory format

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 21:25:30 +02:00

545 lines
39 KiB
XML

<Window x:Class="HC_APTBS.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:vm="clr-namespace:HC_APTBS.ViewModels"
xmlns:uc="clr-namespace:HC_APTBS.Views.UserControls"
xmlns:models="clr-namespace:HC_APTBS.Models"
mc:Ignorable="d"
Title="HC_APTBS — Herlic Test Bench"
Height="1080" Width="1920"
WindowState="Maximized"
WindowStartupLocation="CenterScreen"
FontFamily="Ebrima"
Background="#FFEDEDED"
Closing="OnWindowClosing">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
<!-- LCD blue gradient border -->
<Style x:Key="LcdBlue" TargetType="Border">
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="4"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.3,0" EndPoint="0.5,1.3">
<GradientStop Color="#0040ff" Offset="0"/>
<GradientStop Color="#0031c2" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<!-- LCD amber gradient border -->
<Style x:Key="LcdAmber" TargetType="Border">
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="3"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.3,0" EndPoint="0.5,1.3">
<GradientStop Color="#ffae00" Offset="0"/>
<GradientStop Color="#91670a" Offset="2"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<!-- Connection indicator style (green/gray) -->
<Style x:Key="ConnIndicator" TargetType="Border">
<Setter Property="Background" Value="Gray"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Margin" Value="2,4"/>
</Style>
<!-- Relay toggle button style -->
<Style x:Key="RelayButton" TargetType="Button">
<Setter Property="Padding" Value="6,3"/>
<Setter Property="Margin" Value="3,2"/>
<Setter Property="FontSize" Value="11"/>
</Style>
</Window.Resources>
<DockPanel>
<!-- ── Menu bar ──────────────────────────────────────────────────── -->
<Menu DockPanel.Dock="Top" Background="#FFEDEDED">
<MenuItem Header="Settings" Command="{Binding SaveSettingsCommand}"/>
</Menu>
<!-- ── Status bar ─────────────────────────────────────────────────── -->
<StatusBar DockPanel.Dock="Bottom" Height="24" Background="#FFD0D0D0">
<StatusBarItem>
<TextBlock Text="{Binding CanStatusText}" Margin="4,0"/>
</StatusBarItem>
<Separator/>
<StatusBarItem>
<TextBlock Text="{Binding VerboseStatus}" Margin="4,0"/>
</StatusBarItem>
</StatusBar>
<!-- ── Three-column main layout ───────────────────────────────────── -->
<Grid>
<Grid.ColumnDefinitions>
<!-- Left: bench controls -->
<ColumnDefinition Width="500" MinWidth="400" MaxWidth="600"/>
<!-- Splitter -->
<ColumnDefinition Width="5"/>
<!-- Middle: pump + test + DFI -->
<ColumnDefinition Width="460" MinWidth="380" MaxWidth="560"/>
<!-- Splitter -->
<ColumnDefinition Width="5"/>
<!-- Right: live test display + results -->
<ColumnDefinition Width="*" MinWidth="600"/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch"
Background="#FF7F7F7F" ResizeBehavior="PreviousAndNext"/>
<GridSplitter Grid.Column="3" Width="5" HorizontalAlignment="Stretch"
Background="#FF7F7F7F" ResizeBehavior="PreviousAndNext"/>
<!-- ══════════════════════════════════════════════════════════════
LEFT PANEL — bench status and controls
══════════════════════════════════════════════════════════════ -->
<Expander Header="Bench" IsExpanded="True" Margin="0,2,0,0">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!-- Row 0: connection status -->
<RowDefinition Height="Auto"/> <!-- Row 1: CAN buttons -->
<RowDefinition Height="Auto"/> <!-- Row 2: two-column info + controls -->
<RowDefinition Height="Auto"/> <!-- Row 3: flowmeter charts -->
<RowDefinition Height="Auto"/> <!-- Row 4: angle display -->
</Grid.RowDefinitions>
<!-- ── Row 0: Connection status indicators ─────────────── -->
<Border BorderBrush="Black" BorderThickness="1" Margin="0,4,0,4">
<Grid Margin="4,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Status:" VerticalAlignment="Center"
FontSize="10" Margin="0,0,6,0"/>
<Border Grid.Column="1">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource ConnIndicator}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsCanConnected}" Value="True">
<Setter Property="Background" Value="#26C200"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="CAN" HorizontalAlignment="Center"
FontSize="10" Padding="2"/>
</Border>
<Border Grid.Column="2">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource ConnIndicator}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsBenchConnected}" Value="True">
<Setter Property="Background" Value="#26C200"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="Bench" HorizontalAlignment="Center"
FontSize="10" Padding="2"/>
</Border>
<Border Grid.Column="3">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource ConnIndicator}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsPumpConnected}" Value="True">
<Setter Property="Background" Value="#26C200"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="Pump" HorizontalAlignment="Center"
FontSize="10" Padding="2"/>
</Border>
<Border Grid.Column="4">
<Border.Style>
<Style TargetType="Border" BasedOn="{StaticResource ConnIndicator}">
<Style.Triggers>
<DataTrigger Binding="{Binding KLineState}" Value="{x:Static models:KLineConnectionState.Connected}">
<Setter Property="Background" Value="#26C200"/>
</DataTrigger>
<DataTrigger Binding="{Binding KLineState}" Value="{x:Static models:KLineConnectionState.Failed}">
<Setter Property="Background" Value="#FF3333"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="K-Line" HorizontalAlignment="Center"
FontSize="10" Padding="2"/>
</Border>
</Grid>
</Border>
<!-- ── Row 1: CAN connect / disconnect ─────────────────── -->
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,4">
<Button Content="Connect CAN" Width="110" Margin="0,0,6,0"
Command="{Binding ConnectCanCommand}"/>
<Button Content="Disconnect CAN" Width="120"
Command="{Binding DisconnectCanCommand}"
IsEnabled="{Binding IsCanConnected}"/>
</StackPanel>
<!-- ── Row 2: Two-column layout (Info | Controls) ──────── -->
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- ─── Column 0: Bench Information ─────────────────── -->
<StackPanel>
<!-- RPM display with target and voltage -->
<Border Style="{StaticResource LcdBlue}" Margin="0,4" Padding="10,4">
<StackPanel>
<Grid Height="70">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding BenchRpm, StringFormat=F0}"
FontSize="60" FontWeight="UltraBold" Foreground="#EBEBFF"
HorizontalAlignment="Right" VerticalAlignment="Center"
FontFamily="Consolas"/>
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="6,0,0,0">
<TextBlock Text="rpm" FontSize="18" Foreground="#FFFFEB6E"/>
</StackPanel>
</Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="Target:" Foreground="#EBEBFF" FontSize="11" Margin="0,0,4,0"/>
<TextBlock Text="{Binding BenchControl.TargetRpm, StringFormat=F0}"
Foreground="#FFFFEB6E" FontSize="11" FontFamily="Consolas" Margin="0,0,8,0"/>
<TextBlock Text="V:" Foreground="#EBEBFF" FontSize="11" Margin="0,0,4,0"/>
<TextBlock Text="{Binding BenchControl.CommandVoltage, StringFormat=F3}"
Foreground="#FFFFEB6E" FontSize="11" FontFamily="Consolas"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Temperatures and Pressure -->
<Border Style="{StaticResource LcdBlue}" Margin="0,4" Padding="8,4">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="T. In:" Grid.Row="0" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="T. Out:" Grid.Row="1" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="T. 4:" Grid.Row="2" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="T. Tank:" Grid.Row="3" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="P1:" Grid.Row="4" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="P2:" Grid.Row="5" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="{Binding TempIn, StringFormat=F1}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
<TextBlock Text="{Binding TempOut, StringFormat=F1}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
<TextBlock Text="{Binding Temp4, StringFormat=F1}" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
<TextBlock Text="{Binding BenchTemp, StringFormat=F1}" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
<TextBlock Text="{Binding Pressure, StringFormat=F1}" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
<TextBlock Text="{Binding Pressure2, StringFormat=F1}" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
<TextBlock Text="°C" Grid.Row="0" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
<TextBlock Text="°C" Grid.Row="1" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
<TextBlock Text="°C" Grid.Row="2" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
<TextBlock Text="°C" Grid.Row="3" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
<TextBlock Text="bar" Grid.Row="4" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
<TextBlock Text="bar" Grid.Row="5" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
</Grid>
</Border>
<!-- Q measurements -->
<Border Style="{StaticResource LcdAmber}" Margin="0,4" Padding="8,4">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Q-Del.:" VerticalAlignment="Center" Foreground="#FFFFEB6E" FontSize="13"/>
<TextBlock Text="Q-Over:" Grid.Row="1" VerticalAlignment="Center" Foreground="#FFFFEB6E" FontSize="13"/>
<TextBlock Text="{Binding QDelivery, StringFormat=F3}" Grid.Column="1" HorizontalAlignment="Right" Foreground="#FFFFEB6E" FontSize="22" FontFamily="Consolas"/>
<TextBlock Text="{Binding QOver, StringFormat=F3}" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right" Foreground="#FFFFEB6E" FontSize="22" FontFamily="Consolas"/>
<TextBlock Text="cc/stroke" Grid.Column="2" VerticalAlignment="Center" Foreground="#FFFFEB6E" FontSize="11" Margin="4,0"/>
<TextBlock Text="cc/stroke" Grid.Column="2" Grid.Row="1" VerticalAlignment="Center" Foreground="#FFFFEB6E" FontSize="11" Margin="4,0"/>
</Grid>
</Border>
<!-- Pump live values -->
<Border BorderBrush="#888" BorderThickness="1" Margin="0,4" Padding="8,4" Visibility="Collapsed">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="P-RPM:" VerticalAlignment="Center" FontSize="12" Foreground="DimGray"/>
<TextBlock Text="P-Temp:" Grid.Row="1" VerticalAlignment="Center" FontSize="12" Foreground="DimGray"/>
<TextBlock Text="P-ME:" Grid.Row="2" VerticalAlignment="Center" FontSize="12" Foreground="DimGray"/>
<TextBlock Text="P-FBkW:" Grid.Row="3" VerticalAlignment="Center" FontSize="12" Foreground="DimGray"/>
<TextBlock Text="{Binding PumpRpm, StringFormat=F0}" Grid.Column="1" HorizontalAlignment="Right" FontSize="16" FontFamily="Consolas"/>
<TextBlock Text="{Binding PumpTemp, StringFormat=F1}" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right" FontSize="16" FontFamily="Consolas"/>
<TextBlock Text="{Binding PumpMe, StringFormat=F2}" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Right" FontSize="16" FontFamily="Consolas"/>
<TextBlock Text="{Binding PumpFbkw, StringFormat=F2}" Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right" FontSize="16" FontFamily="Consolas"/>
</Grid>
</Border>
<!-- PSG encoder value -->
<StackPanel Orientation="Horizontal" Margin="0,4" Visibility="Collapsed">
<TextBlock Text="PSG Encoder:" VerticalAlignment="Center" FontSize="12" Margin="0,0,8,0"/>
<TextBlock Text="{Binding PsgEncoderValue, StringFormat=F2}"
FontSize="16" FontFamily="Consolas" VerticalAlignment="Center"/>
</StackPanel>
</StackPanel>
<!-- ─── Column 1: User Commands ─────────────────────── -->
<StackPanel Grid.Column="1" Width="160" Margin="6,0,0,0">
<!-- Direction toggle -->
<TextBlock Text="Direction" FontSize="10" Foreground="DimGray" Margin="0,4,0,2"/>
<ToggleButton IsChecked="{Binding BenchControl.IsDirectionRight}"
Height="32" FontSize="12" FontWeight="SemiBold">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Content" Value="LEFT"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="RIGHT"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<!-- Start / Stop bench -->
<TextBlock Text="Bench Motor" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
<Button Content="START" FontSize="13" FontWeight="Bold" Height="36"
Foreground="DarkGreen" Margin="0,0,0,4"
Command="{Binding BenchControl.OpenRpmPopupCommand}"/>
<Popup StaysOpen="False" Placement="Left"
IsOpen="{Binding BenchControl.IsRpmPopupOpen, Mode=TwoWay}">
<Border Background="White" BorderBrush="Black" BorderThickness="1" Padding="8">
<StackPanel Width="200">
<TextBlock Text="Set RPM:" FontSize="12" Margin="0,0,0,4"/>
<TextBox Text="{Binding BenchControl.RpmInputText, UpdateSourceTrigger=PropertyChanged}"
FontSize="16" FontFamily="Consolas" Height="28" Margin="0,0,0,6"/>
<Button Content="GO" FontSize="13" FontWeight="Bold" Height="30"
Foreground="DarkGreen" Margin="0,0,0,6"
Command="{Binding BenchControl.StartBenchCommand}"/>
<UniformGrid Columns="5">
<Button Content="100" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="100"/>
<Button Content="200" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="200"/>
<Button Content="300" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="300"/>
<Button Content="400" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="400"/>
<Button Content="500" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="500"/>
<Button Content="600" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="600"/>
<Button Content="700" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="700"/>
<Button Content="800" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="800"/>
<Button Content="900" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="900"/>
<Button Content="1000" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1000"/>
<Button Content="1200" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1200"/>
<Button Content="1400" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1400"/>
<Button Content="1600" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1600"/>
<Button Content="1800" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="1800"/>
<Button Content="2000" Style="{StaticResource RelayButton}" Command="{Binding BenchControl.SetQuickRpmCommand}" CommandParameter="2000"/>
</UniformGrid>
</StackPanel>
</Border>
</Popup>
<Button Content="STOP" FontSize="13" FontWeight="Bold" Height="36"
Foreground="DarkRed"
Command="{Binding BenchControl.StopBenchCommand}"/>
<!-- Oil pump toggle -->
<TextBlock Text="Oil Pump" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
<ToggleButton IsChecked="{Binding BenchControl.IsOilPumpOn}"
Height="32" FontSize="12" FontWeight="SemiBold">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Content" Value="OIL OFF"/>
<Setter Property="Background" Value="LightGray"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="OIL ON"/>
<Setter Property="Background" Value="#80FF80"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<!-- Turn counter -->
<TextBlock Text="Counter" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
<ToggleButton Content="Counter"
IsChecked="{Binding BenchControl.IsCounterPopupOpen}"
Height="28" FontSize="11"/>
<Popup StaysOpen="False" Placement="Left"
IsOpen="{Binding BenchControl.IsCounterPopupOpen, Mode=TwoWay}">
<Border Background="White" BorderBrush="Black" BorderThickness="1" Padding="8">
<StackPanel Width="160">
<TextBlock Text="Turns:" FontSize="12" Margin="0,0,0,4"/>
<TextBox Text="{Binding BenchControl.CounterInputText, UpdateSourceTrigger=PropertyChanged}"
FontSize="16" FontFamily="Consolas" Height="28" Margin="0,0,0,4"/>
<Button Content="Send" FontSize="12" Height="28"
Command="{Binding BenchControl.SendCounterCommand}"/>
</StackPanel>
</Border>
</Popup>
<TextBlock FontSize="14" FontFamily="Consolas" Margin="0,2"
Text="{Binding BenchControl.BenchCounterValue, StringFormat=00000000}"/>
<!-- Relay toggles -->
<TextBlock Text="Relays" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
<StackPanel>
<Button Content="Electronic" Style="{StaticResource RelayButton}" Command="{Binding ToggleElectronicCommand}"/>
<Button Content="Deposit Cooler" Style="{StaticResource RelayButton}" Command="{Binding ToggleDepositCoolerCommand}"/>
<Button Content="Deposit Heater" Style="{StaticResource RelayButton}" Command="{Binding ToggleDepositHeaterCommand}"/>
</StackPanel>
</StackPanel>
</Grid>
<!-- ── Row 3: Flowmeter charts ─────────────────────────── -->
<StackPanel Grid.Row="3" Margin="0,4">
<uc:FlowmeterChartView DataContext="{Binding FlowmeterChart.Delivery}"/>
<uc:FlowmeterChartView DataContext="{Binding FlowmeterChart.Over}" Margin="0,4,0,0"/>
</StackPanel>
<!-- ── Row 4: Advance monitoring (encoder angles) ─────── -->
<uc:AngleDisplayView Grid.Row="4" Margin="0,4"
DataContext="{Binding AngleDisplay}"/>
</Grid>
</ScrollViewer>
</Expander>
<!-- ══════════════════════════════════════════════════════════════
MIDDLE PANEL — pump selection, K-Line, controls, live data, tests
══════════════════════════════════════════════════════════════ -->
<ScrollViewer Grid.Column="2" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!-- Pump selector -->
<RowDefinition Height="Auto"/> <!-- K-Line block -->
<RowDefinition Height="Auto"/> <!-- DFI manage -->
<RowDefinition Height="Auto"/> <!-- Pump manual controls -->
<RowDefinition Height="Auto"/> <!-- Pump live data -->
<RowDefinition Height="Auto"/> <!-- Status displays -->
</Grid.RowDefinitions>
<!-- Pump identification: selector + K-Line ECU info -->
<uc:PumpIdentificationView Grid.RowSpan="2"
DataContext="{Binding PumpIdentification}"/>
<!-- DFI management control -->
<Border Grid.Row="2" BorderBrush="#999" BorderThickness="0,0,0,1">
<uc:DfiManageView DataContext="{Binding DfiViewModel}"/>
</Border>
<!-- Pump manual controls (FBKW / ME / PreIn sliders) -->
<Border Grid.Row="3" BorderBrush="#999" BorderThickness="0,0,0,1" Padding="0,4">
<uc:PumpControlView DataContext="{Binding PumpControl}"/>
</Border>
<!-- Pump live data (LCD-style display) -->
<Border Grid.Row="4" Style="{StaticResource LcdBlue}" Margin="6,4" Padding="8,4">
<Grid Height="90">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1.2*"/>
<RowDefinition/>
<RowDefinition Height="1.2*"/>
</Grid.RowDefinitions>
<TextBlock Text="T-hyb" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="RPM" Grid.Row="1" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="T-ein" Grid.Row="2" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
<TextBlock Text="{Binding PumpTemp, StringFormat=F2}" Grid.Column="1"
HorizontalAlignment="Right" VerticalAlignment="Center"
Foreground="#EBEBFF" FontSize="20" FontWeight="Bold" FontFamily="Consolas"/>
<TextBlock Text="{Binding PumpRpm, StringFormat=F0}" Grid.Column="1" Grid.Row="1"
HorizontalAlignment="Right" VerticalAlignment="Center"
Foreground="#EBEBFF" FontSize="20" FontWeight="Bold" FontFamily="Consolas"/>
<TextBlock Text="{Binding PumpTein, StringFormat=F0}" Grid.Column="1" Grid.Row="2"
HorizontalAlignment="Right" VerticalAlignment="Center"
Foreground="#EBEBFF" FontSize="20" FontWeight="Bold" FontFamily="Consolas"/>
<TextBlock Text="°C" Grid.Column="2" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="12" Margin="4,0"/>
<TextBlock Text="1/min" Grid.Column="2" Grid.Row="1" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="12" Margin="4,0"/>
<TextBlock Text="µs" Grid.Column="2" Grid.Row="2" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="12" Margin="4,0"/>
</Grid>
</Border>
<!-- Status displays (Status word + Empf3 word) -->
<StackPanel Grid.Row="5" Margin="6,4">
<uc:StatusDisplayView DataContext="{Binding StatusDisplay1}"/>
<uc:StatusDisplayView DataContext="{Binding StatusDisplay2}" Margin="0,4,0,0"/>
</StackPanel>
</Grid>
</ScrollViewer>
<!-- ══════════════════════════════════════════════════════════════
RIGHT PANEL — active test phases + results
══════════════════════════════════════════════════════════════ -->
<Grid Grid.Column="4">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!-- Test display (phase cards) -->
<RowDefinition/> <!-- Results table -->
</Grid.RowDefinitions>
<!-- Test panel: all test sections with phase cards and graphic indicators -->
<uc:TestPanelView DataContext="{Binding TestPanel}" Margin="0,2,0,4"/>
<!-- Results table (bound to ResultDisplayViewModel) -->
<uc:ResultDisplayView Grid.Row="1" Margin="0,2"
DataContext="{Binding ResultDisplay}"/>
</Grid>
</Grid>
</DockPanel>
</Window>