Files
HC_APTBS/Resources/Styles.xaml
LucianoDev 69bfda54e1 feat: redesign Bench page with Fluent card layout and radial advance monitor
Three-column layout replacing the old HMI grid:
- BenchRpmCommandCard: inline numeric input, 2×4 preset grid, Start/Stop
- BenchActuatorsCard: direction toggle, oil pump, temperature PID, misc relays
  with FluentStateToggle showing checked state via AccentFillColor
- BenchLiveDataCard: 2×5 KPI tiles (RPM, P1, P2, Q-Delivery, Q-Over, temps)
- BenchChartsCard: 2×2 compact chart grid (Delivery, Over, P1, P2)
- AdvanceMonitorCard: RadialAngleGauge custom FrameworkElement + PSG/INJ readouts,
  Δ° lock offset input, Zero PSG / Zero INJ buttons

Supporting changes:
- AngleDisplayViewModel: promote _currentManualDegrees, _isLockSet to
  [ObservableProperty]; add PsgRelativeDegrees, InjEncoderDegreesValue,
  TargetLockAngle, IsRunningMode (29/31 hysteresis); computed PrimaryGaugeAngle,
  TargetAngleForGauge, SecondaryGaugeAngle
- BenchControlViewModel: add IsDirectionLeft computed property,
  SetDirectionRightCommand, SetDirectionLeftCommand, ApplyRpmCommand
- FlowmeterChartView: add IsCompact DP (false default) for 90px compact height
- Styles.xaml: add IsChecked trigger to FluentStateToggle (accent fill + white text)
- Strings.en/es.xaml: add all new card and actuator string keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 17:45:59 +02:00

276 lines
15 KiB
XML

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:HC_APTBS.Converters">
<!-- Boolean → Visibility converter (shared across views) -->
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
<!-- Null → Collapsed, non-null → Visible -->
<conv:NullToVisibilityConverter x:Key="NullToVis"/>
<!-- LCD blue gradient border -->
<Style x:Key="LcdBlue" TargetType="Border">
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="4"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.3,0" EndPoint="0.5,1.3">
<GradientStop Color="#0040ff" Offset="0"/>
<GradientStop Color="#0031c2" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<!-- LCD amber gradient border -->
<Style x:Key="LcdAmber" TargetType="Border">
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="3"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.3,0" EndPoint="0.5,1.3">
<GradientStop Color="#ffae00" Offset="0"/>
<GradientStop Color="#91670a" Offset="2"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<!-- Connection indicator style (green/gray) -->
<Style x:Key="ConnIndicator" TargetType="Border">
<Setter Property="Background" Value="Gray"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Margin" Value="2,4"/>
</Style>
<!-- Relay toggle button style — inherits WPF-UI Button appearance -->
<Style x:Key="RelayButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Padding" Value="6,3"/>
<Setter Property="Margin" Value="3,2"/>
<Setter Property="FontSize" Value="11"/>
</Style>
<!--
Base style for state-indicating toggle buttons (on/off with colour feedback).
Uses a custom ControlTemplate so that TemplateBinding Background is honoured
in ALL states — including IsChecked=True. Derived styles add IsChecked triggers
with a custom Background colour (green, amber, blue, etc.) and those colours are
guaranteed to propagate, unlike WPF-UI's own ToggleButton template which has an
internal IsChecked trigger that would override a simple BasedOn + Background setter.
Hover/pressed feedback is applied via a transparent overlay so it works on any
background colour without conflicting with the checked state.
-->
<Style x:Key="FluentStateToggle" TargetType="ToggleButton">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}"/>
<Setter Property="Padding" Value="8,4"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Background" Value="{DynamicResource ControlFillColorDefaultBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeColorDefaultBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Border x:Name="Root"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4"
SnapsToDevicePixels="True"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
TextElement.Foreground="{TemplateBinding Foreground}"/>
<!-- Transparent overlay — darkens on hover/pressed over any background colour -->
<Border x:Name="HoverOverlay" CornerRadius="4" Background="Transparent"
IsHitTestVisible="False"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Root" Property="Background" Value="{DynamicResource AccentFillColorDefaultBrush}"/>
<Setter TargetName="Root" Property="BorderBrush" Value="{DynamicResource AccentFillColorDefaultBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource TextOnAccentFillColorPrimaryBrush}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="HoverOverlay" Property="Background" Value="#18000000"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="HoverOverlay" Property="Background" Value="#30000000"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ── Dashboard KPI tile styles ─────────────────────────────────────── -->
<Style x:Key="KpiTile" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource CardBackgroundFillColorDefaultBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource CardStrokeColorDefaultBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Padding" Value="16"/>
<Setter Property="Margin" Value="6"/>
<Setter Property="MinHeight" Value="140"/>
</Style>
<Style x:Key="KpiHeaderText" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="{DynamicResource TextFillColorSecondaryBrush}"/>
<Setter Property="Margin" Value="0,0,0,4"/>
</Style>
<Style x:Key="KpiValueText" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="52"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}"/>
<Setter Property="TextAlignment" Value="Left"/>
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
</Style>
<Style x:Key="KpiUnitText" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="{DynamicResource TextFillColorTertiaryBrush}"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="6,0,0,6"/>
</Style>
<!-- Connection strip chip -->
<Style x:Key="ConnChip" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeColorDefaultBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="14"/>
<Setter Property="Padding" Value="14,6"/>
<Setter Property="Margin" Value="0,0,8,0"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>
<!-- Status dot (10 px ellipse; Fill overridden by DataTrigger for state colour) -->
<Style x:Key="StatusDot" TargetType="Ellipse">
<Setter Property="Width" Value="10"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Fill" Value="{DynamicResource SystemFillColorNeutralBrush}"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="6,0,4,0"/>
</Style>
<!-- ── Pump page card chrome (same Fluent look as Dashboard inline cards) ── -->
<Style x:Key="PumpCard" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource CardBackgroundFillColorDefaultBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource CardStrokeColorDefaultBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Padding" Value="16"/>
<Setter Property="Margin" Value="4"/>
</Style>
<Style x:Key="PumpCardHeader" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}"/>
<Setter Property="Margin" Value="0,0,0,10"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<!-- Small label beneath a pump slider (parameter name, unit, range limit) -->
<Style x:Key="PumpCommandLabel" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="Foreground" Value="{DynamicResource TextFillColorSecondaryBrush}"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
<!-- Current-value readout beneath a pump slider -->
<Style x:Key="PumpCommandValue" TargetType="TextBox">
<Setter Property="FontFamily" Value="Consolas"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Foreground" Value="{DynamicResource AccentTextFillColorPrimaryBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="Padding" Value="4,2"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="30"/>
</Style>
<!-- Snackbar bottom-overlay shell -->
<Style x:Key="SnackbarShell" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource CardBackgroundFillColorDefaultBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource CardStrokeColorDefaultBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="#000000" Opacity="0.18" BlurRadius="20" ShadowDepth="4"/>
</Setter.Value>
</Setter>
</Style>
<!-- ── Device row button — hover tint indicates intent (connect=blue, disconnect=red) -->
<Style x:Key="DeviceRow" TargetType="Button">
<Setter Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="10,6"/>
<Setter Property="Margin" Value="0,0,0,4"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
CornerRadius="6">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<!-- Hover + disconnected → accent blue (will connect) -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsMouseOver}" Value="True"/>
<Condition Binding="{Binding IsConnected}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource AccentFillColorSecondaryBrush}"/>
</MultiDataTrigger>
<!-- Hover + connected → critical red (will disconnect) -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsMouseOver}" Value="True"/>
<Condition Binding="{Binding IsConnected}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SystemFillColorCriticalBackgroundBrush}"/>
</MultiDataTrigger>
<!-- Disabled → muted (bench placeholder) -->
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Bd" Property="Opacity" Value="0.5"/>
<Setter Property="Cursor" Value="Arrow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>