Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**

Expand Down Expand Up @@ -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` |

Expand Down
179 changes: 5 additions & 174 deletions src/ProDHCPServer.App/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,184 +11,15 @@
<local:StateGlyphConverter x:Key="StateGlyph" />
<local:VisibleWhenConverter x:Key="VisibleWhen" />

<local:RunningBrushConverter x:Key="RunningBrush" />
<!--
Faces: Figtree for everything you read, League Spartan only for the few big things (status line, device IP).
Both are embedded so every laptop shows the same thing. Monospace is kept for raw technical detail only.
Everything else (type scale, text styles, panel and button shapes, colours, fonts, backdrop) comes from the
current look: Theme.Apply merges Themes/<Look>.<Dark|Light>.xaml, which itself merges Themes/Shared.xaml.
-->
<FontFamily x:Key="TextFont">pack://application:,,,/Assets/Fonts/#Figtree</FontFamily>
<FontFamily x:Key="DisplayFont">pack://application:,,,/Assets/Fonts/#League Spartan</FontFamily>
<FontFamily x:Key="ContentControlThemeFontFamily">pack://application:,,,/Assets/Fonts/#Figtree</FontFamily>
<FontFamily x:Key="MonoFont">Cascadia Mono, Consolas, Courier New</FontFamily>
<FontFamily x:Key="IconFont">Segoe Fluent Icons, Segoe MDL2 Assets</FontFamily>

<!-- Five sizes: small, body, lead, head, display. Nothing below 13. -->
<sys:Double x:Key="TextSmall">13</sys:Double>
<sys:Double x:Key="TextBody">16</sys:Double>
<sys:Double x:Key="TextLead">20</sys:Double>
<sys:Double x:Key="TextHead">40</sys:Double>
<sys:Double x:Key="TextDisplay">64</sys:Double>

<!-- Panels are a tone step above the ground: no border, no shadow, square corners. -->
<Style x:Key="Panel" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource PanelBg}" />
<Setter Property="Padding" Value="24" />
</Style>

<!-- Status banners: a whole field of the state's soft colour. -->
<Style x:Key="Banner" TargetType="Border">
<Setter Property="Padding" Value="24,16" />
<Setter Property="Margin" Value="0,0,0,16" />
</Style>

<Style x:Key="SectionTitle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource TextLead}" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Foreground" Value="{DynamicResource TextPrimary}" />
</Style>

<Style x:Key="Primary" TargetType="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource TextPrimary}" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>

<Style x:Key="Secondary" TargetType="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource TextSecondary}" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>

<Style x:Key="Meta" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource TextSmall}" />
<Setter Property="Foreground" Value="{DynamicResource TextMuted}" />
</Style>

<!-- Raw technical detail (packets, exceptions): the one place monospace belongs. -->
<Style x:Key="MonoBox" TargetType="TextBox">
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
<Setter Property="FontSize" Value="{StaticResource TextSmall}" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="MaxHeight" Value="224" />
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="Background" Value="{DynamicResource MonoBg}" />
<Setter Property="Foreground" Value="{DynamicResource TextSecondary}" />
<Setter Property="BorderThickness" Value="0" />
</Style>

<!--
Buttons: flat, one fill, fully round (the status LED's circle is the app's one shape). Hover and press tint the
fill with its own text colour; keyboard focus draws a ring in the ink colour outside the button.
-->
<Style x:Key="PillButton" TargetType="Button">
<Setter Property="Background" Value="{DynamicResource RaisedBg}" />
<Setter Property="Foreground" Value="{DynamicResource TextPrimary}" />
<Setter Property="FontFamily" Value="{StaticResource TextFont}" />
<Setter Property="FontSize" Value="{StaticResource TextBody}" />
<Setter Property="FontWeight" Value="Medium" />
<Setter Property="Padding" Value="20,0" />
<Setter Property="MinHeight" Value="40" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="Ring" Margin="-4" CornerRadius="{Binding ActualHeight, RelativeSource={RelativeSource Self}, Converter={x:Static local:PillRadiusConverter.Instance}}" BorderThickness="2" BorderBrush="Transparent" />
<Border x:Name="Bg" CornerRadius="{Binding ActualHeight, RelativeSource={RelativeSource Self}, Converter={x:Static local:PillRadiusConverter.Instance}}" Background="{TemplateBinding Background}" />
<Border x:Name="Tint" CornerRadius="{Binding ActualHeight, RelativeSource={RelativeSource Self}, Converter={x:Static local:PillRadiusConverter.Instance}}" Background="{TemplateBinding Foreground}" Opacity="0" />
<ContentPresenter Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="Center"
TextElement.Foreground="{TemplateBinding Foreground}" RecognizesAccessKey="True" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Tint" Property="Opacity" Value="0.08" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Tint" Property="Opacity" Value="0.16" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="Ring" Property="BorderBrush" Value="{DynamicResource TextPrimary}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<!-- The primary action: solid ink. -->
<Style x:Key="AccentButton" TargetType="Button" BasedOn="{StaticResource PillButton}">
<Setter Property="Background" Value="{DynamicResource AccentBrush}" />
<Setter Property="Foreground" Value="{DynamicResource AccentText}" />
<Setter Property="FontWeight" Value="SemiBold" />
</Style>

<Style x:Key="SecondaryButton" TargetType="Button" BasedOn="{StaticResource PillButton}" />

<!-- Risky confirmations only. -->
<Style x:Key="DangerButton" TargetType="Button" BasedOn="{StaticResource PillButton}">
<Setter Property="Background" Value="{DynamicResource BadBrush}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontWeight" Value="SemiBold" />
</Style>

<!-- Round icon-only button. Always give it a ToolTip (shown on hover and keyboard focus) and an AutomationProperties.Name. -->
<Style x:Key="IconButton" TargetType="Button" BasedOn="{StaticResource PillButton}">
<Setter Property="FontFamily" Value="{StaticResource IconFont}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="Width" Value="48" />
<Setter Property="Height" Value="48" />
<Setter Property="Padding" Value="0" />
</Style>

<!-- A clickable list row: flat at rest, a tone step on hover, an ink ring on keyboard focus. -->
<Style x:Key="RowButton" TargetType="Button">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource TextPrimary}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="16,12" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bg" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="2"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bg" Property="Background" Value="{DynamicResource RowHover}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="Bg" Property="BorderBrush" Value="{DynamicResource TextPrimary}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<Style x:Key="FieldLabel" TargetType="Label">
<Setter Property="Foreground" Value="{DynamicResource TextPrimary}" />
<Setter Property="FontSize" Value="{StaticResource TextBody}" />
<Setter Property="FontWeight" Value="Medium" />
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0,24,0,8" />
</Style>

<Style x:Key="FieldHelp" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource TextSmall}" />
<Setter Property="Foreground" Value="{DynamicResource TextSecondary}" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="Margin" Value="0,8,0,0" />
</Style>

<!-- Kept here rather than in Shared.xaml: it must base on Fluent's TextBox style, which a look file can't see while it loads. -->
<Style x:Key="FieldBox" TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="FontSize" Value="{StaticResource TextBody}" />
<Setter Property="FontSize" Value="{DynamicResource TextBody}" />
<Setter Property="Typography.NumeralAlignment" Value="Tabular" />
</Style>
</Application.Resources>
Expand Down
3 changes: 2 additions & 1 deletion src/ProDHCPServer.App/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ protected override void OnStartup(StartupEventArgs e)
base.OnStartup(e);
var userFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ProDHCPServer");
var settingsStore = new SettingsStore(Path.Combine(userFolder, "settings.json"));
Theme.Apply(settingsStore.Load().Theme);
var startSettings = settingsStore.Load();
Theme.Apply(startSettings.Theme, startSettings.Look);

if (!Elevation.IsAdministrator())
{
Expand Down
93 changes: 93 additions & 0 deletions src/ProDHCPServer.App/Assets/Fonts/OFL-Orbitron.txt
Original file line number Diff line number Diff line change
@@ -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.
Binary file not shown.
Loading
Loading