Files
HC_APTBS/Views/UserControls/GraphicIndicatorView.xaml
LucianoDev 827b811b39 feat: developer tools page, auto-test orchestrator, BIP display, tests redesign
Bundles several feature streams that have been iterating on the working tree:

- Developer Tools page (Debug-only via DEVELOPER_TOOLS symbol): hosts the
  identification card, manual KWP write + transaction log, ROM/EEPROM dump
  card with progress banner and completion message, persisted custom-commands
  library, persisted EEPROM passwords library. New service primitives:
  IKwpService.SendRawCustomAsync / ReadEepromAsync / ReadRomEepromAsync.
  Persistence mirrors the Clients XML pattern in two new files
  (custom_commands.xml, eeprom_passwords.xml).
- Auto-test orchestrator (IAutoTestOrchestrator + AutoTestState): linear
  K-Line read -> unlock -> bench-on -> test sequence with snackbar UI and
  progress dialog VM, gated on dashboard alarms.
- BIP-STATUS display: BipDisplayViewModel + BipDisplayView, RAM read at
  0x0106 via IKwpService.ReadBipStatusAsync; status definitions in
  BipStatusDefinition.
- Tests page redesign: TestSectionCard + PhaseTileView replacing the old
  TestPlanView/TestRunningView/TestDoneView/TestPreconditionsView/
  TestSectionView controls and their VMs.
- Pump command sliders: Fluent thick-track style with overhang thumb,
  click-anywhere-and-drag, mouse-wheel adjustment.
- Window startup: app.manifest declares PerMonitorV2 DPI awareness,
  MainWindow installs a WM_GETMINMAXINFO hook in OnSourceInitialized and
  maximizes there (after the hook is in place) so the app fits the work
  area exactly on any display configuration.
- Misc: PercentToPixelsConverter, seed_aliases.py one-shot pump-alias
  importer, tools/Import-BipStatus.ps1, kline_eeprom_spec.md and
  dump-functions reference docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 13:59:50 +02:00

132 lines
6.6 KiB
XML

<UserControl x:Class="HC_APTBS.Views.UserControls.GraphicIndicatorView"
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:sys="clr-namespace:System;assembly=System.Runtime"
xmlns:conv="clr-namespace:HC_APTBS.Converters"
xmlns:vm="clr-namespace:HC_APTBS.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=vm:GraphicIndicatorViewModel, IsDesignTimeCreatable=False}">
<!--
Vertical min/max/target gauge. Fluent-styled with DynamicResource tokens so
the control repaints on theme change. The bar fills from the bottom via an
inner ProgressBar (native easing on Value changes). An overlay rectangle
highlights the in-tolerance band; a thin accent line marks the target.
Fill colour reacts live to IsWithinTolerance and locks on IsPhaseCompleted
when the owning phase ends.
-->
<UserControl.Resources>
<conv:PercentToPixelsConverter x:Key="PercentToPixels"/>
<sys:Double x:Key="TrackHeightPx">92</sys:Double>
<!-- Fill-colour style for the inner ProgressBar. Triggers cascade:
phase completed + failed → critical (locked);
live out-of-tolerance → critical;
else → accent. -->
<Style x:Key="IndicatorFillStyle" TargetType="ProgressBar">
<Setter Property="Foreground" Value="{DynamicResource AccentFillColorDefaultBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsWithinTolerance}" Value="False">
<Setter Property="Foreground" Value="{DynamicResource SystemFillColorCriticalBrush}"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsPhaseCompleted}" Value="True"/>
<Condition Binding="{Binding PhasePassed}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="{DynamicResource SystemFillColorCriticalBrush}"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid Width="58" Margin="2,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <!-- Max label -->
<RowDefinition Height="92"/> <!-- Track -->
<RowDefinition Height="Auto"/> <!-- Min label -->
<RowDefinition Height="Auto"/> <!-- Param name -->
</Grid.RowDefinitions>
<!-- Max bound -->
<TextBlock Text="{Binding MaxBound, StringFormat=F1}"
FontSize="10"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
HorizontalAlignment="Center" Margin="0,0,0,2"/>
<!-- Gauge track -->
<Grid Grid.Row="1" SnapsToDevicePixels="True">
<!-- Track background -->
<Border Background="{DynamicResource ControlFillColorDefaultBrush}"
BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="3"/>
<!-- In-tolerance band -->
<Canvas ClipToBounds="True" Margin="1">
<Rectangle Width="56"
Fill="{DynamicResource AccentFillColorTertiaryBrush}"
Opacity="0.10"
Canvas.Left="0"
Canvas.Top="{Binding ToleranceBandTopPercent,
Converter={StaticResource PercentToPixels},
ConverterParameter={StaticResource TrackHeightPx}}"
Height="{Binding ToleranceBandHeightPercent,
Converter={StaticResource PercentToPixels},
ConverterParameter={StaticResource TrackHeightPx}}"/>
<!-- Target line (1 px accent) -->
<Line X1="0" X2="56" StrokeThickness="0.4" Opacity="0.20"
Stroke="{DynamicResource AccentTextFillColorPrimaryBrush}"
Canvas.Top="{Binding ExpectedMarkerPercent,
Converter={StaticResource PercentToPixels},
ConverterParameter={StaticResource TrackHeightPx}}"/>
</Canvas>
<!-- Fill bar (bottom-up) -->
<ProgressBar Orientation="Vertical"
Minimum="0" Maximum="100"
Value="{Binding ProgressPercent, Mode=OneWay}"
Background="Transparent"
BorderThickness="0"
Opacity="0.55"
Margin="1"
Style="{StaticResource IndicatorFillStyle}"/>
<!-- Numeric readout -->
<TextBlock Text="{Binding DisplayValue}"
FontSize="14" FontWeight="SemiBold"
HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasValue}" Value="False">
<Setter Property="Foreground" Value="{DynamicResource TextFillColorTertiaryBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
<!-- Min bound -->
<TextBlock Grid.Row="2"
Text="{Binding MinBound, StringFormat=F1}"
FontSize="10"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
HorizontalAlignment="Center" Margin="0,2,0,0"/>
<!-- Parameter name -->
<TextBlock Grid.Row="3"
Text="{Binding ParameterName}"
FontSize="11" FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
HorizontalAlignment="Center"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding ParameterName}"
Margin="0,1,0,0"/>
</Grid>
</UserControl>