- Replace sub-nav + HiddenTabsTabControl with 3-column Fluent card layout: PumpCommandsCard (vertical ME/FBKW/PreIn sliders) + DfiCalibrationCard / PumpLiveDataCard (KPI tiles + RPM rolling chart + redesigned status bytes) / PumpIdentificationCard + DtcCard - Add PumpTopStripView: pump selector, model badge, CAN + K-Line chips - Move immobilizer unlock to MainWindow bottom snackbar (UnlockSnackbarView): auto-close on success after 3 s, persist on failure with manual Dismiss - Redesign StatusDisplayView to 2×8 rounded 28px tiles with bit index + tooltip - Add NullToVisibilityConverter; add SnackbarShell, PumpCard, and related styles - Delete obsolete views: UnlockProgressDialog, UnlockPanelView, PumpIdentificationPanelView, PumpLiveDataView, DfiManageView, DtcListView, PumpControlView - PumpPageViewModel: remove PumpSubPage enum, add RpmChart wired to Root.PumpRpm Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
221 lines
11 KiB
XML
221 lines
11 KiB
XML
<ui:FluentWindow x:Class="HC_APTBS.MainWindow"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:ui="http://schemas.lepo.co/wpfui/2022/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:pages="clr-namespace:HC_APTBS.Views.Pages"
|
|
xmlns:models="clr-namespace:HC_APTBS.Models"
|
|
mc:Ignorable="d"
|
|
Title="{DynamicResource App.Title}"
|
|
Height="1080" Width="1920"
|
|
WindowState="Maximized"
|
|
WindowStartupLocation="CenterScreen"
|
|
FontFamily="Ebrima"
|
|
Closing="OnWindowClosing">
|
|
|
|
<DockPanel>
|
|
|
|
<!-- ── WPF-UI custom title bar (replaces OS chrome) ──────────────────── -->
|
|
<ui:TitleBar DockPanel.Dock="Top"
|
|
Title="{DynamicResource App.Title}"
|
|
ShowMaximize="True"
|
|
ShowMinimize="True"/>
|
|
|
|
<!-- ── Persistent app header: pump identification + connection state ──── -->
|
|
<Border DockPanel.Dock="Top" Background="Transparent"
|
|
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">
|
|
<StatusBarItem>
|
|
<TextBlock Text="{Binding CanStatusText}" Margin="4,0"/>
|
|
</StatusBarItem>
|
|
<Separator/>
|
|
<StatusBarItem>
|
|
<TextBlock Text="{Binding VerboseStatus}" Margin="4,0"/>
|
|
</StatusBarItem>
|
|
</StatusBar>
|
|
|
|
<!-- ── Main content: left navigation rail + hidden-tab page host ──── -->
|
|
<Grid>
|
|
<!-- Inner grid: nav rail (col 0) + page host (col 1) -->
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="180"/>
|
|
<ColumnDefinition Width="*"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!--
|
|
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="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<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>
|
|
|
|
<Border Grid.Row="1" Height="1" Background="#FF555C6B"
|
|
Margin="12,4,12,4"/>
|
|
|
|
<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>
|
|
<uc:UnlockSnackbarView DataContext="{Binding CurrentUnlockVm}"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Bottom"
|
|
Margin="0,0,0,8"/>
|
|
</Grid>
|
|
</DockPanel>
|
|
</ui:FluentWindow>
|