feat: page-based navigation shell + Tests page wizard
Replace the monolithic MainWindow with a SelectedPage-driven shell (Dashboard / Pump / Bench / Tests / Results / Settings). The Tests page gets the Plan -> Preconditions -> Running -> Done wizard from ui-structure.md \u00a74, backed by a 7-item precondition gate and shared sub-views (PhaseCardView / TestSectionView / GraphicIndicatorView) extracted from the now-deleted monolithic TestPanelView. New VMs / views: - Tests wizard: TestPreconditions, PhaseCard, GraphicIndicator, TestSection, TestPlan, TestRunning, TestDone - Dashboard panels: DashboardConnection, DashboardReadings, DashboardAlarms, InterlockBanner, ResultHistory - Pump / bench panels: PumpIdentificationPanel, PumpLiveData, UnlockPanel, BenchDriveControl, BenchReadings, RelayBank, TemperatureControl, DtcList, AuthGate - Dialogs: generic ConfirmDialog, UserManageDialog, UserPromptDialog Supporting changes: - IsOilPumpOn exposed on MainViewModel for precondition evaluation - RequiresAuth added to TestDefinition (XML round-trip) - BipStatusDefinition + CompletedTestRun models - ~35 new Test.* localization keys (en + es) - Settings moved from modal dialog to full page - Pause / Retry / Skip stubs in TestRunningView; full spec in docs/gap-test-running-controls.md for follow-up implementation - docs/ui-structure.md captures the wizard design Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
662
MainWindow.xaml
662
MainWindow.xaml
@@ -5,6 +5,7 @@
|
||||
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:pages="clr-namespace:HC_APTBS.Views.Pages"
|
||||
xmlns:models="clr-namespace:HC_APTBS.Models"
|
||||
mc:Ignorable="d"
|
||||
Title="{DynamicResource App.Title}"
|
||||
@@ -15,62 +16,93 @@
|
||||
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="{DynamicResource Menu.Settings}" Command="{Binding OpenSettingsCommand}"/>
|
||||
<MenuItem Header="{DynamicResource App.LanguageLabel}" Command="{Binding ToggleLanguageCommand}"/>
|
||||
</Menu>
|
||||
<!-- ── Persistent app header: pump identification + connection state ──── -->
|
||||
<Border DockPanel.Dock="Top" Background="#FFEDEDED"
|
||||
BorderBrush="#999" BorderThickness="0,0,0,1" Visibility="Collapsed">
|
||||
<Grid Margin="4,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Pump selector + K-Line ECU info -->
|
||||
<uc:PumpIdentificationView DataContext="{Binding PumpIdentification}"/>
|
||||
|
||||
<!-- Connection indicators + CAN connect/disconnect -->
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal"
|
||||
VerticalAlignment="Center" Margin="8,0,0,0">
|
||||
<TextBlock Text="{DynamicResource Status.Label}" VerticalAlignment="Center"
|
||||
FontSize="10" Margin="0,0,6,0"/>
|
||||
|
||||
<Border Width="54" Margin="2,0">
|
||||
<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="{DynamicResource Status.Can}" HorizontalAlignment="Center"
|
||||
FontSize="10" Padding="2"/>
|
||||
</Border>
|
||||
|
||||
<Border Width="54" Margin="2,0">
|
||||
<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="{DynamicResource Status.Bench}" HorizontalAlignment="Center"
|
||||
FontSize="10" Padding="2"/>
|
||||
</Border>
|
||||
|
||||
<Border Width="54" Margin="2,0">
|
||||
<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="{DynamicResource Status.Pump}" HorizontalAlignment="Center"
|
||||
FontSize="10" Padding="2"/>
|
||||
</Border>
|
||||
|
||||
<Border Width="54" Margin="2,0,8,0">
|
||||
<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="{DynamicResource Status.KLine}" HorizontalAlignment="Center"
|
||||
FontSize="10" Padding="2"/>
|
||||
</Border>
|
||||
|
||||
<Button Content="{DynamicResource Bench.ConnectCan}" Width="110" Margin="4,0,4,0"
|
||||
Command="{Binding ConnectCanCommand}"/>
|
||||
<Button Content="{DynamicResource Bench.DisconnectCan}" Width="120"
|
||||
Command="{Binding DisconnectCanCommand}"
|
||||
IsEnabled="{Binding IsCanConnected}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ── Status bar ─────────────────────────────────────────────────── -->
|
||||
<StatusBar DockPanel.Dock="Bottom" Height="24" Background="#FFD0D0D0">
|
||||
@@ -83,463 +115,93 @@
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
|
||||
<!-- ── Three-column main layout ───────────────────────────────────── -->
|
||||
<!-- ── Main content: left navigation rail + hidden-tab page host ──── -->
|
||||
<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"/>
|
||||
<ColumnDefinition Width="180"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</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="{DynamicResource Bench.Header}" 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="{DynamicResource Status.Label}" 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="{DynamicResource Status.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="{DynamicResource Status.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="{DynamicResource Status.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="{DynamicResource Status.KLine}" 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="{DynamicResource Bench.ConnectCan}" Width="110" Margin="0,0,6,0"
|
||||
Command="{Binding ConnectCanCommand}"/>
|
||||
<Button Content="{DynamicResource Bench.DisconnectCan}" 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="{DynamicResource Bench.Rpm}" FontSize="18" Foreground="#FFFFEB6E"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<TextBlock Text="{DynamicResource Bench.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="{DynamicResource Bench.Voltage}" 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="{DynamicResource Bench.TempIn}" Grid.Row="0" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.TempOut}" Grid.Row="1" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.Temp4}" Grid.Row="2" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.TempTank}" Grid.Row="3" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.P1}" Grid.Row="4" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.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="{DynamicResource Bench.QDelivery}" VerticalAlignment="Center" Foreground="#FFFFEB6E" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.QOver}" 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="{DynamicResource Bench.CcStroke}" Grid.Column="2" VerticalAlignment="Center" Foreground="#FFFFEB6E" FontSize="11" Margin="4,0"/>
|
||||
<TextBlock Text="{DynamicResource Bench.CcStroke}" 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="{DynamicResource Bench.PumpRpm}" VerticalAlignment="Center" FontSize="12" Foreground="DimGray"/>
|
||||
<TextBlock Text="{DynamicResource Bench.PumpTemp}" Grid.Row="1" VerticalAlignment="Center" FontSize="12" Foreground="DimGray"/>
|
||||
<TextBlock Text="{DynamicResource Bench.PumpMe}" Grid.Row="2" VerticalAlignment="Center" FontSize="12" Foreground="DimGray"/>
|
||||
<TextBlock Text="{DynamicResource Bench.PumpFbkw}" 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="{DynamicResource Bench.PsgEncoder}" 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="{DynamicResource Bench.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="{DynamicResource Bench.Left}"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.Right}"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
|
||||
<!-- Start / Stop bench -->
|
||||
<TextBlock Text="{DynamicResource Bench.Motor}" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
|
||||
<Button Content="{DynamicResource Bench.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="{DynamicResource Bench.SetRpm}" 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="{DynamicResource Bench.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="{DynamicResource Bench.Stop}" FontSize="13" FontWeight="Bold" Height="36"
|
||||
Foreground="DarkRed"
|
||||
Command="{Binding BenchControl.StopBenchCommand}"/>
|
||||
|
||||
<!-- Oil pump toggle -->
|
||||
<TextBlock Text="{DynamicResource Bench.OilPump}" 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="{DynamicResource Bench.OilOff}"/>
|
||||
<Setter Property="Background" Value="LightGray"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.OilOn}"/>
|
||||
<Setter Property="Background" Value="#80FF80"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
|
||||
<!-- Turn counter -->
|
||||
<TextBlock Text="{DynamicResource Bench.Counter}" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
|
||||
<ToggleButton Content="{DynamicResource Bench.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="{DynamicResource Bench.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="{DynamicResource Bench.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="{DynamicResource Bench.Relays}" FontSize="10" Foreground="DimGray" Margin="0,8,0,2"/>
|
||||
<StackPanel>
|
||||
<Button Content="{DynamicResource Bench.Electronic}" Style="{StaticResource RelayButton}" Command="{Binding ToggleElectronicCommand}"/>
|
||||
<Button Content="{DynamicResource Bench.DepositCooler}" Style="{StaticResource RelayButton}" Command="{Binding ToggleDepositCoolerCommand}"/>
|
||||
<Button Content="{DynamicResource Bench.DepositHeater}" 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>
|
||||
<!--
|
||||
Nav rail column: primary pages at top, Settings pinned at bottom
|
||||
with a divider. Both ListBoxes bind to SelectedPage; WPF auto-
|
||||
deselects a ListBox whose SelectedValue is not among its items,
|
||||
so clicking Settings clears the top highlight and vice versa.
|
||||
-->
|
||||
<Grid Grid.Column="0" Background="#FF2F3440">
|
||||
<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 -->
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Pump identification: selector + K-Line ECU info -->
|
||||
<uc:PumpIdentificationView Grid.RowSpan="2"
|
||||
DataContext="{Binding PumpIdentification}"/>
|
||||
<ListBox Grid.Row="0"
|
||||
Style="{StaticResource NavRail}"
|
||||
SelectedValuePath="Tag"
|
||||
SelectedValue="{Binding SelectedPage, Mode=TwoWay}">
|
||||
<ListBoxItem Tag="{x:Static vm:AppPage.Dashboard}">
|
||||
<TextBlock Text="{DynamicResource Nav.Dashboard}"
|
||||
Foreground="#FFE6E6E6" FontSize="14"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:AppPage.Bench}">
|
||||
<TextBlock Text="{DynamicResource Nav.Bench}"
|
||||
Foreground="#FFE6E6E6" FontSize="14"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:AppPage.Pump}">
|
||||
<TextBlock Text="{DynamicResource Nav.Pump}"
|
||||
Foreground="#FFE6E6E6" FontSize="14"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:AppPage.Tests}">
|
||||
<TextBlock Text="{DynamicResource Nav.Tests}"
|
||||
Foreground="#FFE6E6E6" FontSize="14"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:AppPage.Results}">
|
||||
<TextBlock Text="{DynamicResource Nav.Results}"
|
||||
Foreground="#FFE6E6E6" FontSize="14"/>
|
||||
</ListBoxItem>
|
||||
</ListBox>
|
||||
|
||||
<!-- DFI management control -->
|
||||
<Border Grid.Row="2" BorderBrush="#999" BorderThickness="0,0,0,1">
|
||||
<uc:DfiManageView DataContext="{Binding DfiViewModel}"/>
|
||||
</Border>
|
||||
<Border Grid.Row="1" Height="1" Background="#FF555C6B"
|
||||
Margin="12,4,12,4"/>
|
||||
|
||||
<!-- 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="{DynamicResource Pump.THyb}" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Pump.Rpm}" Grid.Row="1" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Pump.TEin}" 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="{DynamicResource Pump.UnitRpm}" 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}"/>
|
||||
<ListBox Grid.Row="2"
|
||||
Style="{StaticResource NavRail}"
|
||||
SelectedValuePath="Tag"
|
||||
SelectedValue="{Binding SelectedPage, Mode=TwoWay}">
|
||||
<ListBoxItem Tag="{x:Static vm:AppPage.Settings}">
|
||||
<TextBlock Text="{DynamicResource Nav.Settings}"
|
||||
Foreground="#FFE6E6E6" FontSize="14"/>
|
||||
</ListBoxItem>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
|
||||
<!--
|
||||
TabItem order must match AppPage enum values:
|
||||
Bench=0, Pump=1, Tests=2, Dashboard=3, Settings=4, Results=5.
|
||||
Nav rail order above is UX-driven (Dashboard first) via Tag binding.
|
||||
-->
|
||||
<TabControl Grid.Column="1"
|
||||
Style="{StaticResource HiddenTabsTabControl}"
|
||||
SelectedIndex="{Binding SelectedPage, Converter={StaticResource EnumToInt}}">
|
||||
<TabItem>
|
||||
<pages:BenchPage DataContext="{Binding BenchPage}"/>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<pages:PumpPage DataContext="{Binding PumpPage}"/>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<pages:TestsPage DataContext="{Binding TestsPage}"/>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<pages:DashboardPage DataContext="{Binding DashboardPage}"/>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<pages:SettingsPage DataContext="{Binding SettingsPage}"/>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<pages:ResultsPage DataContext="{Binding ResultsPage}"/>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
|
||||
Reference in New Issue
Block a user