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:
51
Views/Dialogs/ConfirmDialog.xaml
Normal file
51
Views/Dialogs/ConfirmDialog.xaml
Normal file
@@ -0,0 +1,51 @@
|
||||
<Window x:Class="HC_APTBS.Views.Dialogs.ConfirmDialog"
|
||||
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.Dialogs"
|
||||
mc:Ignorable="d"
|
||||
Title="{Binding Title}"
|
||||
Height="200" Width="440"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
d:DataContext="{d:DesignInstance Type=vm:ConfirmDialogViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Generic Yes/No modal. DataContext: ConfirmDialogViewModel.
|
||||
-->
|
||||
<Grid Margin="16,12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="48"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.RowSpan="2" Text="?"
|
||||
FontSize="36" Foreground="#1565C0"
|
||||
FontWeight="Bold"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Center"
|
||||
Margin="0,0,8,0"/>
|
||||
|
||||
<TextBlock Grid.Column="1" Text="{Binding Title}"
|
||||
FontSize="16" FontWeight="Bold" Foreground="#222"
|
||||
Margin="0,0,0,8"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="1"
|
||||
Text="{Binding Message}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalAlignment="Top"/>
|
||||
|
||||
<StackPanel Grid.Row="2" Grid.Column="1"
|
||||
Orientation="Horizontal" HorizontalAlignment="Right"
|
||||
Margin="0,12,0,0">
|
||||
<Button Content="{Binding ConfirmText}" MinWidth="80" Height="26" Margin="0,0,8,0"
|
||||
Command="{Binding ConfirmCommand}" IsDefault="True"/>
|
||||
<Button Content="{Binding CancelText}" MinWidth="80" Height="26"
|
||||
Command="{Binding CancelCommand}" IsCancel="True"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
21
Views/Dialogs/ConfirmDialog.xaml.cs
Normal file
21
Views/Dialogs/ConfirmDialog.xaml.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Windows;
|
||||
using HC_APTBS.ViewModels.Dialogs;
|
||||
|
||||
namespace HC_APTBS.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic Yes/No (or Confirm/Cancel) modal dialog. See <see cref="ConfirmDialogViewModel"/>
|
||||
/// for call-site usage — caller configures Title/Message/button text and inspects
|
||||
/// <see cref="ConfirmDialogViewModel.Accepted"/> after closing.
|
||||
/// </summary>
|
||||
public partial class ConfirmDialog : Window
|
||||
{
|
||||
/// <summary>Creates the dialog and wires the ViewModel.</summary>
|
||||
public ConfirmDialog(ConfirmDialogViewModel vm)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = vm;
|
||||
vm.RequestClose += Close;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@
|
||||
<GroupBox Grid.Column="1" Grid.Row="3" Header="{DynamicResource Dialog.Report.Observations}"
|
||||
Margin="8,0,8,4" FontSize="13">
|
||||
<TextBox Text="{Binding Observations, UpdateSourceTrigger=PropertyChanged}"
|
||||
TextWrapping="Wrap"
|
||||
TextWrapping="Wrap" AcceptsReturn="True"
|
||||
BorderBrush="{x:Null}" FontSize="12"/>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
using System.Windows;
|
||||
using HC_APTBS.ViewModels.Dialogs;
|
||||
|
||||
namespace HC_APTBS.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Dialog for editing all application settings.
|
||||
/// </summary>
|
||||
public partial class SettingsDialog : Window
|
||||
{
|
||||
public SettingsDialog(SettingsViewModel vm)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = vm;
|
||||
vm.RequestClose += Close;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
Views/Dialogs/UserManageDialog.xaml
Normal file
60
Views/Dialogs/UserManageDialog.xaml
Normal file
@@ -0,0 +1,60 @@
|
||||
<Window x:Class="HC_APTBS.Views.Dialogs.UserManageDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="{DynamicResource Dialog.UserManage.Title}"
|
||||
Height="360" Width="460"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
FontFamily="Ebrima"
|
||||
Background="#FFEDEDED">
|
||||
|
||||
<DockPanel Margin="12">
|
||||
|
||||
<!-- ── Bottom bar: Close ─────────────────────────────────────────── -->
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
|
||||
HorizontalAlignment="Right" Margin="0,12,0,0">
|
||||
<Button Content="{DynamicResource Dialog.UserManage.Close}" Width="90" Height="26"
|
||||
Command="{Binding CloseCommand}" IsCancel="True" IsDefault="True"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Action buttons under the grid ─────────────────────────────── -->
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<Button Content="{DynamicResource Dialog.UserManage.Add}" Width="95" Height="26"
|
||||
Margin="0,0,8,0" Command="{Binding AddCommand}"/>
|
||||
<Button Content="{DynamicResource Dialog.UserManage.Remove}" Width="95" Height="26"
|
||||
Margin="0,0,8,0" Command="{Binding RemoveCommand}"/>
|
||||
<Button Content="{DynamicResource Dialog.UserManage.ChangePassword}" Width="140" Height="26"
|
||||
Command="{Binding ChangePasswordCommand}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── User list ─────────────────────────────────────────────────── -->
|
||||
<DataGrid x:Name="UsersGrid"
|
||||
ItemsSource="{Binding Users}"
|
||||
SelectedItem="{Binding SelectedUser, Mode=TwoWay}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
CanUserDeleteRows="False"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserResizeRows="False"
|
||||
IsReadOnly="True"
|
||||
SelectionMode="Single"
|
||||
HeadersVisibility="Column"
|
||||
GridLinesVisibility="Horizontal">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Width="*">
|
||||
<DataGridTemplateColumn.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{DynamicResource Dialog.UserManage.ColumnUsername}"/>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.HeaderTemplate>
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding}" VerticalAlignment="Center" Margin="6,0"/>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
</DockPanel>
|
||||
</Window>
|
||||
21
Views/Dialogs/UserManageDialog.xaml.cs
Normal file
21
Views/Dialogs/UserManageDialog.xaml.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Windows;
|
||||
using HC_APTBS.ViewModels.Dialogs;
|
||||
|
||||
namespace HC_APTBS.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Admin dialog for managing the stored user list: add, remove, and change password.
|
||||
/// Each action persists immediately via <see cref="Services.IConfigurationService"/>;
|
||||
/// the Close button simply dismisses the window.
|
||||
/// </summary>
|
||||
public partial class UserManageDialog : Window
|
||||
{
|
||||
/// <summary>Creates the dialog and wires the ViewModel.</summary>
|
||||
public UserManageDialog(UserManageViewModel vm)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = vm;
|
||||
vm.RequestClose += Close;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
Views/Dialogs/UserPromptDialog.xaml
Normal file
48
Views/Dialogs/UserPromptDialog.xaml
Normal file
@@ -0,0 +1,48 @@
|
||||
<Window x:Class="HC_APTBS.Views.Dialogs.UserPromptDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
Title="{DynamicResource Dialog.UserManage.Prompt.AddTitle}"
|
||||
Height="170" Width="420"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
FontFamily="Ebrima"
|
||||
Background="#FFEDEDED">
|
||||
|
||||
<Grid Margin="16,12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="110"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Username (hidden when UsernameVisible == false) -->
|
||||
<Label x:Name="LblUsername"
|
||||
Content="{DynamicResource Dialog.UserCheck.Username}"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<TextBox x:Name="TbUsername" Grid.Column="1"
|
||||
Margin="8,4" Height="26" VerticalContentAlignment="Center"/>
|
||||
|
||||
<!-- Password -->
|
||||
<Label Grid.Row="1"
|
||||
Content="{DynamicResource Dialog.UserCheck.Password}"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
<PasswordBox x:Name="PbPassword" Grid.Row="1" Grid.Column="1"
|
||||
Margin="8,4" Height="26" VerticalContentAlignment="Center"/>
|
||||
|
||||
<!-- Buttons -->
|
||||
<StackPanel Grid.Row="2" Grid.Column="1"
|
||||
Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
|
||||
<Button Content="{DynamicResource Common.Accept}" Width="80" Height="26" Margin="0,0,8,0"
|
||||
Click="OnAccept" IsDefault="True"/>
|
||||
<Button Content="{DynamicResource Common.Cancel}" Width="80" Height="26"
|
||||
IsCancel="True"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
59
Views/Dialogs/UserPromptDialog.xaml.cs
Normal file
59
Views/Dialogs/UserPromptDialog.xaml.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HC_APTBS.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Small input dialog that prompts for a username and password, or a password only.
|
||||
/// Used by <see cref="Views.Dialogs.UserManageDialog"/> when adding a new user or
|
||||
/// changing an existing user's password. Kept as a code-behind dialog (not MVVM)
|
||||
/// because it is a transient prompt with no shared state.
|
||||
/// </summary>
|
||||
public partial class UserPromptDialog : Window
|
||||
{
|
||||
/// <summary>Username entered by the operator. Empty when <see cref="UsernameVisible"/> is false.</summary>
|
||||
public string EnteredUsername { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>Password entered by the operator.</summary>
|
||||
public string EnteredPassword { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the dialog.
|
||||
/// </summary>
|
||||
/// <param name="title">Window title (already-localised string).</param>
|
||||
/// <param name="usernameVisible">
|
||||
/// True to show the username field (Add user flow); false to hide it (Change password flow).
|
||||
/// </param>
|
||||
/// <param name="prefillUsername">
|
||||
/// Pre-filled, read-only username shown as a label when <paramref name="usernameVisible"/> is false.
|
||||
/// Ignored otherwise.
|
||||
/// </param>
|
||||
public UserPromptDialog(string title, bool usernameVisible, string prefillUsername = "")
|
||||
{
|
||||
InitializeComponent();
|
||||
Title = title;
|
||||
|
||||
if (usernameVisible)
|
||||
{
|
||||
EnteredUsername = string.Empty;
|
||||
TbUsername.Focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide username row; reserve width so layout doesn't shift.
|
||||
LblUsername.Visibility = Visibility.Collapsed;
|
||||
TbUsername.Visibility = Visibility.Collapsed;
|
||||
EnteredUsername = prefillUsername;
|
||||
PbPassword.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAccept(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (TbUsername.Visibility == Visibility.Visible)
|
||||
EnteredUsername = TbUsername.Text;
|
||||
EnteredPassword = PbPassword.Password;
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
66
Views/Pages/BenchPage.xaml
Normal file
66
Views/Pages/BenchPage.xaml
Normal file
@@ -0,0 +1,66 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.Pages.BenchPage"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="900" d:DesignWidth="1280">
|
||||
<!--
|
||||
Bench page — HMI-style manual hardware operation.
|
||||
DataContext = BenchPageViewModel.
|
||||
Three zones:
|
||||
A. Live readings (LCD panel + encoder angles)
|
||||
B. Live plots (Q flows + pressure traces)
|
||||
C. Controls (drive, temperature, relay bank)
|
||||
Interlock banner spans the page above zone contents when triggered.
|
||||
-->
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
||||
<Grid Margin="6">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- interlock banner -->
|
||||
<RowDefinition Height="*"/> <!-- main content -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Interlock banner: hidden unless InterlockBannerViewModel raises a condition -->
|
||||
<uc:InterlockBannerView Grid.Row="0" DataContext="{Binding Interlock}"/>
|
||||
|
||||
<!-- Main content: 3 columns -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="400"/> <!-- Zone A: readings + angles -->
|
||||
<ColumnDefinition Width="*"/> <!-- Zone B: live plots -->
|
||||
<ColumnDefinition Width="210"/> <!-- Zone C: controls -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- ── Zone A: readings + encoder angles ──────────────────── -->
|
||||
<StackPanel Grid.Column="0" Margin="0,0,6,0">
|
||||
<uc:BenchReadingsView/>
|
||||
<uc:AngleDisplayView DataContext="{Binding AngleDisplay}"
|
||||
Margin="0,6,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Zone B: live plots (flows + pressure) ──────────────── -->
|
||||
<StackPanel Grid.Column="1" Margin="0,0,6,0">
|
||||
<uc:FlowmeterChartView DataContext="{Binding FlowmeterChart.Delivery}"/>
|
||||
<uc:FlowmeterChartView DataContext="{Binding FlowmeterChart.Over}"
|
||||
Margin="0,4,0,0"/>
|
||||
<uc:FlowmeterChartView DataContext="{Binding PressureTrace.P1}"
|
||||
Margin="0,4,0,0"/>
|
||||
<uc:FlowmeterChartView DataContext="{Binding PressureTrace.P2}"
|
||||
Margin="0,4,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Zone C: stacked control panels ─────────────────────── -->
|
||||
<StackPanel Grid.Column="2">
|
||||
<uc:BenchDriveControlView/>
|
||||
<uc:TemperatureControlView DataContext="{Binding TempControl}"
|
||||
Margin="0,10,0,0"/>
|
||||
<uc:RelayBankView DataContext="{Binding RelayBank}"
|
||||
Margin="0,10,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
16
Views/Pages/BenchPage.xaml.cs
Normal file
16
Views/Pages/BenchPage.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Bench navigation page. DataContext is expected to be a
|
||||
/// <see cref="HC_APTBS.ViewModels.Pages.BenchPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class BenchPage : UserControl
|
||||
{
|
||||
public BenchPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
241
Views/Pages/DashboardPage.xaml
Normal file
241
Views/Pages/DashboardPage.xaml
Normal file
@@ -0,0 +1,241 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.Pages.DashboardPage"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="700" d:DesignWidth="980">
|
||||
<!--
|
||||
Dashboard — operator "at a glance" landing page.
|
||||
DataContext: DashboardPageViewModel. Read-first. Only Start / Stop / E-Stop are interactive.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<!-- Section card style -->
|
||||
<Style x:Key="DashCard" TargetType="Border">
|
||||
<Setter Property="Background" Value="#FAFAFA"/>
|
||||
<Setter Property="BorderBrush" Value="#DDD"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Padding" Value="10"/>
|
||||
<Setter Property="Margin" Value="4"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="DashHeader" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Foreground" Value="#333"/>
|
||||
<Setter Property="Margin" Value="0,0,0,6"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="6">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/> <!-- footer: quick actions -->
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="340"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- ── Left column: readings ───────────────────────────────────────── -->
|
||||
<Border Grid.Row="0" Grid.Column="0" Style="{StaticResource DashCard}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{DynamicResource Dashboard.Readings}" Style="{StaticResource DashHeader}"/>
|
||||
<uc:DashboardReadingsView/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ── Right column: connections + test summary + alarms ───────────── -->
|
||||
<Grid Grid.Row="0" Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Connections -->
|
||||
<Border Grid.Row="0" Grid.Column="0" Style="{StaticResource DashCard}">
|
||||
<uc:DashboardConnectionView/>
|
||||
</Border>
|
||||
|
||||
<!-- Test summary -->
|
||||
<Border Grid.Row="0" Grid.Column="1" Style="{StaticResource DashCard}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{DynamicResource Dashboard.TestSummary}" Style="{StaticResource DashHeader}"/>
|
||||
|
||||
<!-- Active test view (when running) -->
|
||||
<StackPanel Visibility="{Binding Root.IsTestRunning, Converter={StaticResource BoolToVis}}">
|
||||
<Grid Margin="0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Dashboard.TestActive}" Foreground="#555" FontSize="12"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Root.TestPanel.TestName}"
|
||||
FontWeight="SemiBold" FontSize="13" TextTrimming="CharacterEllipsis"/>
|
||||
</Grid>
|
||||
<Grid Margin="0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Dashboard.TestPhase}" Foreground="#555" FontSize="12"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Root.CurrentPhaseName}"
|
||||
FontFamily="Consolas" FontSize="13" TextTrimming="CharacterEllipsis"/>
|
||||
</Grid>
|
||||
<TextBlock Text="{Binding Root.VerboseStatus}" FontStyle="Italic"
|
||||
Foreground="#666" FontSize="11" Margin="0,6,0,0"
|
||||
TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Idle view (last result or "no test run") -->
|
||||
<StackPanel>
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.IsTestRunning}" Value="True">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
|
||||
<TextBlock Text="{DynamicResource Dashboard.NoTestRunning}"
|
||||
Foreground="#888" FontStyle="Italic" FontSize="12"/>
|
||||
|
||||
<Border Margin="0,8,0,0" Padding="8,4" CornerRadius="3"
|
||||
HorizontalAlignment="Left">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#D62828"/>
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding Root.IsTestSaved}" Value="False"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</MultiDataTrigger>
|
||||
<DataTrigger Binding="{Binding Root.LastTestSuccess}" Value="True">
|
||||
<Setter Property="Background" Value="#26C200"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Foreground="White" FontWeight="Bold" FontSize="12">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.LastTestFail}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.LastTestSuccess}" Value="True">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.LastTestPass}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Alarms (spans both columns of the right grid) -->
|
||||
<Border Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Style="{StaticResource DashCard}">
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top" Text="{DynamicResource Dashboard.Alarms}"
|
||||
Style="{StaticResource DashHeader}"/>
|
||||
|
||||
<!-- "System OK" banner when no alarms -->
|
||||
<Border Background="#26C200" CornerRadius="3" Padding="10,6"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||
Visibility="{Binding Alarms.IsClear, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock Text="{DynamicResource Dashboard.AlarmsNone}"
|
||||
Foreground="White" FontWeight="Bold" FontSize="12"/>
|
||||
</Border>
|
||||
|
||||
<!-- Active alarm list -->
|
||||
<ItemsControl ItemsSource="{Binding Alarms.ActiveAlarms}">
|
||||
<ItemsControl.Style>
|
||||
<Style TargetType="ItemsControl">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Alarms.IsClear}" Value="True">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ItemsControl.Style>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Margin="0,2" Padding="8,4" CornerRadius="3">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#FFB020"/> <!-- warning -->
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsCritical}" Value="True">
|
||||
<Setter Property="Background" Value="#D62828"/> <!-- critical -->
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="●" Foreground="White" FontSize="14" VerticalAlignment="Center" Margin="0,0,6,0"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Description}"
|
||||
Foreground="White" FontWeight="SemiBold" FontSize="12"
|
||||
VerticalAlignment="Center" TextWrapping="Wrap"/>
|
||||
<TextBlock Grid.Column="2" Foreground="#FFF" FontSize="11" FontFamily="Consolas"
|
||||
VerticalAlignment="Center" Margin="6,0,0,0">
|
||||
<Run Text="bit "/><Run Text="{Binding Bit, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- ── Footer: quick actions ───────────────────────────────────────── -->
|
||||
<Border Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
Background="#F0F0F0" BorderBrush="#CCC" BorderThickness="0,1,0,0"
|
||||
Padding="8" Margin="4,4,4,4">
|
||||
<DockPanel LastChildFill="False">
|
||||
<Button DockPanel.Dock="Left"
|
||||
Content="{DynamicResource Dashboard.Action.StartTest}"
|
||||
Command="{Binding Root.StartTestCommand}"
|
||||
Height="44" MinWidth="140" FontSize="13" FontWeight="Bold"
|
||||
Foreground="DarkGreen" Margin="0,0,6,0"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
ToolTip="{DynamicResource Dashboard.Action.StartTest.Tip}"/>
|
||||
|
||||
<Button DockPanel.Dock="Left"
|
||||
Content="{DynamicResource Dashboard.Action.Stop}"
|
||||
Command="{Binding Root.StopTestCommand}"
|
||||
Height="44" MinWidth="120" FontSize="13" FontWeight="Bold"
|
||||
Foreground="DarkRed" Margin="0,0,6,0"/>
|
||||
|
||||
<!-- E-Stop pinned right, red, always visible -->
|
||||
<Button DockPanel.Dock="Right"
|
||||
Content="{DynamicResource Dashboard.Action.EmergencyStop}"
|
||||
Command="{Binding Root.EmergencyStopCommand}"
|
||||
Height="44" MinWidth="200" FontSize="14" FontWeight="Bold"
|
||||
Foreground="White" Background="#D62828" BorderBrush="#8B0000"
|
||||
BorderThickness="2"/>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
16
Views/Pages/DashboardPage.xaml.cs
Normal file
16
Views/Pages/DashboardPage.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Dashboard navigation page. DataContext is expected to be a
|
||||
/// <see cref="HC_APTBS.ViewModels.Pages.DashboardPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class DashboardPage : UserControl
|
||||
{
|
||||
public DashboardPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
288
Views/Pages/PumpPage.xaml
Normal file
288
Views/Pages/PumpPage.xaml
Normal file
@@ -0,0 +1,288 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.Pages.PumpPage"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
xmlns:vm="clr-namespace:HC_APTBS.ViewModels.Pages"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="780" d:DesignWidth="1100">
|
||||
<!--
|
||||
Pump page — ECU diagnostics and control.
|
||||
DataContext = PumpPageViewModel.
|
||||
|
||||
Layout:
|
||||
- Banner row: K-Line session banner + "no pump selected" banner
|
||||
- Sub-nav (left): Identification / DTCs / LiveData / Adaptation / Unlock
|
||||
- Sub-page content (right): selected sub-section via hidden tabs
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<!-- Sub-nav item: narrower than the main rail, same accent pattern -->
|
||||
<Style x:Key="SubNavItem" TargetType="ListBoxItem">
|
||||
<Setter Property="Height" Value="44"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ListBoxItem">
|
||||
<Border x:Name="Root" Background="Transparent">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border x:Name="Accent" Grid.Column="0" Background="Transparent"/>
|
||||
<ContentPresenter Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Margin="12,0,6,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Root" Property="Background" Value="#ECECEC"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter TargetName="Root" Property="Background" Value="#E4EEF7"/>
|
||||
<Setter TargetName="Accent" Property="Background" Value="#2196F3"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="Opacity" Value="0.35"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SubNavText" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="Foreground" Value="#333"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- banners -->
|
||||
<RowDefinition Height="*"/> <!-- body -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════════
|
||||
Banners: K-Line session + no pump selected
|
||||
══════════════════════════════════════════════════════════════ -->
|
||||
<StackPanel Grid.Row="0">
|
||||
|
||||
<!-- K-Line session banner (closed / failed) -->
|
||||
<Border Padding="10,6">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#FFF3CD"/>
|
||||
<Setter Property="BorderBrush" Value="#FFC107"/>
|
||||
<Setter Property="BorderThickness" Value="0,0,0,1"/>
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsKLineSessionOpen}" Value="True">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsKLineSessionFailed}" Value="True">
|
||||
<Setter Property="Background" Value="#FDECEA"/>
|
||||
<Setter Property="BorderBrush" Value="#D62828"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock FontSize="12" TextWrapping="Wrap">
|
||||
<Run Text="●" FontSize="14"/>
|
||||
<Run Text=" "/>
|
||||
<Run Text="{DynamicResource Pump.KLineClosed}"/>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<!-- No pump selected banner (BoolToVis has no Invert support, so use a DataTrigger style) -->
|
||||
<Border Background="#E3F2FD" BorderBrush="#2196F3" BorderThickness="0,0,0,1"
|
||||
Padding="10,6">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsPumpSelected}" Value="False">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Text="{DynamicResource Pump.NoPumpSelected}"
|
||||
FontSize="12" Foreground="#0D47A1"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════════
|
||||
Body: sub-nav + sub-page content
|
||||
══════════════════════════════════════════════════════════════ -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- ── Sub-nav rail ───────────────────────────────────────── -->
|
||||
<Border Grid.Column="0" Background="#F7F7F7"
|
||||
BorderBrush="#DDD" BorderThickness="0,0,1,0">
|
||||
<ListBox SelectedValuePath="Tag" BorderThickness="0"
|
||||
Background="Transparent"
|
||||
ItemContainerStyle="{StaticResource SubNavItem}"
|
||||
SelectedValue="{Binding SelectedSubPage, Mode=TwoWay}">
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.Identification}">
|
||||
<TextBlock Text="{DynamicResource PumpSub.Identification}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.Dtcs}"
|
||||
IsEnabled="{Binding IsPumpSelected}">
|
||||
<TextBlock Text="{DynamicResource PumpSub.Dtcs}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.LiveData}"
|
||||
IsEnabled="{Binding IsPumpSelected}">
|
||||
<TextBlock Text="{DynamicResource PumpSub.LiveData}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.Adaptation}"
|
||||
IsEnabled="{Binding IsPumpSelected}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{DynamicResource PumpSub.Adaptation}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
<TextBlock Text=" 🔒" FontSize="11"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding DataContext.AdaptationAuth.IsAuthenticated,
|
||||
RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
Value="True">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem Tag="{x:Static vm:PumpSubPage.Unlock}">
|
||||
<ListBoxItem.Style>
|
||||
<Style TargetType="ListBoxItem" BasedOn="{StaticResource SubNavItem}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsUnlockApplicable}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ListBoxItem.Style>
|
||||
<TextBlock Text="{DynamicResource PumpSub.Unlock}"
|
||||
Style="{StaticResource SubNavText}"/>
|
||||
</ListBoxItem>
|
||||
</ListBox>
|
||||
</Border>
|
||||
|
||||
<!-- ── Sub-page content ───────────────────────────────────── -->
|
||||
<TabControl Grid.Column="1"
|
||||
Style="{StaticResource HiddenTabsTabControl}"
|
||||
SelectedIndex="{Binding SelectedSubPage, Converter={StaticResource EnumToInt}}">
|
||||
|
||||
<!-- 3a Identification -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<uc:PumpIdentificationPanelView
|
||||
DataContext="{Binding Identification}"/>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!-- 3b DTCs -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<uc:DtcListView DataContext="{Binding DtcList}"/>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!-- 3c Live Data — DataContext stays as PumpPageViewModel so
|
||||
the view can reach Root.PumpXxx and StatusDisplay1/2. -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<uc:PumpLiveDataView/>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!-- 3d Adaptation (auth-gated) -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<uc:AuthGateView DataContext="{Binding AdaptationAuth}">
|
||||
<uc:AuthGateView.GatedContent>
|
||||
<Border Background="#FAFAFA" BorderBrush="#DDD"
|
||||
BorderThickness="1" CornerRadius="4"
|
||||
Padding="12" Margin="6">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{DynamicResource PumpSub.Adaptation}"
|
||||
FontSize="15" FontWeight="SemiBold"
|
||||
Foreground="#333" Margin="0,0,0,8"/>
|
||||
<uc:DfiManageView DataContext="{Binding DataContext.DfiViewModel,
|
||||
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
|
||||
<Separator Margin="0,10"/>
|
||||
<uc:PumpControlView DataContext="{Binding DataContext.PumpControl,
|
||||
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</uc:AuthGateView.GatedContent>
|
||||
</uc:AuthGateView>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<!-- 3e Unlock -->
|
||||
<TabItem>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<Grid>
|
||||
<!-- "No active unlock" placeholder — visible when UnlockVm is null -->
|
||||
<Border Background="#F5F5F5" BorderBrush="#CCC"
|
||||
BorderThickness="1" CornerRadius="4"
|
||||
Padding="20" Margin="6"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding UnlockVm}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Text="{DynamicResource Pump.NoUnlockActive}"
|
||||
FontSize="13" Foreground="#666"/>
|
||||
</Border>
|
||||
|
||||
<!-- Active unlock panel — visible when UnlockVm is non-null.
|
||||
DataContext binds to UnlockVm so `{Binding}` inside the
|
||||
style evaluates to the VM instance (or null). -->
|
||||
<uc:UnlockPanelView DataContext="{Binding UnlockVm}">
|
||||
<uc:UnlockPanelView.Style>
|
||||
<Style TargetType="uc:UnlockPanelView">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</uc:UnlockPanelView.Style>
|
||||
</uc:UnlockPanelView>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
16
Views/Pages/PumpPage.xaml.cs
Normal file
16
Views/Pages/PumpPage.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Pump navigation page. DataContext is expected to be a
|
||||
/// <see cref="HC_APTBS.ViewModels.Pages.PumpPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class PumpPage : UserControl
|
||||
{
|
||||
public PumpPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Views/Pages/ResultsPage.xaml
Normal file
162
Views/Pages/ResultsPage.xaml
Normal file
@@ -0,0 +1,162 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.Pages.ResultsPage"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="700" d:DesignWidth="1100">
|
||||
<!--
|
||||
Results — review completed test runs, edit observations, export PDF.
|
||||
DataContext: ResultsPageViewModel. No live hardware data on this page.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<Style x:Key="DashCard" TargetType="Border">
|
||||
<Setter Property="Background" Value="#FAFAFA"/>
|
||||
<Setter Property="BorderBrush" Value="#DDD"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Padding" Value="10"/>
|
||||
<Setter Property="Margin" Value="4"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="DashHeader" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Foreground" Value="#333"/>
|
||||
<Setter Property="Margin" Value="0,0,0,6"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="320"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- ── Left: history list ─────────────────────────────────────────── -->
|
||||
<Border Grid.Column="0" Style="{StaticResource DashCard}">
|
||||
<uc:ResultHistoryView/>
|
||||
</Border>
|
||||
|
||||
<!-- ── Right: detail pane ──────────────────────────────────────────── -->
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- header -->
|
||||
<RowDefinition Height="*"/> <!-- results table -->
|
||||
<RowDefinition Height="Auto"/> <!-- observations -->
|
||||
<RowDefinition Height="Auto"/> <!-- actions -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Selected-run header -->
|
||||
<Border Grid.Row="0" Style="{StaticResource DashCard}"
|
||||
Visibility="{Binding SelectedRun, Converter={StaticResource BoolToVis}}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource DashHeader}">
|
||||
<Run Text="{Binding SelectedRun.PumpModel, Mode=OneWay}"/>
|
||||
<Run Text=" · "/>
|
||||
<Run Text="{Binding SelectedRun.PumpSerial, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="11" Foreground="#666"
|
||||
Text="{Binding SelectedRun.CompletedAt, StringFormat='{}{0:dd MMM yyyy HH:mm:ss}'}"/>
|
||||
<TextBlock FontSize="11" Foreground="#666" Margin="0,2,0,0"
|
||||
Text="{Binding SelectedRun.TestNames}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Overall verdict pill -->
|
||||
<Border Grid.Column="1" Padding="8,3" CornerRadius="3"
|
||||
VerticalAlignment="Center">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#B71C1C"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedRun.OverallPassed}" Value="True">
|
||||
<Setter Property="Background" Value="#2E7D32"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding SelectedRun.Interrupted}" Value="True">
|
||||
<Setter Property="Background" Value="#FFB020"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Foreground="White" FontSize="13" FontWeight="Bold">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{DynamicResource Common.Fail}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedRun.OverallPassed}" Value="True">
|
||||
<Setter Property="Text" Value="{DynamicResource Common.Pass}"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding SelectedRun.Interrupted}" Value="True">
|
||||
<Setter Property="Text" Value="{DynamicResource Results.InterruptedLabel}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Embedded ResultDisplayView — bound to the page's Detail VM -->
|
||||
<Border Grid.Row="1" Style="{StaticResource DashCard}"
|
||||
Visibility="{Binding SelectedRun, Converter={StaticResource BoolToVis}}">
|
||||
<uc:ResultDisplayView DataContext="{Binding Detail}"/>
|
||||
</Border>
|
||||
|
||||
<!-- Observations / notes -->
|
||||
<Border Grid.Row="2" Style="{StaticResource DashCard}"
|
||||
Visibility="{Binding SelectedRun, Converter={StaticResource BoolToVis}}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{DynamicResource Results.ObservationsLabel}"
|
||||
Style="{StaticResource DashHeader}"/>
|
||||
<TextBox Text="{Binding SelectedRun.Observations, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
AcceptsReturn="True" TextWrapping="Wrap"
|
||||
Height="80" VerticalScrollBarVisibility="Auto"
|
||||
FontSize="12"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Action row -->
|
||||
<Border Grid.Row="3" Background="#F0F0F0" BorderBrush="#CCC"
|
||||
BorderThickness="0,1,0,0" Padding="8" Margin="4,4,4,4"
|
||||
Visibility="{Binding SelectedRun, Converter={StaticResource BoolToVis}}">
|
||||
<DockPanel LastChildFill="False">
|
||||
<Button DockPanel.Dock="Right"
|
||||
Content="{DynamicResource Results.ExportButton}"
|
||||
Command="{Binding ExportPdfCommand}"
|
||||
Height="36" MinWidth="160" FontSize="13" FontWeight="Bold"
|
||||
Foreground="White" Background="#1976D2" BorderBrush="#0D47A1"
|
||||
BorderThickness="1"/>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Empty-state when no selection (covers rows 0-3) -->
|
||||
<Border Grid.Row="0" Grid.RowSpan="4"
|
||||
VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource DashCard}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SelectedRun}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Text="{DynamicResource Results.NoSelection}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
FontSize="13" Foreground="#888" FontStyle="Italic"
|
||||
TextWrapping="Wrap" TextAlignment="Center"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
14
Views/Pages/ResultsPage.xaml.cs
Normal file
14
Views/Pages/ResultsPage.xaml.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Results navigation page (§5 in <c>docs/ui-structure.md</c>).
|
||||
/// Review, compare, and export completed test runs. DataContext must be a
|
||||
/// <see cref="ViewModels.Pages.ResultsPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class ResultsPage : UserControl
|
||||
{
|
||||
public ResultsPage() => InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,25 @@
|
||||
<Window x:Class="HC_APTBS.Views.Dialogs.SettingsDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="{DynamicResource Dialog.Settings.Title}"
|
||||
Height="560" Width="680"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
FontFamily="Ebrima"
|
||||
Background="#FFEDEDED">
|
||||
<UserControl x:Class="HC_APTBS.Views.Pages.SettingsPage"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
FontFamily="Ebrima"
|
||||
Background="#FFEDEDED"
|
||||
d:DesignHeight="700" d:DesignWidth="980">
|
||||
<!--
|
||||
Settings page — form-based, grouped, tabbed.
|
||||
DataContext: SettingsPageViewModel. Changes only apply on Save.
|
||||
-->
|
||||
<DockPanel Margin="12">
|
||||
|
||||
<DockPanel Margin="8">
|
||||
|
||||
<!-- ── Bottom button bar ─────────────────────────────────────────── -->
|
||||
<!-- ── Bottom Save/Discard bar ───────────────────────────────────── -->
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
|
||||
HorizontalAlignment="Right" Margin="0,8,0,0">
|
||||
<Button Content="{DynamicResource Common.Accept}" Width="80" Height="26"
|
||||
Margin="0,0,8,0" Command="{Binding AcceptCommand}" IsDefault="True"/>
|
||||
<Button Content="{DynamicResource Common.Cancel}" Width="80" Height="26"
|
||||
Command="{Binding CancelCommand}" IsCancel="True"/>
|
||||
HorizontalAlignment="Right" Margin="0,12,0,0">
|
||||
<Button Content="{DynamicResource Common.Accept}" Width="90" Height="28"
|
||||
Margin="0,0,8,0" Command="{Binding SaveCommand}" IsDefault="True"/>
|
||||
<Button Content="{DynamicResource Common.Cancel}" Width="90" Height="28"
|
||||
Command="{Binding DiscardCommand}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Tab control ───────────────────────────────────────────────── -->
|
||||
@@ -35,6 +38,12 @@
|
||||
FontWeight="SemiBold" Margin="0,16,0,4"/>
|
||||
<TextBox Text="{Binding DaysKeepLogs, UpdateSourceTrigger=LostFocus}"
|
||||
Width="80" HorizontalAlignment="Left"/>
|
||||
|
||||
<TextBlock Text="{DynamicResource Dialog.Settings.UsersHeader}"
|
||||
FontWeight="SemiBold" Margin="0,16,0,4"/>
|
||||
<Button Content="{DynamicResource Dialog.Settings.ManageUsers}"
|
||||
Command="{Binding ManageUsersCommand}"
|
||||
Width="200" Height="26" HorizontalAlignment="Left"/>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
|
||||
@@ -229,8 +238,8 @@
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
|
||||
<!-- ══ Company ══════════════════════════════════════════════════ -->
|
||||
<TabItem Header="{DynamicResource Dialog.Settings.Tab.Company}">
|
||||
<!-- ══ Report ═══════════════════════════════════════════════════ -->
|
||||
<TabItem Header="{DynamicResource Dialog.Settings.Tab.Report}">
|
||||
<StackPanel Margin="16">
|
||||
<TextBlock Text="{DynamicResource Dialog.Settings.CompanyName}"
|
||||
FontWeight="SemiBold" Margin="0,0,0,4"/>
|
||||
@@ -330,4 +339,4 @@
|
||||
|
||||
</TabControl>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
</UserControl>
|
||||
17
Views/Pages/SettingsPage.xaml.cs
Normal file
17
Views/Pages/SettingsPage.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings navigation page. Hosts grouped configuration forms (General,
|
||||
/// Safety, PID, Motor, Report, K-Line, Advanced). DataContext is
|
||||
/// <see cref="HC_APTBS.ViewModels.Pages.SettingsPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class SettingsPage : UserControl
|
||||
{
|
||||
public SettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
204
Views/Pages/TestsPage.xaml
Normal file
204
Views/Pages/TestsPage.xaml
Normal file
@@ -0,0 +1,204 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.Pages.TestsPage"
|
||||
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:models="clr-namespace:HC_APTBS.Models"
|
||||
xmlns:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
xmlns:vm="clr-namespace:HC_APTBS.ViewModels"
|
||||
xmlns:vmp="clr-namespace:HC_APTBS.ViewModels.Pages"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="800" d:DesignWidth="1000"
|
||||
d:DataContext="{d:DesignInstance Type=vmp:TestsPageViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Plan → Preconditions → Running → Done wizard (ui-structure.md §4).
|
||||
DataContext: TestsPageViewModel.
|
||||
Top row: 4-pill stepper. Middle: ContentControl routing CurrentStateVm
|
||||
through typed DataTemplates. Bottom: wizard footer with Back / Next.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<!-- Step → View mappings -->
|
||||
<DataTemplate DataType="{x:Type vmp:PlanStateViewModel}">
|
||||
<uc:TestPlanView DataContext="{Binding TestPanel}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="{x:Type vm:TestPreconditionsViewModel}">
|
||||
<uc:TestPreconditionsView/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="{x:Type vmp:RunningStateViewModel}">
|
||||
<uc:TestRunningView DataContext="{Binding TestPanel}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="{x:Type vmp:TestsPageViewModel}">
|
||||
<uc:TestDoneView/>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Stepper pill style -->
|
||||
<Style x:Key="StepPillStyle" TargetType="Border">
|
||||
<Setter Property="CornerRadius" Value="12"/>
|
||||
<Setter Property="Padding" Value="14,4"/>
|
||||
<Setter Property="Margin" Value="0,0,6,0"/>
|
||||
<Setter Property="Background" Value="#ECEFF1"/>
|
||||
<Setter Property="BorderBrush" Value="#CFD8DC"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Wizard stepper -->
|
||||
<Border Background="White" BorderBrush="#DDD" BorderThickness="0,0,0,1" Padding="10,8">
|
||||
<ItemsControl>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<Border Style="{StaticResource StepPillStyle}">
|
||||
<Border.Resources>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource StepPillStyle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CurrentState}"
|
||||
Value="{x:Static models:TestFlowState.Plan}">
|
||||
<Setter Property="Background" Value="#1565C0"/>
|
||||
<Setter Property="BorderBrush" Value="#0D47A1"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Resources>
|
||||
<TextBlock Text="{DynamicResource Test.Wizard.Plan}" FontSize="12">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#455A64"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CurrentState}"
|
||||
Value="{x:Static models:TestFlowState.Plan}">
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<Border Style="{StaticResource StepPillStyle}">
|
||||
<Border.Resources>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource StepPillStyle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CurrentState}"
|
||||
Value="{x:Static models:TestFlowState.Preconditions}">
|
||||
<Setter Property="Background" Value="#1565C0"/>
|
||||
<Setter Property="BorderBrush" Value="#0D47A1"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Resources>
|
||||
<TextBlock Text="{DynamicResource Test.Wizard.Preconditions}" FontSize="12">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#455A64"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CurrentState}"
|
||||
Value="{x:Static models:TestFlowState.Preconditions}">
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<Border Style="{StaticResource StepPillStyle}">
|
||||
<Border.Resources>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource StepPillStyle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CurrentState}"
|
||||
Value="{x:Static models:TestFlowState.Running}">
|
||||
<Setter Property="Background" Value="#1565C0"/>
|
||||
<Setter Property="BorderBrush" Value="#0D47A1"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Resources>
|
||||
<TextBlock Text="{DynamicResource Test.Wizard.Running}" FontSize="12">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#455A64"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CurrentState}"
|
||||
Value="{x:Static models:TestFlowState.Running}">
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<Border Style="{StaticResource StepPillStyle}">
|
||||
<Border.Resources>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource StepPillStyle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CurrentState}"
|
||||
Value="{x:Static models:TestFlowState.Done}">
|
||||
<Setter Property="Background" Value="#1565C0"/>
|
||||
<Setter Property="BorderBrush" Value="#0D47A1"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Resources>
|
||||
<TextBlock Text="{DynamicResource Test.Wizard.Done}" FontSize="12">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#455A64"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CurrentState}"
|
||||
Value="{x:Static models:TestFlowState.Done}">
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</ItemsControl>
|
||||
</Border>
|
||||
|
||||
<!-- Current step body -->
|
||||
<ContentControl Grid.Row="1" Content="{Binding CurrentStateVm}"/>
|
||||
|
||||
<!-- Wizard footer: Back / Next -->
|
||||
<Border Grid.Row="2" Padding="10,8"
|
||||
Background="White" BorderBrush="#DDD" BorderThickness="0,1,0,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Column="0"
|
||||
Content="{DynamicResource Test.Wizard.Back}"
|
||||
Command="{Binding BackCommand}"
|
||||
Padding="16,6" FontSize="12"/>
|
||||
|
||||
<Button Grid.Column="2"
|
||||
Content="{DynamicResource Test.Wizard.Next}"
|
||||
Command="{Binding NextCommand}"
|
||||
Padding="16,6" FontSize="12"
|
||||
FontWeight="SemiBold"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
16
Views/Pages/TestsPage.xaml.cs
Normal file
16
Views/Pages/TestsPage.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests navigation page. DataContext is expected to be a
|
||||
/// <see cref="HC_APTBS.ViewModels.Pages.TestsPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class TestsPage : UserControl
|
||||
{
|
||||
public TestsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
85
Views/UserControls/AuthGateView.xaml
Normal file
85
Views/UserControls/AuthGateView.xaml
Normal file
@@ -0,0 +1,85 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.AuthGateView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="240" d:DesignWidth="500">
|
||||
<!--
|
||||
Wraps any child content behind an operator-authentication gate.
|
||||
DataContext = AuthGateViewModel. Set GatedContent via the attached-like
|
||||
property below to supply the content to show when authenticated.
|
||||
|
||||
Usage (in a parent view):
|
||||
<uc:AuthGateView DataContext="{Binding AdaptationAuth}">
|
||||
<uc:AuthGateView.GatedContent>
|
||||
<uc:DfiManageView DataContext="{Binding DfiViewModel}"/>
|
||||
</uc:AuthGateView.GatedContent>
|
||||
</uc:AuthGateView>
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<!-- ── Locked state: authenticate prompt ─────────────────────── -->
|
||||
<Border Background="#F5F5F5" BorderBrush="#CCC" BorderThickness="1"
|
||||
CornerRadius="4" Padding="20" Margin="6">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAuthenticated}" Value="True">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock Text="🔒"
|
||||
HorizontalAlignment="Center" FontSize="40" Margin="0,0,0,8"/>
|
||||
<TextBlock Text="{DynamicResource AuthGate.LockedTitle}"
|
||||
FontSize="14" FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,4"/>
|
||||
<TextBlock Text="{DynamicResource AuthGate.LockedMessage}"
|
||||
FontSize="12" Foreground="#666"
|
||||
HorizontalAlignment="Center" TextWrapping="Wrap"
|
||||
MaxWidth="360" TextAlignment="Center" Margin="0,0,0,14"/>
|
||||
<Button Content="{DynamicResource AuthGate.Authenticate}"
|
||||
Command="{Binding AuthenticateCommand}"
|
||||
HorizontalAlignment="Center"
|
||||
MinWidth="160" Height="34" FontWeight="Bold"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ── Unlocked state: child content + re-lock button ─────────── -->
|
||||
<Grid Visibility="{Binding IsAuthenticated, Converter={StaticResource BoolToVis}}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Grid.Row="0" Background="#E8F5E9" BorderBrush="#66BB6A"
|
||||
BorderThickness="0,0,0,1" Padding="10,4" Margin="6,6,6,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock FontSize="12" Foreground="#2E7D32" VerticalAlignment="Center">
|
||||
<Run Text="{DynamicResource AuthGate.UnlockedAs}"/>
|
||||
<Run Text="{Binding AuthenticatedUser, Mode=OneWay}" FontWeight="Bold"/>
|
||||
</TextBlock>
|
||||
<Button Grid.Column="1"
|
||||
Content="{DynamicResource AuthGate.Lock}"
|
||||
Command="{Binding LockCommand}"
|
||||
Height="22" MinWidth="70" FontSize="11"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<ContentPresenter Grid.Row="1"
|
||||
Content="{Binding GatedContent, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
31
Views/UserControls/AuthGateView.xaml.cs
Normal file
31
Views/UserControls/AuthGateView.xaml.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// A gated container that shows <see cref="GatedContent"/> only after the operator
|
||||
/// authenticates via <c>AuthGateViewModel</c>. DataContext is
|
||||
/// <c>AuthGateViewModel</c>.
|
||||
/// </summary>
|
||||
public partial class AuthGateView : UserControl
|
||||
{
|
||||
/// <summary>The content to show once the gate unlocks.</summary>
|
||||
public static readonly DependencyProperty GatedContentProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(GatedContent), typeof(object), typeof(AuthGateView),
|
||||
new PropertyMetadata(null));
|
||||
|
||||
/// <summary>Gets or sets the content displayed when the gate is unlocked.</summary>
|
||||
public object? GatedContent
|
||||
{
|
||||
get => GetValue(GatedContentProperty);
|
||||
set => SetValue(GatedContentProperty, value);
|
||||
}
|
||||
|
||||
public AuthGateView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Views/UserControls/BenchDriveControlView.xaml
Normal file
109
Views/UserControls/BenchDriveControlView.xaml
Normal file
@@ -0,0 +1,109 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.BenchDriveControlView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="420" d:DesignWidth="180">
|
||||
<!--
|
||||
Manual drive control panel: direction, RPM start/stop with quick-select,
|
||||
oil pump, and turn counter.
|
||||
DataContext = BenchPageViewModel; operates on BenchControl.X.
|
||||
-->
|
||||
<StackPanel Width="170">
|
||||
|
||||
<!-- 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}"/>
|
||||
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
17
Views/UserControls/BenchDriveControlView.xaml.cs
Normal file
17
Views/UserControls/BenchDriveControlView.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Manual drive control panel for the Bench page: direction toggle,
|
||||
/// RPM start/stop with quick-select popup, oil pump, and turn counter.
|
||||
/// </summary>
|
||||
public partial class BenchDriveControlView : UserControl
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="BenchDriveControlView"/> control.</summary>
|
||||
public BenchDriveControlView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
140
Views/UserControls/BenchReadingsView.xaml
Normal file
140
Views/UserControls/BenchReadingsView.xaml
Normal file
@@ -0,0 +1,140 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.BenchReadingsView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300" d:DesignWidth="380">
|
||||
<!--
|
||||
HMI-style bench readings panel used on the Bench page.
|
||||
Larger than the Dashboard variant; includes QDelivery + QOver and
|
||||
shows the live voltage/target RPM summary.
|
||||
DataContext = BenchPageViewModel. Reads via Root.X / BenchControl.X.
|
||||
-->
|
||||
<StackPanel>
|
||||
|
||||
<!-- RPM — oversized, with target + voltage summary -->
|
||||
<Border Style="{StaticResource LcdBlue}" Margin="0,0,0,4" Padding="10,6">
|
||||
<StackPanel>
|
||||
<Grid Height="86">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{Binding Root.BenchRpm, StringFormat=F0}"
|
||||
FontSize="72" FontWeight="UltraBold" Foreground="#EBEBFF"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
FontFamily="Consolas"/>
|
||||
<TextBlock Grid.Column="1" Text="{DynamicResource Bench.Rpm}"
|
||||
FontSize="20" Foreground="#FFFFEB6E"
|
||||
VerticalAlignment="Center" Margin="6,0,0,0"/>
|
||||
</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>
|
||||
|
||||
<!-- Pressures + temperatures side by side -->
|
||||
<Grid Margin="0,0,0,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border Grid.Column="0" Style="{StaticResource LcdBlue}" Margin="0,0,2,0" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="60"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="30"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="{DynamicResource Bench.P1}" Grid.Row="0" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.P2}" Grid.Row="1" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{Binding Root.Pressure, StringFormat=F1}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="22" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.Pressure2, StringFormat=F1}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="22" FontFamily="Consolas"/>
|
||||
<TextBlock Text="bar" Grid.Row="0" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
|
||||
<TextBlock Text="bar" Grid.Row="1" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Column="1" Style="{StaticResource LcdBlue}" Margin="2,0,0,0" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="60"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="30"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<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="{Binding Root.TempIn, StringFormat=F1}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="18" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.TempOut, StringFormat=F1}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="18" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.Temp4, StringFormat=F1}" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="18" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.BenchTemp, StringFormat=F1}" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="18" 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"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Flow: QDelivery + QOver -->
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border Grid.Column="0" Style="{StaticResource LcdBlue}" Margin="0,0,2,0" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="70"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="56"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Bench.QDelivery}" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{Binding Root.QDelivery, StringFormat=F1}"
|
||||
Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Foreground="#EBEBFF" FontSize="22" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{DynamicResource Bench.CcStroke}" Grid.Column="2"
|
||||
Foreground="#EBEBFF" FontSize="11" VerticalAlignment="Center" Margin="4,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Column="1" Style="{StaticResource LcdBlue}" Margin="2,0,0,0" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="70"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="56"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Bench.QOver}" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{Binding Root.QOver, StringFormat=F1}"
|
||||
Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Foreground="#EBEBFF" FontSize="22" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{DynamicResource Bench.CcStroke}" Grid.Column="2"
|
||||
Foreground="#EBEBFF" FontSize="11" VerticalAlignment="Center" Margin="4,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
18
Views/UserControls/BenchReadingsView.xaml.cs
Normal file
18
Views/UserControls/BenchReadingsView.xaml.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// HMI-style bench readings panel (RPM, pressures, temperatures, Q flows)
|
||||
/// rendered on the Bench page. Shares the <c>LcdBlue</c> style with the
|
||||
/// dashboard equivalent but is wider and includes QDelivery + QOver.
|
||||
/// </summary>
|
||||
public partial class BenchReadingsView : UserControl
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="BenchReadingsView"/> control.</summary>
|
||||
public BenchReadingsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
158
Views/UserControls/DashboardConnectionView.xaml
Normal file
158
Views/UserControls/DashboardConnectionView.xaml
Normal file
@@ -0,0 +1,158 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.DashboardConnectionView"
|
||||
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:models="clr-namespace:HC_APTBS.Models"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="160" d:DesignWidth="220">
|
||||
<!--
|
||||
Connection status block for the Dashboard.
|
||||
DataContext is DashboardPageViewModel; pills read from Root.X.
|
||||
Pill uses the shared ConnIndicator style. Gray = offline, green = live, red = K-Line failed.
|
||||
-->
|
||||
<StackPanel>
|
||||
<TextBlock Text="{DynamicResource Dashboard.Connections}"
|
||||
FontSize="13" FontWeight="SemiBold" Foreground="#333"
|
||||
Margin="0,0,0,6"/>
|
||||
|
||||
<!-- CAN bus -->
|
||||
<Grid Margin="0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="80"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Dashboard.Conn.Can}" VerticalAlignment="Center" FontSize="12"/>
|
||||
<Border Grid.Column="1" MinWidth="72" Height="22">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource ConnIndicator}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.IsCanConnected}" Value="True">
|
||||
<Setter Property="Background" Value="#26C200"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
FontSize="10" FontWeight="SemiBold" Foreground="White"
|
||||
Text="{DynamicResource Dashboard.StateOnline}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateOffline}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.IsCanConnected}" Value="True">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateOnline}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Bench liveness -->
|
||||
<Grid Margin="0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="80"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Dashboard.Conn.Bench}" VerticalAlignment="Center" FontSize="12"/>
|
||||
<Border Grid.Column="1" MinWidth="72" Height="22">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource ConnIndicator}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.IsBenchConnected}" Value="True">
|
||||
<Setter Property="Background" Value="#26C200"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
FontSize="10" FontWeight="SemiBold" Foreground="White">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateOffline}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.IsBenchConnected}" Value="True">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateOnline}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Pump liveness -->
|
||||
<Grid Margin="0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="80"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Dashboard.Conn.Pump}" VerticalAlignment="Center" FontSize="12"/>
|
||||
<Border Grid.Column="1" MinWidth="72" Height="22">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource ConnIndicator}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.IsPumpConnected}" Value="True">
|
||||
<Setter Property="Background" Value="#26C200"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
FontSize="10" FontWeight="SemiBold" Foreground="White">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateOffline}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.IsPumpConnected}" Value="True">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateOnline}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- K-Line session -->
|
||||
<Grid Margin="0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="80"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Dashboard.Conn.KLine}" VerticalAlignment="Center" FontSize="12"/>
|
||||
<Border Grid.Column="1" MinWidth="72" Height="22">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border" BasedOn="{StaticResource ConnIndicator}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.KLineState}" Value="{x:Static models:KLineConnectionState.Connected}">
|
||||
<Setter Property="Background" Value="#26C200"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Root.KLineState}" Value="{x:Static models:KLineConnectionState.Failed}">
|
||||
<Setter Property="Background" Value="#FF3333"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
FontSize="10" FontWeight="SemiBold" Foreground="White">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateClosed}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Root.KLineState}" Value="{x:Static models:KLineConnectionState.Connected}">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateOpen}"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Root.KLineState}" Value="{x:Static models:KLineConnectionState.Failed}">
|
||||
<Setter Property="Text" Value="{DynamicResource Dashboard.StateFailed}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
16
Views/UserControls/DashboardConnectionView.xaml.cs
Normal file
16
Views/UserControls/DashboardConnectionView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Connection/liveness status pills for the Dashboard page.
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.Pages.DashboardPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class DashboardConnectionView : UserControl
|
||||
{
|
||||
public DashboardConnectionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
103
Views/UserControls/DashboardReadingsView.xaml
Normal file
103
Views/UserControls/DashboardReadingsView.xaml
Normal file
@@ -0,0 +1,103 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.DashboardReadingsView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300" d:DesignWidth="320">
|
||||
<!--
|
||||
Dashboard-only compact LCD panel.
|
||||
DataContext is DashboardPageViewModel; binds via Root.X to MainViewModel live readings.
|
||||
Read-first: no controls, no popups.
|
||||
-->
|
||||
<StackPanel>
|
||||
|
||||
<!-- RPM: oversized single-line read -->
|
||||
<Border Style="{StaticResource LcdBlue}" Margin="0,0,0,4" Padding="10,6">
|
||||
<Grid Height="76">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{Binding Root.BenchRpm, StringFormat=F0}"
|
||||
FontSize="60" FontWeight="UltraBold" Foreground="#EBEBFF"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
FontFamily="Consolas"/>
|
||||
<TextBlock Grid.Column="1" Text="{DynamicResource Bench.Rpm}"
|
||||
FontSize="18" Foreground="#FFFFEB6E"
|
||||
VerticalAlignment="Center" Margin="6,0,0,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Temperatures + Pressures side by side -->
|
||||
<Grid Margin="0,0,0,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Pressures -->
|
||||
<Border Grid.Column="0" Style="{StaticResource LcdBlue}" Margin="0,0,2,0" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="60"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="30"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="{DynamicResource Bench.P1}" Grid.Row="0" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.P2}" Grid.Row="1" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{Binding Root.Pressure, StringFormat=F1}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.Pressure2, StringFormat=F1}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
|
||||
<TextBlock Text="bar" Grid.Row="0" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
|
||||
<TextBlock Text="bar" Grid.Row="1" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Temperatures -->
|
||||
<Border Grid.Column="1" Style="{StaticResource LcdBlue}" Margin="2,0,0,0" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="60"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="30"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<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.TempTank}" Grid.Row="2" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{Binding Root.TempIn, StringFormat=F1}" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.TempOut, StringFormat=F1}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Foreground="#EBEBFF" FontSize="20" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.BenchTemp, StringFormat=F1}" Grid.Row="2" 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"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Flow: Q-Delivery -->
|
||||
<Border Style="{StaticResource LcdBlue}" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="90"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="46"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource Bench.QDelivery}" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{Binding Root.QDelivery, StringFormat=F1}"
|
||||
Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Foreground="#EBEBFF" FontSize="22" FontFamily="Consolas"/>
|
||||
<TextBlock Text="cc/s" Grid.Column="2" Foreground="#EBEBFF" FontSize="13" VerticalAlignment="Center" Margin="4,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
16
Views/UserControls/DashboardReadingsView.xaml.cs
Normal file
16
Views/UserControls/DashboardReadingsView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Compact read-only LCD panel for the Dashboard page.
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.Pages.DashboardPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class DashboardReadingsView : UserControl
|
||||
{
|
||||
public DashboardReadingsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
94
Views/UserControls/DtcListView.xaml
Normal file
94
Views/UserControls/DtcListView.xaml
Normal file
@@ -0,0 +1,94 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.DtcListView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="360" d:DesignWidth="700">
|
||||
<!--
|
||||
Pump page §3.b DTC list. DataContext = DtcListViewModel.
|
||||
Moves the fault-code surface out of the one-shot KlineErrorsDialog
|
||||
into a proper sub-section with read / clear actions and a row list.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border Background="#FAFAFA" BorderBrush="#DDD" BorderThickness="1"
|
||||
CornerRadius="4" Padding="12" Margin="6">
|
||||
<DockPanel>
|
||||
|
||||
<!-- ── Header row: title + actions ─────────────────────────── -->
|
||||
<Grid DockPanel.Dock="Top" Margin="0,0,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource PumpSub.Dtcs}"
|
||||
FontSize="15" FontWeight="SemiBold" Foreground="#333"
|
||||
VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<Button Content="{DynamicResource Dtc.Read}"
|
||||
Command="{Binding ReadCommand}"
|
||||
MinWidth="90" Height="28" Margin="0,0,6,0"
|
||||
FontWeight="Bold"/>
|
||||
<Button Content="{DynamicResource Dtc.Clear}"
|
||||
Command="{Binding ClearCommand}"
|
||||
MinWidth="90" Height="28"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- ── Status line ─────────────────────────────────────────── -->
|
||||
<TextBlock DockPanel.Dock="Top"
|
||||
Text="{Binding StatusText}"
|
||||
Foreground="#666" FontSize="11" Margin="0,0,0,6"/>
|
||||
|
||||
<!-- ── Busy indicator ──────────────────────────────────────── -->
|
||||
<ProgressBar DockPanel.Dock="Top"
|
||||
IsIndeterminate="True" Height="3" Margin="0,0,0,6"
|
||||
Visibility="{Binding IsBusy, Converter={StaticResource BoolToVis}}"/>
|
||||
|
||||
<!-- ── "No faults" banner ──────────────────────────────────── -->
|
||||
<Border DockPanel.Dock="Top"
|
||||
Background="#26C200" CornerRadius="3" Padding="10,6"
|
||||
HorizontalAlignment="Left"
|
||||
Visibility="{Binding IsClear, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock Text="{DynamicResource Dtc.NoFaults}"
|
||||
Foreground="White" FontWeight="Bold" FontSize="12"/>
|
||||
</Border>
|
||||
|
||||
<!-- ── DTC rows ────────────────────────────────────────────── -->
|
||||
<ListBox ItemsSource="{Binding Codes}"
|
||||
BorderThickness="0" Background="Transparent">
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="ListBoxItem">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="#FDECEA" BorderBrush="#D62828"
|
||||
BorderThickness="0,0,0,1" Padding="8,6" Margin="0,2">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="110"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{Binding Code}"
|
||||
FontFamily="Consolas" FontWeight="Bold"
|
||||
FontSize="13" Foreground="#B22222"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding Description}"
|
||||
FontSize="12" Foreground="#333"
|
||||
TextWrapping="Wrap"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</UserControl>
|
||||
16
Views/UserControls/DtcListView.xaml.cs
Normal file
16
Views/UserControls/DtcListView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Pump page §3.b DTC list view. DataContext is
|
||||
/// <c>DtcListViewModel</c>.
|
||||
/// </summary>
|
||||
public partial class DtcListView : UserControl
|
||||
{
|
||||
public DtcListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.FlowmeterChartView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF">
|
||||
xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.WPF;assembly=LiveChartsCore.SkiaSharpView.WPF"
|
||||
>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -23,6 +24,7 @@
|
||||
YAxes="{Binding YAxes}"
|
||||
Sections="{Binding Sections}"
|
||||
TooltipPosition="Hidden"
|
||||
AnimationsSpeed="00:00:00"/>
|
||||
AnimationsSpeed="00:00:00"
|
||||
/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
90
Views/UserControls/GraphicIndicatorView.xaml
Normal file
90
Views/UserControls/GraphicIndicatorView.xaml
Normal file
@@ -0,0 +1,90 @@
|
||||
<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:vm="clr-namespace:HC_APTBS.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance Type=vm:GraphicIndicatorViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Vertical progress bar showing a single measurement value against its
|
||||
expected value and tolerance band. Shared across phase cards and the
|
||||
Running view's live measurement table.
|
||||
-->
|
||||
<Grid Width="58" Margin="2,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- Max label -->
|
||||
<RowDefinition Height="90"/> <!-- Progress bar -->
|
||||
<RowDefinition Height="Auto"/> <!-- Min label -->
|
||||
<RowDefinition Height="Auto"/> <!-- Param name -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Text="{Binding MaxBound, StringFormat=F1}"
|
||||
FontSize="9" Foreground="Gray"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,1"/>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Border BorderBrush="Black" BorderThickness="1" SnapsToDevicePixels="True"/>
|
||||
|
||||
<ProgressBar Orientation="Vertical"
|
||||
Minimum="0" Maximum="100"
|
||||
Value="{Binding ProgressPercent, Mode=OneWay}"
|
||||
BorderThickness="0"
|
||||
Background="White"
|
||||
Margin="1">
|
||||
<ProgressBar.Style>
|
||||
<Style TargetType="ProgressBar">
|
||||
<Setter Property="Foreground" Value="#4CAF50"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsWithinTolerance}" Value="False">
|
||||
<Setter Property="Foreground" Value="#FF5722"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ProgressBar.Style>
|
||||
</ProgressBar>
|
||||
|
||||
<Canvas ClipToBounds="True">
|
||||
<Line X1="0" X2="58" StrokeDashArray="3,2"
|
||||
Stroke="LightGray" StrokeThickness="1"
|
||||
Canvas.Top="18"/>
|
||||
<Line X1="0" X2="58" StrokeDashArray="3,2"
|
||||
Stroke="LightGray" StrokeThickness="1"
|
||||
Canvas.Top="72"/>
|
||||
</Canvas>
|
||||
|
||||
<TextBlock Text="{Binding ExpectedValue, StringFormat=F1}"
|
||||
FontSize="9" Foreground="#999999"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Margin="0,-14,0,0"/>
|
||||
|
||||
<TextBlock Text="{Binding DisplayValue}"
|
||||
FontSize="14" FontWeight="Black"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Margin="0,10,0,0">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasValue}" Value="False">
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="2"
|
||||
Text="{Binding MinBound, StringFormat=F1}"
|
||||
FontSize="9" Foreground="Gray"
|
||||
HorizontalAlignment="Center" Margin="0,1,0,0"/>
|
||||
|
||||
<TextBlock Grid.Row="3"
|
||||
Text="{Binding ParameterName}"
|
||||
FontSize="9" FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
ToolTip="{Binding ParameterName}"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
16
Views/UserControls/GraphicIndicatorView.xaml.cs
Normal file
16
Views/UserControls/GraphicIndicatorView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Vertical progress bar indicator for a single measurement value with tolerance band.
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.GraphicIndicatorViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class GraphicIndicatorView : UserControl
|
||||
{
|
||||
public GraphicIndicatorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
47
Views/UserControls/InterlockBannerView.xaml
Normal file
47
Views/UserControls/InterlockBannerView.xaml
Normal file
@@ -0,0 +1,47 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.InterlockBannerView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="40" d:DesignWidth="800">
|
||||
<!--
|
||||
Soft safety interlock banner. Visible only when
|
||||
InterlockBannerViewModel.IsVisible is true.
|
||||
Colour switches from warning amber to critical red.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border CornerRadius="3" Padding="10,6" Margin="0,4"
|
||||
Visibility="{Binding IsVisible, Converter={StaticResource BoolToVis}}">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#FFB020"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsCritical}" Value="True">
|
||||
<Setter Property="Background" Value="#D62828"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="⚠" Foreground="White" FontSize="16"
|
||||
FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,8,0"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Message}"
|
||||
Foreground="White" FontWeight="SemiBold" FontSize="12"
|
||||
VerticalAlignment="Center" TextWrapping="Wrap"/>
|
||||
<Button Grid.Column="2" Content="{DynamicResource Common.Close}"
|
||||
Command="{Binding DismissCommand}"
|
||||
Foreground="White" Background="Transparent" BorderBrush="White"
|
||||
BorderThickness="1" Padding="8,2" FontSize="11"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
18
Views/UserControls/InterlockBannerView.xaml.cs
Normal file
18
Views/UserControls/InterlockBannerView.xaml.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Soft safety interlock banner rendered on the Bench page.
|
||||
/// Shows when oil-pump interlock or RPM-over-limit conditions are active;
|
||||
/// the operator can dismiss it until the condition changes.
|
||||
/// </summary>
|
||||
public partial class InterlockBannerView : UserControl
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="InterlockBannerView"/> control.</summary>
|
||||
public InterlockBannerView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
126
Views/UserControls/PhaseCardView.xaml
Normal file
126
Views/UserControls/PhaseCardView.xaml
Normal file
@@ -0,0 +1,126 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.PhaseCardView"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
xmlns:vm="clr-namespace:HC_APTBS.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance Type=vm:PhaseCardViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Single phase card. DataContext: PhaseCardViewModel.
|
||||
Shared between TestPlanView (shows ReadyValues/OperationValues and enable toggle)
|
||||
and TestRunningView (shows live ResultIndicators and pass/fail colour).
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<!-- Simple Name: Value pair used by ReadyValues and OperationValues -->
|
||||
<DataTemplate DataType="{x:Type vm:OperationValueViewModel}">
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,6,0">
|
||||
<TextBlock Text="{Binding Name}" FontSize="10" Foreground="Black"
|
||||
Padding="0,0,2,0"/>
|
||||
<TextBlock Text=":" FontSize="10" Foreground="Black"/>
|
||||
<TextBlock Text="{Binding Value, StringFormat=F1}" FontSize="10"
|
||||
Foreground="DimGray" Padding="2,0,0,0"
|
||||
HorizontalAlignment="Right"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Vertical progress bar indicator (wraps GraphicIndicatorView) -->
|
||||
<DataTemplate DataType="{x:Type vm:GraphicIndicatorViewModel}">
|
||||
<uc:GraphicIndicatorView/>
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border MinWidth="100" Margin="2,0" Padding="4"
|
||||
CornerRadius="2" SnapsToDevicePixels="True">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#F0F0F0"/>
|
||||
<Setter Property="BorderBrush" Value="#CCCCCC"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsActive}" Value="True">
|
||||
<Setter Property="Background" Value="#FFE082"/>
|
||||
<Setter Property="BorderBrush" Value="#F9A825"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsPassed}" Value="True">
|
||||
<Setter Property="Background" Value="#C8E6C9"/>
|
||||
<Setter Property="BorderBrush" Value="#388E3C"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsFailed}" Value="True">
|
||||
<Setter Property="Background" Value="#FFCDD2"/>
|
||||
<Setter Property="BorderBrush" Value="#C62828"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
|
||||
<Setter Property="Background" Value="#E0E0E0"/>
|
||||
<Setter Property="BorderBrush" Value="#BDBDBD"/>
|
||||
<Setter Property="Opacity" Value="0.5"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
|
||||
<Grid>
|
||||
<!-- Enable/disable toggle -->
|
||||
<CheckBox IsChecked="{Binding IsEnabled}"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||
Margin="0,0,0,0" ToolTip="Enable/disable this phase"/>
|
||||
|
||||
<StackPanel Margin="0,2,0,0">
|
||||
<TextBlock Text="{Binding Name}"
|
||||
FontSize="11" FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
Margin="16,0,0,0"/>
|
||||
|
||||
<TextBlock Text="{DynamicResource Test.Critical}" FontSize="9"
|
||||
Foreground="#E65100" FontWeight="Bold"
|
||||
HorizontalAlignment="Center"
|
||||
Visibility="{Binding IsCritical, Converter={StaticResource BoolToVis}}"/>
|
||||
|
||||
<StackPanel Visibility="{Binding ShowOperationValues, Converter={StaticResource BoolToVis}}"
|
||||
Margin="0,3,0,0">
|
||||
<StackPanel Visibility="{Binding ReadyValues.Count, FallbackValue=Collapsed}">
|
||||
<TextBlock Text="{DynamicResource Test.Required}" FontSize="9" Foreground="#666"
|
||||
FontWeight="SemiBold" Margin="0,1,0,0"/>
|
||||
<ItemsControl ItemsSource="{Binding ReadyValues}"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="{DynamicResource Test.TestLabel}" FontSize="9" Foreground="#666"
|
||||
FontWeight="SemiBold" Margin="0,2,0,0"/>
|
||||
<ItemsControl ItemsSource="{Binding OperationValues}"/>
|
||||
</StackPanel>
|
||||
|
||||
<ItemsControl ItemsSource="{Binding ResultIndicators}" Margin="0,4,0,0">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Text="{Binding ResultText}"
|
||||
FontSize="12" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Margin="0,3,0,0">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="DimGray"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsPassed}" Value="True">
|
||||
<Setter Property="Foreground" Value="#2E7D32"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsFailed}" Value="True">
|
||||
<Setter Property="Foreground" Value="#B71C1C"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
16
Views/UserControls/PhaseCardView.xaml.cs
Normal file
16
Views/UserControls/PhaseCardView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Single phase card (critical / operation values / graphic indicators / result).
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.PhaseCardViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class PhaseCardView : UserControl
|
||||
{
|
||||
public PhaseCardView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
165
Views/UserControls/PumpIdentificationPanelView.xaml
Normal file
165
Views/UserControls/PumpIdentificationPanelView.xaml
Normal file
@@ -0,0 +1,165 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.PumpIdentificationPanelView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="360" d:DesignWidth="700">
|
||||
<!--
|
||||
Pump-page variant of PumpIdentificationView (spec §3.a Identification).
|
||||
Reuses PumpIdentificationViewModel. Presents the ECU info panel
|
||||
in a larger, two-column format suitable for the Pump page.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<Style x:Key="IdLabel" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Foreground" Value="#555"/>
|
||||
<Setter Property="Width" Value="110"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="IdValue" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
<Setter Property="FontFamily" Value="Consolas"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border Background="#FAFAFA" BorderBrush="#DDD" BorderThickness="1"
|
||||
CornerRadius="4" Padding="12" Margin="6">
|
||||
<StackPanel>
|
||||
|
||||
<!-- ── Section title ────────────────────────────────────────── -->
|
||||
<TextBlock Text="{DynamicResource PumpSub.Identification}"
|
||||
FontSize="15" FontWeight="SemiBold" Foreground="#333"
|
||||
Margin="0,0,0,8"/>
|
||||
|
||||
<!-- ── Pump selector row ────────────────────────────────────── -->
|
||||
<Grid Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="110"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{DynamicResource PumpId.Label}"
|
||||
VerticalAlignment="Center" FontSize="13"/>
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemsSource="{Binding PumpIds}"
|
||||
SelectedItem="{Binding SelectedPumpId}"
|
||||
FontSize="18" Margin="0,0,12,0"
|
||||
VerticalContentAlignment="Center"/>
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding CurrentPump.Model}"
|
||||
FontSize="13" Foreground="#888"
|
||||
VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
|
||||
<!-- ── Action row: Read + Disconnect + progress ─────────────── -->
|
||||
<Grid Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0"
|
||||
Content="{DynamicResource PumpId.ReadKLine}"
|
||||
Command="{Binding ReadKlineCommand}"
|
||||
MinWidth="130" Height="34" FontWeight="Bold"
|
||||
Margin="0,0,8,0"/>
|
||||
<Button Grid.Column="1"
|
||||
Content="{DynamicResource PumpId.Disconnect}"
|
||||
Command="{Binding DisconnectKLineCommand}"
|
||||
MinWidth="110" Height="34"
|
||||
Margin="0,0,12,0"/>
|
||||
<StackPanel Grid.Column="2"
|
||||
Orientation="Vertical"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{Binding IsReading, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock Text="{Binding ProgressMessage}"
|
||||
FontSize="11" Foreground="#666"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
<ProgressBar Value="{Binding ProgressPercent, Mode=OneWay}"
|
||||
Minimum="0" Maximum="100" Height="8" Margin="0,2,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- ── Two-column ECU info grid ─────────────────────────────── -->
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Left column -->
|
||||
<StackPanel Grid.Column="0">
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.PumpId}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlinePumpId}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.SerialNo}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlineSerialNumber}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.ModelRef}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlineModelRef}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.ModelIndex}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlineModelIndex}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.DataRecord}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlineDataRecord}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Right column -->
|
||||
<StackPanel Grid.Column="2">
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.SwVer1}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlineSwVersion1}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.SwVer2}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlineSwVersion2}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.PumpCtrl}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlinePumpControl}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.Dfi}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlineDfi}" Style="{StaticResource IdValue}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,2">
|
||||
<TextBlock Text="{DynamicResource PumpId.Errors}" Style="{StaticResource IdLabel}"/>
|
||||
<TextBlock Text="{Binding KlineErrors}" Style="{StaticResource IdValue}" Foreground="DarkRed"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- ── Connection error footer (auto-collapses) ─────────────── -->
|
||||
<Border Background="#FDECEA" BorderBrush="#D62828" BorderThickness="1"
|
||||
CornerRadius="3" Padding="8,4" Margin="0,10,0,0">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding KlineConnectError}" Value="">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Text="{Binding KlineConnectError}"
|
||||
FontSize="12" FontFamily="Consolas" Foreground="#B22222"
|
||||
TextWrapping="Wrap"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</UserControl>
|
||||
17
Views/UserControls/PumpIdentificationPanelView.xaml.cs
Normal file
17
Views/UserControls/PumpIdentificationPanelView.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Larger page-scoped variant of <see cref="PumpIdentificationView"/> used by the
|
||||
/// Pump page §3.a Identification sub-section. DataContext is
|
||||
/// <c>PumpIdentificationViewModel</c>.
|
||||
/// </summary>
|
||||
public partial class PumpIdentificationPanelView : UserControl
|
||||
{
|
||||
public PumpIdentificationPanelView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,14 +12,14 @@
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="{DynamicResource PumpId.Label}" VerticalAlignment="Center" Margin="0,0,8,0" FontSize="14"/>
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemsSource="{Binding PumpIds}"
|
||||
SelectedItem="{Binding SelectedPumpId}"
|
||||
FontSize="14" VerticalAlignment="Center"/>
|
||||
FontSize="36" VerticalAlignment="Center"/>
|
||||
<TextBlock Grid.Column="2" Margin="8,0,0,0"
|
||||
Text="{Binding CurrentPump.Model}" FontSize="12"
|
||||
Foreground="Gray" VerticalAlignment="Center"/>
|
||||
|
||||
130
Views/UserControls/PumpLiveDataView.xaml
Normal file
130
Views/UserControls/PumpLiveDataView.xaml
Normal file
@@ -0,0 +1,130 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.PumpLiveDataView"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="380" d:DesignWidth="700">
|
||||
<!--
|
||||
Pump page §3.c Live Data. DataContext = PumpPageViewModel so the view
|
||||
can reach the MainViewModel-owned live readings via {Binding Root.X}
|
||||
and the two StatusDisplay VMs.
|
||||
-->
|
||||
<Border Background="#FAFAFA" BorderBrush="#DDD" BorderThickness="1"
|
||||
CornerRadius="4" Padding="12" Margin="6">
|
||||
<StackPanel>
|
||||
|
||||
<!-- ── Section title ─────────────────────────────────────────── -->
|
||||
<TextBlock Text="{DynamicResource PumpSub.LiveData}"
|
||||
FontSize="15" FontWeight="SemiBold" Foreground="#333"
|
||||
Margin="0,0,0,8"/>
|
||||
|
||||
<!-- ── LCD-style readings block ──────────────────────────────── -->
|
||||
<Border Style="{StaticResource LcdBlue}" Padding="10,6">
|
||||
<Grid Height="110">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="90"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="60"/>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<ColumnDefinition Width="90"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="60"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Left column: T-hyb / RPM / T-ein -->
|
||||
<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 Root.PumpTemp, StringFormat=F2}"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Foreground="#EBEBFF" FontSize="22" FontWeight="Bold" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.PumpRpm, StringFormat=F0}"
|
||||
Grid.Column="1" Grid.Row="1"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Foreground="#EBEBFF" FontSize="22" FontWeight="Bold" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.PumpTein, StringFormat=F0}"
|
||||
Grid.Column="1" Grid.Row="2"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Foreground="#EBEBFF" FontSize="22" 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"/>
|
||||
|
||||
<!-- Right column: ME / FBKW -->
|
||||
<TextBlock Text="{DynamicResource Bench.PumpMe}"
|
||||
Grid.Column="4" VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
<TextBlock Text="{DynamicResource Bench.PumpFbkw}"
|
||||
Grid.Column="4" Grid.Row="1"
|
||||
VerticalAlignment="Center" Foreground="#EBEBFF" FontSize="13"/>
|
||||
|
||||
<TextBlock Text="{Binding Root.PumpMe, StringFormat=F2}"
|
||||
Grid.Column="5"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Foreground="#EBEBFF" FontSize="22" FontWeight="Bold" FontFamily="Consolas"/>
|
||||
<TextBlock Text="{Binding Root.PumpFbkw, StringFormat=F2}"
|
||||
Grid.Column="5" Grid.Row="1"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Foreground="#EBEBFF" FontSize="22" FontWeight="Bold" FontFamily="Consolas"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ── Status displays (Status word + Empf3) ─────────────────── -->
|
||||
<StackPanel Margin="0,8,0,0">
|
||||
<uc:StatusDisplayView DataContext="{Binding StatusDisplay1}"/>
|
||||
<uc:StatusDisplayView DataContext="{Binding StatusDisplay2}" Margin="0,4,0,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- ── Engineering expander (raw values) ─────────────────────── -->
|
||||
<Expander Header="{DynamicResource PumpLive.Engineering}"
|
||||
IsExpanded="False" Margin="0,10,0,0" FontSize="12">
|
||||
<Border Background="#1E1E1E" Padding="10,6" CornerRadius="2">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Foreground="#9CDCFE" FontFamily="Consolas" FontSize="11">
|
||||
<Run Text="PumpRpm = "/><Run Text="{Binding Root.PumpRpm, StringFormat=F2, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="#9CDCFE" FontFamily="Consolas" FontSize="11">
|
||||
<Run Text="PumpTemp = "/><Run Text="{Binding Root.PumpTemp, StringFormat=F2, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="#9CDCFE" FontFamily="Consolas" FontSize="11">
|
||||
<Run Text="PumpMe = "/><Run Text="{Binding Root.PumpMe, StringFormat=F3, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1">
|
||||
<TextBlock Foreground="#9CDCFE" FontFamily="Consolas" FontSize="11">
|
||||
<Run Text="PumpFbkw = "/><Run Text="{Binding Root.PumpFbkw, StringFormat=F3, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="#9CDCFE" FontFamily="Consolas" FontSize="11">
|
||||
<Run Text="PumpTein = "/><Run Text="{Binding Root.PumpTein, StringFormat=F0, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="#9CDCFE" FontFamily="Consolas" FontSize="11">
|
||||
<Run Text="KLineState = "/><Run Text="{Binding Root.KLineState, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Expander>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</UserControl>
|
||||
17
Views/UserControls/PumpLiveDataView.xaml.cs
Normal file
17
Views/UserControls/PumpLiveDataView.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Pump page §3.c Live Data view: pump CAN readings, status-word displays,
|
||||
/// and a collapsible engineering panel. DataContext is
|
||||
/// <c>PumpPageViewModel</c> (reaches MainViewModel via <c>Root</c>).
|
||||
/// </summary>
|
||||
public partial class PumpLiveDataView : UserControl
|
||||
{
|
||||
public PumpLiveDataView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
49
Views/UserControls/RelayBankView.xaml
Normal file
49
Views/UserControls/RelayBankView.xaml
Normal file
@@ -0,0 +1,49 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.RelayBankView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="220" d:DesignWidth="180">
|
||||
<!--
|
||||
Curated bank of auxiliary relay toggles.
|
||||
DataContext = RelayBankViewModel.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="RelayToggle" TargetType="ToggleButton">
|
||||
<Setter Property="Height" Value="28"/>
|
||||
<Setter Property="FontSize" Value="11"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Margin" Value="0,2,0,0"/>
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.RelayOff}"/>
|
||||
<Setter Property="Background" Value="LightGray"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.RelayOn}"/>
|
||||
<Setter Property="Background" Value="#26C200"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border Background="#FAFAFA" BorderBrush="#DDD" BorderThickness="1" CornerRadius="4" Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{DynamicResource Bench.Relays}"
|
||||
FontSize="13" FontWeight="SemiBold" Foreground="#333"
|
||||
Margin="0,0,0,6"/>
|
||||
|
||||
<TextBlock Text="{DynamicResource Bench.Electronic}" FontSize="10" Foreground="DimGray"/>
|
||||
<ToggleButton Style="{StaticResource RelayToggle}"
|
||||
IsChecked="{Binding IsElectronicOn}"/>
|
||||
|
||||
<TextBlock Text="{DynamicResource Bench.Flasher}" FontSize="10" Foreground="DimGray" Margin="0,8,0,0"/>
|
||||
<ToggleButton Style="{StaticResource RelayToggle}"
|
||||
IsChecked="{Binding IsFlasherOn}"/>
|
||||
|
||||
<TextBlock Text="{DynamicResource Bench.Pulse4Signal}" FontSize="10" Foreground="DimGray" Margin="0,8,0,0"/>
|
||||
<ToggleButton Style="{StaticResource RelayToggle}"
|
||||
IsChecked="{Binding IsPulse4SignalOn}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</UserControl>
|
||||
17
Views/UserControls/RelayBankView.xaml.cs
Normal file
17
Views/UserControls/RelayBankView.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Curated bank of auxiliary relay toggles rendered on the Bench page.
|
||||
/// Hosts Electronic, Flasher, and Pulse4Signal toggles with state indication.
|
||||
/// </summary>
|
||||
public partial class RelayBankView : UserControl
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="RelayBankView"/> control.</summary>
|
||||
public RelayBankView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
147
Views/UserControls/ResultHistoryView.xaml
Normal file
147
Views/UserControls/ResultHistoryView.xaml
Normal file
@@ -0,0 +1,147 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.ResultHistoryView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="600" d:DesignWidth="320">
|
||||
|
||||
<!--
|
||||
Session-only test-run history list.
|
||||
DataContext: ResultsPageViewModel. Renders one row per CompletedTestRun in History.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<TextBlock Grid.Row="0" Text="{DynamicResource Results.HistoryHeader}"
|
||||
FontSize="13" FontWeight="SemiBold" Foreground="#333"
|
||||
Margin="0,0,0,6"/>
|
||||
|
||||
<!-- Empty-state prompt -->
|
||||
<Border Grid.Row="1"
|
||||
Visibility="{Binding IsHistoryEmpty, Converter={StaticResource BoolToVis}}"
|
||||
VerticalAlignment="Top" Padding="8" Margin="0,0,0,4"
|
||||
Background="#F5F5F5" BorderBrush="#DDD" BorderThickness="1" CornerRadius="3">
|
||||
<TextBlock Text="{DynamicResource Results.EmptyState}"
|
||||
FontSize="12" Foreground="#777" FontStyle="Italic"
|
||||
TextWrapping="Wrap"/>
|
||||
</Border>
|
||||
|
||||
<!-- Entries list -->
|
||||
<ListBox Grid.Row="1"
|
||||
ItemsSource="{Binding History}"
|
||||
SelectedItem="{Binding SelectedRun, Mode=TwoWay}"
|
||||
BorderThickness="0"
|
||||
Background="Transparent"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="ListBoxItem">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Margin" Value="0,0,0,4"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,6" CornerRadius="3" BorderThickness="1" BorderBrush="#DDD"
|
||||
Background="#FAFAFA">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Timestamp -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="{Binding CompletedAt, StringFormat='{}{0:dd/MM HH:mm:ss}'}"
|
||||
FontFamily="Consolas" FontSize="11" Foreground="#555"/>
|
||||
|
||||
<!-- PASS / FAIL / INTERRUPTED pill -->
|
||||
<Border Grid.Row="0" Grid.Column="1" Padding="5,1" CornerRadius="2"
|
||||
Margin="4,0,0,0" VerticalAlignment="Center">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#B71C1C"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding OverallPassed}" Value="True">
|
||||
<Setter Property="Background" Value="#2E7D32"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Interrupted}" Value="True">
|
||||
<Setter Property="Background" Value="#FFB020"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock Foreground="White" FontSize="10" FontWeight="Bold">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="{DynamicResource Common.Fail}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding OverallPassed}" Value="True">
|
||||
<Setter Property="Text" Value="{DynamicResource Common.Pass}"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Interrupted}" Value="True">
|
||||
<Setter Property="Text" Value="{DynamicResource Results.InterruptedLabel}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<!-- Delete (×) button -->
|
||||
<Button Grid.Row="0" Grid.Column="2"
|
||||
Content="✕"
|
||||
Width="20" Height="20" Margin="4,0,0,0" Padding="0"
|
||||
FontSize="11" FontWeight="Bold" Foreground="#999"
|
||||
Background="Transparent" BorderThickness="0"
|
||||
Cursor="Hand"
|
||||
ToolTip="{DynamicResource Results.DeleteTooltip}"
|
||||
Command="{Binding DataContext.RemoveEntryCommand,
|
||||
RelativeSource={RelativeSource AncestorType=ListBox}}"
|
||||
CommandParameter="{Binding Id}"/>
|
||||
|
||||
<!-- Pump identity -->
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3"
|
||||
FontSize="12" FontWeight="SemiBold" Margin="0,2,0,0"
|
||||
TextTrimming="CharacterEllipsis">
|
||||
<Run Text="{Binding PumpModel, Mode=OneWay}"/>
|
||||
<Run Text=" · "/>
|
||||
<Run Text="{Binding PumpSerial, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
|
||||
<!-- Test names -->
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"
|
||||
Text="{Binding TestNames}"
|
||||
FontSize="11" Foreground="#666" Margin="0,2,0,0"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<!-- Clear session -->
|
||||
<Button Grid.Row="2"
|
||||
Content="{DynamicResource Results.ClearSessionButton}"
|
||||
Command="{Binding ClearHistoryCommand}"
|
||||
Margin="0,6,0,0" Padding="6,3" HorizontalAlignment="Right"
|
||||
FontSize="11"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
13
Views/UserControls/ResultHistoryView.xaml.cs
Normal file
13
Views/UserControls/ResultHistoryView.xaml.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Session-only test-run history list for the Results page.
|
||||
/// DataContext must be a <see cref="ViewModels.Pages.ResultsPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class ResultHistoryView : UserControl
|
||||
{
|
||||
public ResultHistoryView() => InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -41,13 +41,13 @@
|
||||
</Grid.RowDefinitions>
|
||||
<Rectangle Fill="{Binding Color, Converter={StaticResource HexToBrush}}"
|
||||
Stroke="#5D5D5D" StrokeThickness="1"
|
||||
Width="12" Height="12"
|
||||
Width="16" Height="10"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
ToolTip="{Binding Description}"
|
||||
ToolTipService.InitialShowDelay="150"
|
||||
ToolTipService.ShowDuration="30000"
|
||||
SnapsToDevicePixels="True"/>
|
||||
<TextBlock Grid.Row="1" FontSize="8"
|
||||
<TextBlock Grid.Row="1" FontSize="12"
|
||||
Text="{Binding Index}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Foreground="DimGray"/>
|
||||
|
||||
103
Views/UserControls/TemperatureControlView.xaml
Normal file
103
Views/UserControls/TemperatureControlView.xaml
Normal file
@@ -0,0 +1,103 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.TemperatureControlView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="230" d:DesignWidth="190">
|
||||
<!--
|
||||
Temperature control panel: PID setpoint + heater / cooler relay toggles.
|
||||
DataContext = TemperatureControlViewModel.
|
||||
-->
|
||||
<Border Background="#FAFAFA" BorderBrush="#DDD" BorderThickness="1" CornerRadius="4" Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{DynamicResource Bench.TempControl}"
|
||||
FontSize="13" FontWeight="SemiBold" Foreground="#333"
|
||||
Margin="0,0,0,6"/>
|
||||
|
||||
<!-- PID setpoint -->
|
||||
<TextBlock Text="{DynamicResource Bench.Setpoint}" FontSize="10" Foreground="DimGray"/>
|
||||
<Grid Margin="0,2,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Text="{Binding SetpointText, UpdateSourceTrigger=PropertyChanged}"
|
||||
FontSize="16" FontFamily="Consolas" Height="26"
|
||||
VerticalContentAlignment="Center"/>
|
||||
<TextBlock Grid.Column="1" Text="°C" VerticalAlignment="Center"
|
||||
Margin="6,0,0,0" Foreground="#555"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="{DynamicResource Bench.Tolerance}" FontSize="10" Foreground="DimGray"/>
|
||||
<Grid Margin="0,2,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Text="{Binding ToleranceText, UpdateSourceTrigger=PropertyChanged}"
|
||||
FontSize="13" FontFamily="Consolas" Height="22"
|
||||
VerticalContentAlignment="Center"/>
|
||||
<TextBlock Grid.Column="1" Text="± °C" VerticalAlignment="Center"
|
||||
Margin="6,0,0,0" Foreground="#555"/>
|
||||
</Grid>
|
||||
|
||||
<Button Content="{DynamicResource Bench.ApplySetpoint}" Height="26" FontSize="11"
|
||||
FontWeight="SemiBold"
|
||||
Command="{Binding ApplySetpointCommand}"/>
|
||||
|
||||
<!-- Heater / Cooler toggles -->
|
||||
<TextBlock Text="{DynamicResource Bench.DepositHeater}" FontSize="10" Foreground="DimGray" Margin="0,10,0,2"/>
|
||||
<ToggleButton IsChecked="{Binding IsHeaterOn}" Height="28" FontSize="11" FontWeight="SemiBold">
|
||||
<ToggleButton.Style>
|
||||
<Style TargetType="ToggleButton">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.RelayOff}"/>
|
||||
<Setter Property="Background" Value="LightGray"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.RelayOn}"/>
|
||||
<Setter Property="Background" Value="#FFB020"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
|
||||
<TextBlock Text="{DynamicResource Bench.DepositCooler}" FontSize="10" Foreground="DimGray" Margin="0,6,0,2"/>
|
||||
<ToggleButton IsChecked="{Binding IsDepositCoolerOn}" Height="28" FontSize="11" FontWeight="SemiBold">
|
||||
<ToggleButton.Style>
|
||||
<Style TargetType="ToggleButton">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.RelayOff}"/>
|
||||
<Setter Property="Background" Value="LightGray"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.RelayOn}"/>
|
||||
<Setter Property="Background" Value="#4080FF"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
|
||||
<TextBlock Text="{DynamicResource Bench.TinCooler}" FontSize="10" Foreground="DimGray" Margin="0,6,0,2"/>
|
||||
<ToggleButton IsChecked="{Binding IsTinCoolerOn}" Height="28" FontSize="11" FontWeight="SemiBold">
|
||||
<ToggleButton.Style>
|
||||
<Style TargetType="ToggleButton">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.RelayOff}"/>
|
||||
<Setter Property="Background" Value="LightGray"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Content" Value="{DynamicResource Bench.RelayOn}"/>
|
||||
<Setter Property="Background" Value="#26C200"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</UserControl>
|
||||
17
Views/UserControls/TemperatureControlView.xaml.cs
Normal file
17
Views/UserControls/TemperatureControlView.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Bench temperature control panel: PID setpoint input and
|
||||
/// heater / deposit cooler / T-in cooler relay toggles.
|
||||
/// </summary>
|
||||
public partial class TemperatureControlView : UserControl
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="TemperatureControlView"/> control.</summary>
|
||||
public TemperatureControlView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Views/UserControls/TestDoneView.xaml
Normal file
91
Views/UserControls/TestDoneView.xaml
Normal file
@@ -0,0 +1,91 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.TestDoneView"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
xmlns:vmp="clr-namespace:HC_APTBS.ViewModels.Pages"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="560" d:DesignWidth="900"
|
||||
Background="#FFEDEDED" Foreground="Black"
|
||||
d:DataContext="{d:DesignInstance Type=vmp:TestsPageViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Done step of the Tests wizard. DataContext: TestsPageViewModel.
|
||||
Shows PASS/FAIL banner, embedded ResultDisplayView, and navigation buttons.
|
||||
-->
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Overall pass/fail banner -->
|
||||
<Border Padding="16,12" Margin="0,0,0,4">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#FFCDD2"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ResultDisplay.OverallPassed}" Value="True">
|
||||
<Setter Property="Background" Value="#C8E6C9"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock FontSize="26" FontWeight="Bold" VerticalAlignment="Center">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#B71C1C"/>
|
||||
<Setter Property="Text" Value="{DynamicResource Test.Done.Failed}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ResultDisplay.OverallPassed}" Value="True">
|
||||
<Setter Property="Foreground" Value="#2E7D32"/>
|
||||
<Setter Property="Text" Value="{DynamicResource Test.Done.Passed}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding ResultDisplay.TestName}"
|
||||
FontSize="14" FontStyle="Italic"
|
||||
Foreground="#555"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="16,0,0,4"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Inline results table -->
|
||||
<uc:ResultDisplayView Grid.Row="1"
|
||||
DataContext="{Binding ResultDisplay}"
|
||||
Margin="4"/>
|
||||
|
||||
<!-- Action row -->
|
||||
<Border Grid.Row="2" Padding="10,8"
|
||||
BorderBrush="#DDD" BorderThickness="0,1,0,0"
|
||||
Background="White">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Column="0"
|
||||
Content="{DynamicResource Test.Done.ViewFullResults}"
|
||||
Command="{Binding ViewFullResultsCommand}"
|
||||
Padding="14,6" FontSize="12"/>
|
||||
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal">
|
||||
<Button Content="{DynamicResource Test.Report}"
|
||||
Command="{Binding Root.GenerateReportCommand}"
|
||||
Padding="14,6" FontSize="12" Margin="0,0,8,0"/>
|
||||
<Button Content="{DynamicResource Test.Done.RunAgain}"
|
||||
Command="{Binding RunAgainCommand}"
|
||||
Padding="18,6" FontSize="14" FontWeight="Bold"
|
||||
Background="#1565C0" Foreground="White" BorderThickness="0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
16
Views/UserControls/TestDoneView.xaml.cs
Normal file
16
Views/UserControls/TestDoneView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Done step of the Tests wizard — PASS/FAIL banner, results table, Run Again.
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.Pages.TestsPageViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class TestDoneView : UserControl
|
||||
{
|
||||
public TestDoneView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,390 +0,0 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.TestPanelView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:vm="clr-namespace:HC_APTBS.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="600" d:DesignWidth="900"
|
||||
Background="#FFEDEDED" Foreground="Black">
|
||||
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════════
|
||||
GRAPHIC INDICATOR TEMPLATE — vertical progress bar per receive param
|
||||
═══════════════════════════════════════════════════════════════════ -->
|
||||
<DataTemplate DataType="{x:Type vm:GraphicIndicatorViewModel}">
|
||||
<Grid Width="58" Margin="2,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- Max label -->
|
||||
<RowDefinition Height="90"/> <!-- Progress bar -->
|
||||
<RowDefinition Height="Auto"/> <!-- Min label -->
|
||||
<RowDefinition Height="Auto"/> <!-- Param name -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Max bound -->
|
||||
<TextBlock Text="{Binding MaxBound, StringFormat=F1}"
|
||||
FontSize="9" Foreground="Gray"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,1"/>
|
||||
|
||||
<!-- Vertical progress bar area -->
|
||||
<Grid Grid.Row="1">
|
||||
<!-- Border around the bar -->
|
||||
<Border BorderBrush="Black" BorderThickness="1"
|
||||
SnapsToDevicePixels="True"/>
|
||||
|
||||
<!-- The progress bar itself -->
|
||||
<ProgressBar Orientation="Vertical"
|
||||
Minimum="0" Maximum="100"
|
||||
Value="{Binding ProgressPercent, Mode=OneWay}"
|
||||
BorderThickness="0"
|
||||
Background="White"
|
||||
Margin="1">
|
||||
<ProgressBar.Style>
|
||||
<Style TargetType="ProgressBar">
|
||||
<Setter Property="Foreground" Value="#4CAF50"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsWithinTolerance}" Value="False">
|
||||
<Setter Property="Foreground" Value="#FF5722"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ProgressBar.Style>
|
||||
</ProgressBar>
|
||||
|
||||
<!-- Dashed tolerance boundary lines -->
|
||||
<Canvas ClipToBounds="True">
|
||||
<!-- Upper tolerance line at ~80% from bottom (60% band + 20% margin) -->
|
||||
<Line X1="0" X2="58" StrokeDashArray="3,2"
|
||||
Stroke="LightGray" StrokeThickness="1"
|
||||
Canvas.Top="18"/>
|
||||
<!-- Lower tolerance line at ~20% from bottom -->
|
||||
<Line X1="0" X2="58" StrokeDashArray="3,2"
|
||||
Stroke="LightGray" StrokeThickness="1"
|
||||
Canvas.Top="72"/>
|
||||
</Canvas>
|
||||
|
||||
<!-- Expected value label (center) -->
|
||||
<TextBlock Text="{Binding ExpectedValue, StringFormat=F1}"
|
||||
FontSize="9" Foreground="#999999"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Margin="0,-14,0,0"/>
|
||||
|
||||
<!-- Current value label (center, bold) -->
|
||||
<TextBlock Text="{Binding DisplayValue}"
|
||||
FontSize="14" FontWeight="Black"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Margin="0,10,0,0">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasValue}" Value="False">
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
|
||||
<!-- Min bound -->
|
||||
<TextBlock Grid.Row="2"
|
||||
Text="{Binding MinBound, StringFormat=F1}"
|
||||
FontSize="9" Foreground="Gray"
|
||||
HorizontalAlignment="Center" Margin="0,1,0,0"/>
|
||||
|
||||
<!-- Parameter name -->
|
||||
<TextBlock Grid.Row="3"
|
||||
Text="{Binding ParameterName}"
|
||||
FontSize="9" FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
ToolTip="{Binding ParameterName}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════════
|
||||
OPERATION VALUE TEMPLATE — simple name: value pair
|
||||
═══════════════════════════════════════════════════════════════════ -->
|
||||
<DataTemplate DataType="{x:Type vm:OperationValueViewModel}">
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,6,0">
|
||||
<TextBlock Text="{Binding Name}" FontSize="10" Foreground="Black"
|
||||
Padding="0,0,2,0"/>
|
||||
<TextBlock Text=":" FontSize="10" Foreground="Black"/>
|
||||
<TextBlock Text="{Binding Value, StringFormat=F1}" FontSize="10"
|
||||
Foreground="DimGray" Padding="2,0,0,0"
|
||||
HorizontalAlignment="Right"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════════
|
||||
PHASE CARD TEMPLATE
|
||||
═══════════════════════════════════════════════════════════════════ -->
|
||||
<DataTemplate x:Key="PhaseCardTemplate" DataType="{x:Type vm:PhaseCardViewModel}">
|
||||
<Border MinWidth="100" Margin="2,0" Padding="4"
|
||||
CornerRadius="2" SnapsToDevicePixels="True">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#F0F0F0"/>
|
||||
<Setter Property="BorderBrush" Value="#CCCCCC"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsActive}" Value="True">
|
||||
<Setter Property="Background" Value="#FFE082"/>
|
||||
<Setter Property="BorderBrush" Value="#F9A825"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsPassed}" Value="True">
|
||||
<Setter Property="Background" Value="#C8E6C9"/>
|
||||
<Setter Property="BorderBrush" Value="#388E3C"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsFailed}" Value="True">
|
||||
<Setter Property="Background" Value="#FFCDD2"/>
|
||||
<Setter Property="BorderBrush" Value="#C62828"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
|
||||
<Setter Property="Background" Value="#E0E0E0"/>
|
||||
<Setter Property="BorderBrush" Value="#BDBDBD"/>
|
||||
<Setter Property="Opacity" Value="0.5"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
|
||||
<Grid>
|
||||
<!-- Enable/disable toggle as a transparent overlay -->
|
||||
<CheckBox IsChecked="{Binding IsEnabled}"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||
Margin="0,0,0,0" ToolTip="Enable/disable this phase"/>
|
||||
|
||||
<StackPanel Margin="0,2,0,0">
|
||||
<!-- Phase name -->
|
||||
<TextBlock Text="{Binding Name}"
|
||||
FontSize="11" FontWeight="SemiBold"
|
||||
HorizontalAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
Margin="16,0,0,0"/>
|
||||
|
||||
<!-- Critical indicator -->
|
||||
<TextBlock Text="{DynamicResource Test.Critical}" FontSize="9"
|
||||
Foreground="#E65100" FontWeight="Bold"
|
||||
HorizontalAlignment="Center"
|
||||
Visibility="{Binding IsCritical, Converter={StaticResource BoolToVis}}"/>
|
||||
|
||||
<!-- Operation values (show/hide) -->
|
||||
<StackPanel Visibility="{Binding ShowOperationValues, Converter={StaticResource BoolToVis}}"
|
||||
Margin="0,3,0,0">
|
||||
<!-- Ready values -->
|
||||
<StackPanel Visibility="{Binding ReadyValues.Count, FallbackValue=Collapsed}">
|
||||
<TextBlock Text="{DynamicResource Test.Required}" FontSize="9" Foreground="#666"
|
||||
FontWeight="SemiBold" Margin="0,1,0,0"/>
|
||||
<ItemsControl ItemsSource="{Binding ReadyValues}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Send values -->
|
||||
<TextBlock Text="{DynamicResource Test.TestLabel}" FontSize="9" Foreground="#666"
|
||||
FontWeight="SemiBold" Margin="0,2,0,0"/>
|
||||
<ItemsControl ItemsSource="{Binding OperationValues}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Graphic result indicators -->
|
||||
<ItemsControl ItemsSource="{Binding ResultIndicators}" Margin="0,4,0,0">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
|
||||
<!-- Result text -->
|
||||
<TextBlock Text="{Binding ResultText}"
|
||||
FontSize="12" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Margin="0,3,0,0">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="DimGray"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsPassed}" Value="True">
|
||||
<Setter Property="Foreground" Value="#2E7D32"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsFailed}" Value="True">
|
||||
<Setter Property="Foreground" Value="#B71C1C"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════════
|
||||
TEST SECTION TEMPLATE (one per TestDefinition)
|
||||
═══════════════════════════════════════════════════════════════════ -->
|
||||
<DataTemplate x:Key="TestSectionTemplate" DataType="{x:Type vm:TestSectionViewModel}">
|
||||
<Expander IsExpanded="{Binding IsExpanded}" Margin="0,2,0,0">
|
||||
<!-- Custom header -->
|
||||
<Expander.Header>
|
||||
<Border Padding="4,2" CornerRadius="2">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsActiveTest}" Value="True">
|
||||
<Setter Property="Background" Value="#FFFFF3CD"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/> <!-- Name -->
|
||||
<ColumnDefinition Width="Auto"/> <!-- Description -->
|
||||
<ColumnDefinition/> <!-- Timing -->
|
||||
<ColumnDefinition Width="Auto"/> <!-- Check all -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Test name -->
|
||||
<TextBlock Text="{Binding TestName}"
|
||||
FontSize="20" FontFamily="Impact" FontStyle="Italic"
|
||||
VerticalAlignment="Center" Foreground="Black"
|
||||
Padding="4,0"/>
|
||||
|
||||
<!-- Description -->
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding Description}"
|
||||
FontSize="14" FontStyle="Italic" FontFamily="Impact"
|
||||
VerticalAlignment="Bottom" Foreground="Gray"
|
||||
Padding="8,0,0,3"/>
|
||||
|
||||
<!-- Timing info -->
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal"
|
||||
VerticalAlignment="Center" Margin="16,0,0,0">
|
||||
<TextBlock FontSize="10" Foreground="DimGray">
|
||||
<Run Text="{DynamicResource Test.Condition}"/>
|
||||
<Run Text="{Binding ConditioningTimeSec, Mode=OneWay}"/>
|
||||
<Run Text="s"/>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="10" Foreground="DimGray" Margin="10,0,0,0">
|
||||
<Run Text="{DynamicResource Test.Measurement}"/>
|
||||
<Run Text="{Binding MeasurementTimeSec, Mode=OneWay}"/>
|
||||
<Run Text="s"/>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="10" Foreground="DimGray" Margin="10,0,0,0">
|
||||
<Run Text="{DynamicResource Test.MeasPerSec}"/>
|
||||
<Run Text="{Binding MeasurementsPerSecond, StringFormat=F1, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Per-section check all -->
|
||||
<CheckBox Grid.Column="3"
|
||||
IsChecked="{Binding AllPhasesChecked}"
|
||||
VerticalAlignment="Center" Margin="8,0"
|
||||
ToolTip="Enable/disable all phases in this test"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Expander.Header>
|
||||
|
||||
<!-- Phase cards (horizontal scroll) -->
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Disabled"
|
||||
Padding="0,4">
|
||||
<ItemsControl ItemsSource="{Binding Phases}"
|
||||
ItemTemplate="{StaticResource PhaseCardTemplate}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Expander>
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- Test controls -->
|
||||
<RowDefinition Height="Auto"/> <!-- Toolbar -->
|
||||
<RowDefinition Height="Auto"/> <!-- Status bar -->
|
||||
<RowDefinition/> <!-- Test sections -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- ── Test controls (Start / Stop / Report) ──────────────────────── -->
|
||||
<Border Padding="6,8" BorderBrush="#999" BorderThickness="0,0,0,1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Content="{DynamicResource Test.StartTest}" FontSize="15" FontWeight="Bold"
|
||||
Height="44" Margin="0,0,4,0"
|
||||
Command="{Binding DataContext.StartTestCommand,
|
||||
RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Foreground="DarkGreen"/>
|
||||
<Button Grid.Column="1" Content="{DynamicResource Test.Stop}" FontSize="15" FontWeight="Bold"
|
||||
Height="44" Margin="4,0"
|
||||
Command="{Binding DataContext.StopTestCommand,
|
||||
RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Foreground="DarkRed"/>
|
||||
<Button Grid.Column="2" Content="{DynamicResource Test.Report}" FontSize="13"
|
||||
Height="44" Margin="4,0,0,0"
|
||||
Command="{Binding DataContext.GenerateReportCommand,
|
||||
RelativeSource={RelativeSource AncestorType=Window}}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ── Toolbar ─────────────────────────────────────────────────────── -->
|
||||
<Border Grid.Row="1" BorderBrush="Gray" BorderThickness="0,0,0,1" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Show values toggle -->
|
||||
<CheckBox IsChecked="{Binding ShowOperationValues}"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Text="{DynamicResource Test.ShowValues}" FontSize="12"/>
|
||||
</CheckBox>
|
||||
|
||||
<!-- Check all button -->
|
||||
<Button Grid.Column="1" Margin="12,0,0,0"
|
||||
Command="{Binding ToggleCheckAllCommand}"
|
||||
Padding="6,2" ToolTip="Enable/disable all phases">
|
||||
<TextBlock Text="{DynamicResource Test.CheckAll}" FontSize="11"/>
|
||||
</Button>
|
||||
|
||||
<!-- Remaining time -->
|
||||
<TextBlock Grid.Column="3" VerticalAlignment="Center"
|
||||
Foreground="DimGray" FontSize="12" Margin="0,0,4,0">
|
||||
<Run Text="~"/>
|
||||
<Run Text="{Binding RemainingSeconds, Mode=OneWay}"/>
|
||||
<Run Text="{DynamicResource Test.SecondsRemaining}"/>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ── Status line ─────────────────────────────────────────────────── -->
|
||||
<TextBlock Grid.Row="2"
|
||||
Text="{Binding StatusText}"
|
||||
FontSize="12" FontStyle="Italic"
|
||||
Foreground="Gray" Margin="8,2"
|
||||
Visibility="{Binding IsRunning, Converter={StaticResource BoolToVis}}"/>
|
||||
|
||||
<!-- ── Test sections ───────────────────────────────────────────────── -->
|
||||
<ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding Tests}"
|
||||
ItemTemplate="{StaticResource TestSectionTemplate}"
|
||||
Margin="4"/>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for TestPanelView.xaml.
|
||||
/// All logic resides in <see cref="ViewModels.TestPanelViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class TestPanelView : UserControl
|
||||
{
|
||||
/// <summary>Initialises a new instance of the <see cref="TestPanelView"/> class.</summary>
|
||||
public TestPanelView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
64
Views/UserControls/TestPlanView.xaml
Normal file
64
Views/UserControls/TestPlanView.xaml
Normal file
@@ -0,0 +1,64 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.TestPlanView"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
xmlns:vm="clr-namespace:HC_APTBS.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="520" d:DesignWidth="900"
|
||||
Background="#FFEDEDED" Foreground="Black"
|
||||
d:DataContext="{d:DesignInstance Type=vm:TestPanelViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Plan step of the Tests wizard. DataContext: TestPanelViewModel.
|
||||
The operator picks which test phases to run — no Start/Stop/Report buttons,
|
||||
those live on the Preconditions step and in the wizard footer.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<DataTemplate DataType="{x:Type vm:TestSectionViewModel}">
|
||||
<uc:TestSectionView/>
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Toolbar -->
|
||||
<Border BorderBrush="Gray" BorderThickness="0,0,0,1" Padding="8,4">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<CheckBox IsChecked="{Binding ShowOperationValues}"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Text="{DynamicResource Test.ShowValues}" FontSize="12"/>
|
||||
</CheckBox>
|
||||
|
||||
<Button Grid.Column="1" Margin="12,0,0,0"
|
||||
Command="{Binding ToggleCheckAllCommand}"
|
||||
Padding="6,2" ToolTip="Enable/disable all phases">
|
||||
<TextBlock Text="{DynamicResource Test.CheckAll}" FontSize="11"/>
|
||||
</Button>
|
||||
|
||||
<TextBlock Grid.Column="3" VerticalAlignment="Center"
|
||||
Foreground="DimGray" FontSize="12" Margin="0,0,4,0">
|
||||
<Run Text="~"/>
|
||||
<Run Text="{Binding RemainingSeconds, Mode=OneWay}"/>
|
||||
<Run Text="{DynamicResource Test.SecondsRemaining}"/>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Test sections -->
|
||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding Tests}" Margin="4"/>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
16
Views/UserControls/TestPlanView.xaml.cs
Normal file
16
Views/UserControls/TestPlanView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Plan step of the Tests wizard — phase enable/disable and duration preview.
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.TestPanelViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class TestPlanView : UserControl
|
||||
{
|
||||
public TestPlanView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
173
Views/UserControls/TestPreconditionsView.xaml
Normal file
173
Views/UserControls/TestPreconditionsView.xaml
Normal file
@@ -0,0 +1,173 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.TestPreconditionsView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="520" d:DesignWidth="680"
|
||||
d:DataContext="{d:DesignInstance Type=vm:TestPreconditionsViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Preconditions checklist (Tests page wizard step 4b).
|
||||
DataContext: TestPreconditionsViewModel.
|
||||
Rows auto-refresh as underlying properties change; Start button is disabled
|
||||
until AllPassed is true.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border Background="White" BorderBrush="#DDD" BorderThickness="1" CornerRadius="4" Padding="14">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Title -->
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="{DynamicResource Test.Precheck.Title}"
|
||||
FontSize="16" FontWeight="SemiBold" Foreground="#222"
|
||||
Margin="0,0,0,10"/>
|
||||
|
||||
<!-- Auth gate (only when a required test has RequiresAuth=true) -->
|
||||
<Border Grid.Row="1"
|
||||
Background="#FFF8E1" BorderBrush="#F0C24A" BorderThickness="1"
|
||||
CornerRadius="3" Padding="10,8" Margin="0,0,0,10"
|
||||
Visibility="{Binding IsAuthRequired, Converter={StaticResource BoolToVis}}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||
<TextBlock Text="{DynamicResource Test.Precheck.AuthBanner}"
|
||||
FontSize="12" FontWeight="SemiBold" Foreground="#7A5A00"/>
|
||||
<TextBlock Text="{Binding TestAuth.AuthenticatedUser}"
|
||||
FontSize="11" Foreground="#7A5A00"
|
||||
Visibility="{Binding TestAuth.IsAuthenticated, Converter={StaticResource BoolToVis}}"/>
|
||||
</StackPanel>
|
||||
<Button Grid.Column="1"
|
||||
Content="{DynamicResource Test.Precheck.AuthButton}"
|
||||
Command="{Binding TestAuth.AuthenticateCommand}"
|
||||
Padding="10,4" FontSize="12"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Checklist -->
|
||||
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding Items}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type vm:PreconditionItemViewModel}">
|
||||
<Border BorderBrush="#EEE" BorderThickness="0,0,0,1" Padding="0,8">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Status glyph -->
|
||||
<Border Grid.Column="0" Width="20" Height="20"
|
||||
CornerRadius="10" VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0,0,8,0">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="#E74C3C"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSatisfied}" Value="True">
|
||||
<Setter Property="Background" Value="#26C200"/>
|
||||
</DataTrigger>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding IsSatisfied}" Value="False"/>
|
||||
<Condition Binding="{Binding IsRequired}" Value="False"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="Background" Value="#BBB"/>
|
||||
</MultiDataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Foreground="White" FontSize="12" FontWeight="Bold">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="✕"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSatisfied}" Value="True">
|
||||
<Setter Property="Text" Value="✓"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<!-- Label + remediation text -->
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding Label}" FontSize="13" Foreground="#222"/>
|
||||
<TextBlock Text="{Binding RemediationText}"
|
||||
FontSize="11" Foreground="#888">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSatisfied}" Value="True">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Fix-it button -->
|
||||
<Button Grid.Column="2"
|
||||
Content="{DynamicResource Test.Precheck.FixButton}"
|
||||
Command="{Binding NavigateToFixCommand}"
|
||||
Padding="8,3" FontSize="11" Margin="8,0,0,0"
|
||||
Visibility="{Binding HasRemediation, Converter={StaticResource BoolToVis}}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- Start button row -->
|
||||
<Grid Grid.Row="3" Margin="0,14,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" VerticalAlignment="Center"
|
||||
FontSize="12" Foreground="#666"
|
||||
Text="{DynamicResource Test.Precheck.NotReady}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding AllPassed}" Value="True">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="0" VerticalAlignment="Center"
|
||||
FontSize="12" Foreground="#26C200" FontWeight="SemiBold"
|
||||
Text="{DynamicResource Test.Precheck.Ready}"
|
||||
Visibility="{Binding AllPassed, Converter={StaticResource BoolToVis}}"/>
|
||||
|
||||
<Button Grid.Column="1"
|
||||
Content="{DynamicResource Test.StartTest}"
|
||||
Command="{Binding StartTestCommand}"
|
||||
Padding="18,6" FontSize="14" FontWeight="Bold"
|
||||
Background="#26C200" Foreground="White" BorderThickness="0"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
16
Views/UserControls/TestPreconditionsView.xaml.cs
Normal file
16
Views/UserControls/TestPreconditionsView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Preconditions checklist for the Tests page wizard (§4b).
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.TestPreconditionsViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class TestPreconditionsView : UserControl
|
||||
{
|
||||
public TestPreconditionsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
159
Views/UserControls/TestRunningView.xaml
Normal file
159
Views/UserControls/TestRunningView.xaml
Normal file
@@ -0,0 +1,159 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.TestRunningView"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
xmlns:vm="clr-namespace:HC_APTBS.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="640" d:DesignWidth="1000"
|
||||
Background="#FFEDEDED" Foreground="Black"
|
||||
d:DataContext="{d:DesignInstance Type=vm:TestPanelViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Running step of the Tests wizard. DataContext: TestPanelViewModel.
|
||||
Shows the active phase countdown, live phase-card updates, and the flowmeter /
|
||||
angle visuals. Pause / Retry-phase / Skip-phase buttons are rendered disabled —
|
||||
their IBenchService wiring is deferred (see docs/gap-test-running-controls.md).
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
|
||||
<DataTemplate DataType="{x:Type vm:TestSectionViewModel}">
|
||||
<uc:TestSectionView/>
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- Phase header + countdown -->
|
||||
<RowDefinition Height="*"/> <!-- Sections + live charts -->
|
||||
<RowDefinition Height="Auto"/> <!-- Control row -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Phase header + countdown + progress -->
|
||||
<Border Padding="10,8" BorderBrush="#DDD" BorderThickness="0,0,0,1"
|
||||
Background="White">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding CurrentPhaseName}"
|
||||
FontSize="16" FontWeight="SemiBold"
|
||||
Foreground="#222"/>
|
||||
<StackPanel Orientation="Horizontal" Margin="0,1,0,0">
|
||||
<TextBlock Text="{Binding SectionLabel}"
|
||||
FontSize="11" FontStyle="Italic"
|
||||
Foreground="#666"/>
|
||||
<TextBlock Text="{Binding StatusText}"
|
||||
FontSize="11" FontStyle="Italic"
|
||||
Foreground="Gray" Margin="8,0,0,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding PhaseRemainingSeconds, Mode=OneWay}"
|
||||
FontSize="32" FontFamily="Impact"
|
||||
Foreground="#1565C0"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBlock Text="s" FontSize="18"
|
||||
Foreground="#1565C0"
|
||||
VerticalAlignment="Bottom" Margin="2,0,0,4"/>
|
||||
<TextBlock Foreground="#999" FontSize="11"
|
||||
VerticalAlignment="Bottom" Margin="8,0,0,4">
|
||||
<Run Text="/ "/>
|
||||
<Run Text="{Binding PhaseTotalSeconds, Mode=OneWay}"/>
|
||||
<Run Text="s"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<ProgressBar Grid.Row="1" Grid.ColumnSpan="2"
|
||||
Minimum="0" Maximum="1"
|
||||
Value="{Binding PhaseProgress, Mode=OneWay}"
|
||||
Height="6" Margin="0,6,0,0"
|
||||
Background="#EEE" Foreground="#1565C0"
|
||||
BorderThickness="0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Main body: test sections on left, live charts on right -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="420"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Live phase-card list (read-only during run, cards colour themselves) -->
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding Tests}" Margin="4"/>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- Charts + angle display -->
|
||||
<Grid Grid.Column="1" Margin="4">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<uc:FlowmeterChartView Grid.Row="0"
|
||||
DataContext="{Binding DataContext.FlowmeterChart.Delivery,
|
||||
RelativeSource={RelativeSource AncestorType=Window}}"/>
|
||||
|
||||
<uc:FlowmeterChartView Grid.Row="1"
|
||||
DataContext="{Binding DataContext.FlowmeterChart.Over,
|
||||
RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Margin="0,4,0,0"/>
|
||||
|
||||
<uc:AngleDisplayView Grid.Row="2"
|
||||
DataContext="{Binding DataContext.AngleDisplay,
|
||||
RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Margin="0,4,0,0"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<!-- Control row -->
|
||||
<Border Grid.Row="2" Padding="10,8"
|
||||
BorderBrush="#DDD" BorderThickness="0,1,0,0"
|
||||
Background="White">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Grid.Column="0">
|
||||
<Button Content="{DynamicResource Test.Running.Pause}"
|
||||
IsEnabled="False"
|
||||
ToolTip="{DynamicResource Test.Running.ComingSoon}"
|
||||
Padding="12,5" FontSize="12" Margin="0,0,6,0"/>
|
||||
|
||||
<Button Content="{DynamicResource Test.Running.Retry}"
|
||||
IsEnabled="False"
|
||||
ToolTip="{DynamicResource Test.Running.ComingSoon}"
|
||||
Padding="12,5" FontSize="12" Margin="0,0,6,0"/>
|
||||
|
||||
<Button Content="{DynamicResource Test.Running.Skip}"
|
||||
IsEnabled="False"
|
||||
ToolTip="{DynamicResource Test.Running.ComingSoon}"
|
||||
Padding="12,5" FontSize="12"/>
|
||||
</StackPanel>
|
||||
|
||||
<Button Grid.Column="2"
|
||||
Content="{DynamicResource Test.Running.Abort}"
|
||||
Command="{Binding DataContext.TestsPage.AbortCommand,
|
||||
RelativeSource={RelativeSource AncestorType=Window}}"
|
||||
Padding="18,6" FontSize="14" FontWeight="Bold"
|
||||
Background="#C62828" Foreground="White" BorderThickness="0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
16
Views/UserControls/TestRunningView.xaml.cs
Normal file
16
Views/UserControls/TestRunningView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Running step of the Tests wizard — live phase progress, flowmeter charts, abort.
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.TestPanelViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class TestRunningView : UserControl
|
||||
{
|
||||
public TestRunningView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Views/UserControls/TestSectionView.xaml
Normal file
91
Views/UserControls/TestSectionView.xaml
Normal file
@@ -0,0 +1,91 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.TestSectionView"
|
||||
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:uc="clr-namespace:HC_APTBS.Views.UserControls"
|
||||
xmlns:vm="clr-namespace:HC_APTBS.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance Type=vm:TestSectionViewModel, IsDesignTimeCreatable=False}">
|
||||
<!--
|
||||
Expander header + horizontal list of phase cards. DataContext: TestSectionViewModel.
|
||||
Used by TestPlanView and TestRunningView — both show the same structure, differing
|
||||
only in which card state is currently highlighted.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<DataTemplate DataType="{x:Type vm:PhaseCardViewModel}">
|
||||
<uc:PhaseCardView/>
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Expander IsExpanded="{Binding IsExpanded}" Margin="0,2,0,0">
|
||||
<Expander.Header>
|
||||
<Border Padding="4,2" CornerRadius="2">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsActiveTest}" Value="True">
|
||||
<Setter Property="Background" Value="#FFFFF3CD"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Text="{Binding TestName}"
|
||||
FontSize="20" FontFamily="Impact" FontStyle="Italic"
|
||||
VerticalAlignment="Center" Foreground="Black"
|
||||
Padding="4,0"/>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding Description}"
|
||||
FontSize="14" FontStyle="Italic" FontFamily="Impact"
|
||||
VerticalAlignment="Bottom" Foreground="Gray"
|
||||
Padding="8,0,0,3"/>
|
||||
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal"
|
||||
VerticalAlignment="Center" Margin="16,0,0,0">
|
||||
<TextBlock FontSize="10" Foreground="DimGray">
|
||||
<Run Text="{DynamicResource Test.Condition}"/>
|
||||
<Run Text="{Binding ConditioningTimeSec, Mode=OneWay}"/>
|
||||
<Run Text="s"/>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="10" Foreground="DimGray" Margin="10,0,0,0">
|
||||
<Run Text="{DynamicResource Test.Measurement}"/>
|
||||
<Run Text="{Binding MeasurementTimeSec, Mode=OneWay}"/>
|
||||
<Run Text="s"/>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="10" Foreground="DimGray" Margin="10,0,0,0">
|
||||
<Run Text="{DynamicResource Test.MeasPerSec}"/>
|
||||
<Run Text="{Binding MeasurementsPerSecond, StringFormat=F1, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox Grid.Column="3"
|
||||
IsChecked="{Binding AllPhasesChecked}"
|
||||
VerticalAlignment="Center" Margin="8,0"
|
||||
ToolTip="Enable/disable all phases in this test"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Expander.Header>
|
||||
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Disabled"
|
||||
Padding="0,4">
|
||||
<ItemsControl ItemsSource="{Binding Phases}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Expander>
|
||||
</UserControl>
|
||||
16
Views/UserControls/TestSectionView.xaml.cs
Normal file
16
Views/UserControls/TestSectionView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// One test section — Expander header plus the horizontal row of phase cards.
|
||||
/// DataContext is expected to be a <see cref="HC_APTBS.ViewModels.TestSectionViewModel"/>.
|
||||
/// </summary>
|
||||
public partial class TestSectionView : UserControl
|
||||
{
|
||||
public TestSectionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
113
Views/UserControls/UnlockPanelView.xaml
Normal file
113
Views/UserControls/UnlockPanelView.xaml
Normal file
@@ -0,0 +1,113 @@
|
||||
<UserControl x:Class="HC_APTBS.Views.UserControls.UnlockPanelView"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="380" d:DesignWidth="700">
|
||||
<!--
|
||||
Pump page §3.e Unlock inline view. DataContext = UnlockProgressViewModel
|
||||
(exposed from MainViewModel.CurrentUnlockVm). Hidden by the parent when
|
||||
the selected pump does not require unlock or the VM is null.
|
||||
-->
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border Background="#2B2929" BorderBrush="#111" BorderThickness="1"
|
||||
CornerRadius="4" Padding="18" Margin="6">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/> <!-- title -->
|
||||
<RowDefinition Height="Auto"/> <!-- type label -->
|
||||
<RowDefinition Height="210"/> <!-- ring -->
|
||||
<RowDefinition Height="Auto"/> <!-- phase text -->
|
||||
<RowDefinition Height="Auto"/> <!-- progress bar -->
|
||||
<RowDefinition Height="Auto"/> <!-- result -->
|
||||
<RowDefinition Height="Auto"/> <!-- buttons -->
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="{DynamicResource PumpSub.Unlock}"
|
||||
FontSize="15" FontWeight="SemiBold" Foreground="#EEE"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,4"/>
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Text="{Binding UnlockTypeLabel, Mode=OneWay}"
|
||||
FontSize="13" Foreground="#AAA"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,6"/>
|
||||
|
||||
<!-- Progress ring -->
|
||||
<Grid Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Ellipse Width="200" Height="200"
|
||||
Stroke="#4D4D4D" StrokeThickness="10"
|
||||
Fill="Transparent"/>
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock Text="{DynamicResource Dialog.Unlock.Progress}"
|
||||
FontSize="12" Foreground="#888"
|
||||
HorizontalAlignment="Center" Margin="0,0,0,4"/>
|
||||
<TextBlock FontSize="60" FontFamily="Courier New"
|
||||
Foreground="White" HorizontalAlignment="Center">
|
||||
<TextBlock.Text>
|
||||
<Binding Path="Progress" Mode="OneWay"
|
||||
StringFormat="{}{0}%"/>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding ElapsedTime, Mode=OneWay}"
|
||||
FontSize="16" FontFamily="Courier New"
|
||||
Foreground="#CCC" HorizontalAlignment="Center"
|
||||
Margin="0,2,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="3"
|
||||
Text="{Binding PhaseText, Mode=OneWay}"
|
||||
FontSize="16" Foreground="White"
|
||||
HorizontalAlignment="Center" Margin="0,6"/>
|
||||
|
||||
<ProgressBar Grid.Row="4"
|
||||
Value="{Binding Progress, Mode=OneWay}"
|
||||
Minimum="0" Maximum="100"
|
||||
Height="12" Margin="12,0"
|
||||
Foreground="#00EC00" Background="#3D3D3D"/>
|
||||
|
||||
<TextBlock Grid.Row="5"
|
||||
Text="{Binding ResultText, Mode=OneWay}"
|
||||
FontSize="22" FontWeight="Bold"
|
||||
HorizontalAlignment="Center" Margin="0,10,0,0"
|
||||
Visibility="{Binding IsComplete, Converter={StaticResource BoolToVis}}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#FF5858"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSuccess}" Value="True">
|
||||
<Setter Property="Foreground" Value="#00EC00"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
|
||||
<!-- Only the cancel button is exposed inline; the panel cannot be "closed" here -->
|
||||
<StackPanel Grid.Row="6" Orientation="Horizontal"
|
||||
HorizontalAlignment="Center" Margin="0,14,0,0">
|
||||
<Button Content="{DynamicResource Common.Cancel}"
|
||||
Command="{Binding CancelCommand}"
|
||||
Width="110" Height="30"
|
||||
Foreground="White" FontWeight="Bold">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Background" Value="#FF5858"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="Background" Value="#4D4D4D"/>
|
||||
<Setter Property="Foreground" Value="#888"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
17
Views/UserControls/UnlockPanelView.xaml.cs
Normal file
17
Views/UserControls/UnlockPanelView.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HC_APTBS.Views.UserControls
|
||||
{
|
||||
/// <summary>
|
||||
/// Inline unlock panel (Pump page §3.e). DataContext is the
|
||||
/// shared <c>UnlockProgressViewModel</c> also driving the floating
|
||||
/// progress dialog.
|
||||
/// </summary>
|
||||
public partial class UnlockPanelView : UserControl
|
||||
{
|
||||
public UnlockPanelView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user