From e2de64625a5a3c16653416f3a2798124a44eeeec Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 16 Oct 2026 14:40:37 +0000 Subject: [PATCH 1/3] Add a Look setting with Frutiger Aero and Metal Heart themes Every colour, font and shape the window reads now comes from a pair of resource dictionaries under Themes/ (one dark, one light) that Theme.Apply merges in, so a new look is two XAML files and one line in the list. Settings gets a Look picker next to the dark/light one; both apply live and are remembered in settings.json. Looks: Rack faceplate (unchanged default), Frutiger Aero (glass panels over sky and grass, glossy pills, Segoe UI) and Metal Heart (brushed steel, bevelled edges, chrome-red accent, Bahnschrift display face). The smoke test now screenshots each look so they can be compared from the CI run. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01XaLCFyaNVfAWPcHVakuuu8 --- README.md | 4 +- src/ProDHCPServer.App/App.xaml | 38 ++++++---- src/ProDHCPServer.App/App.xaml.cs | 3 +- src/ProDHCPServer.App/Converters.cs | 29 ++++++-- src/ProDHCPServer.App/MainWindow.xaml | 23 ++++-- src/ProDHCPServer.App/Theme.cs | 73 +++++++++--------- .../Themes/Faceplate.Dark.xaml | 51 +++++++++++++ .../Themes/Faceplate.Light.xaml | 51 +++++++++++++ .../Themes/FrutigerAero.Dark.xaml | 64 ++++++++++++++++ .../Themes/FrutigerAero.Light.xaml | 64 ++++++++++++++++ .../Themes/MetalHeart.Dark.xaml | 74 +++++++++++++++++++ .../Themes/MetalHeart.Light.xaml | 74 +++++++++++++++++++ .../ViewModels/MainViewModel.cs | 10 ++- .../ViewModels/SettingsViewModel.cs | 9 ++- src/ProDHCPServer.Core/AppSettings.cs | 2 + tools/smoke-test.ps1 | 20 +++-- 16 files changed, 514 insertions(+), 75 deletions(-) create mode 100644 src/ProDHCPServer.App/Themes/Faceplate.Dark.xaml create mode 100644 src/ProDHCPServer.App/Themes/Faceplate.Light.xaml create mode 100644 src/ProDHCPServer.App/Themes/FrutigerAero.Dark.xaml create mode 100644 src/ProDHCPServer.App/Themes/FrutigerAero.Light.xaml create mode 100644 src/ProDHCPServer.App/Themes/MetalHeart.Dark.xaml create mode 100644 src/ProDHCPServer.App/Themes/MetalHeart.Light.xaml diff --git a/README.md b/README.md index d195a19..0d48bae 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Most AV kit ships set to DHCP, and on a bench or a fresh site there's usually no - **Several devices at once** behind a small switch, each with its own lease. - **Spots a USB adapter that has stopped receiving.** Some USB Ethernet adapters keep showing "connected" but quietly stop receiving after a few seconds, which looks exactly like a silent device. If nothing has come in for 20 seconds while the laptop keeps sending, the cable/link step says so and tells you to replug the adapter. Realtek RTL8152/8153 adapters on a driver older than 2019 (including Windows' own 2015 driver) are flagged as soon as you pick them, with where to get the newer driver. - **Wi-Fi and VPN overlap warnings**, with a one-click option to turn Wi-Fi off until you press Stop. -- **Dark and light themes**, with large status text you can read from arm's length. +- **Dark and light themes** and a choice of looks (rack faceplate, Frutiger Aero, Metal Heart), with large status text you can read from arm's length. **Phase 2: visibility** @@ -104,7 +104,7 @@ Each phase ends with a hardware test pass on real AV equipment before the next o | What | Where | |---|---| -| Your settings (last adapter, profile in use, theme) | `%LOCALAPPDATA%\ProDHCPServer\settings.json` | +| Your settings (last adapter, profile in use, look and theme) | `%LOCALAPPDATA%\ProDHCPServer\settings.json` | | Your profiles | `%LOCALAPPDATA%\ProDHCPServer\profiles.json` | | Adapter backup (only while a session runs, or after a crash) | `%ProgramData%\ProDHCPServer\adapter-backup.json` | diff --git a/src/ProDHCPServer.App/App.xaml b/src/ProDHCPServer.App/App.xaml index 27e628e..5e428c9 100644 --- a/src/ProDHCPServer.App/App.xaml +++ b/src/ProDHCPServer.App/App.xaml @@ -12,12 +12,10 @@ - pack://application:,,,/Assets/Fonts/#Figtree - pack://application:,,,/Assets/Fonts/#League Spartan - pack://application:,,,/Assets/Fonts/#Figtree Cascadia Mono, Consolas, Courier New Segoe Fluent Icons, Segoe MDL2 Assets @@ -28,14 +26,20 @@ 40 64 - + @@ -75,13 +79,14 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/src/ProDHCPServer.App/Assets/Fonts/OFL-Orbitron.txt b/src/ProDHCPServer.App/Assets/Fonts/OFL-Orbitron.txt new file mode 100644 index 0000000..91ede45 --- /dev/null +++ b/src/ProDHCPServer.App/Assets/Fonts/OFL-Orbitron.txt @@ -0,0 +1,93 @@ +Copyright 2018 The Orbitron Project Authors (https://github.com/theleagueof/orbitron), with Reserved Font Name: "Orbitron" + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/ProDHCPServer.App/Assets/Fonts/Orbitron-Bold.ttf b/src/ProDHCPServer.App/Assets/Fonts/Orbitron-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..3252adcec0a74f80f14b7428f11dde11d9c2c579 GIT binary patch literal 24512 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 Cfks#W literal 0 HcmV?d00001 diff --git a/src/ProDHCPServer.App/Converters.cs b/src/ProDHCPServer.App/Converters.cs index 0740ba7..7532a7a 100644 --- a/src/ProDHCPServer.App/Converters.cs +++ b/src/ProDHCPServer.App/Converters.cs @@ -37,6 +37,24 @@ public sealed class StateBrushConverter : IValueConverter public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotSupportedException(); } +/// +/// IsRunning → the Start/Stop button's Background or Foreground (the ConverterParameter): solid ink to start, a quiet +/// button to stop, since the status field already says the server is live. Looked up again after a look change. +/// +public sealed class RunningBrushConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + bool running = value is true; + var key = parameter as string == "Foreground" + ? (running ? "TextPrimary" : "AccentText") + : (running ? "RaisedBg" : "AccentBrush"); + return Application.Current.TryFindResource(key); + } + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotSupportedException(); +} + /// StepState → a short word for screen readers and the colour-blind. public sealed class StateWordConverter : IValueConverter { diff --git a/src/ProDHCPServer.App/MainWindow.xaml b/src/ProDHCPServer.App/MainWindow.xaml index de37394..34fd4f9 100644 --- a/src/ProDHCPServer.App/MainWindow.xaml +++ b/src/ProDHCPServer.App/MainWindow.xaml @@ -40,7 +40,8 @@ - + + @@ -87,12 +88,15 @@ ItemsSource="{Binding Settings.Profiles}" SelectedItem="{Binding Settings.SelectedProfile}" DisplayMemberPath="Display" IsEnabled="{Binding SettingsEditable}" ToolTip="The saved settings Start uses: subnet, pool, lease time and DHCP options" /> - + - + - + + - + - -