Two themes, and one place that decides what colour a station is
Colours came from static brushes scattered over the windows. They now come from a Theme, and everything that paints a station, a spot or a log row asks Themes.Current as it paints, so changing the theme changes every window without reopening it. light is N1MM's own palette, read out of ApplicationStyles: the pale blue behind a window, ivory on a button, white boxes, and the four colours a station is painted in. dark is the same states in colours for a dark screen, which is roughly what the program looked like before. Config > Manage Skins, Colors and Fonts picks one, under N1MM's name for the same dialog, and shows what each theme paints a callsign. The choice is kept in settings.json as Theme, and light is the default. The window chrome follows through resources the Fluent controls read, so a text box and a button take the theme's colours in every state. Fonts and skins are not part of it. Looked at under Xvfb in both themes: the entry window, the theme dialog, and the log window with its rows still coloured by what each contact was worth. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Nonemm.App.Theming;
|
||||
using Nonemm.Core;
|
||||
using Nonemm.Session;
|
||||
|
||||
@@ -22,13 +23,13 @@ public sealed partial class MessagesDialog : Window
|
||||
|
||||
/// The three banks of function keys, coloured so the editor shows which
|
||||
/// line is which key.
|
||||
private static readonly IBrush Blue = new SolidColorBrush(Color.FromRgb(0x29, 0x80, 0xB9));
|
||||
private static IBrush Blue => Themes.Brush(Themes.Current.Worth);
|
||||
|
||||
private static readonly IBrush Green = new SolidColorBrush(Color.FromRgb(0x27, 0xAE, 0x60));
|
||||
private static IBrush Green => Themes.Brush(Themes.Current.Multipliers);
|
||||
|
||||
private static readonly IBrush Red = new SolidColorBrush(Color.FromRgb(0xC0, 0x39, 0x2B));
|
||||
private static IBrush Red => Themes.Brush(Themes.Current.Multiplier);
|
||||
|
||||
private static readonly IBrush Grey = new SolidColorBrush(Color.FromRgb(0x7F, 0x8C, 0x8D));
|
||||
private static IBrush Grey => Themes.Brush(Themes.Current.Dupe);
|
||||
|
||||
private readonly ModeCategory mode;
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Nonemm.App.Dialogs.ThemeDialog"
|
||||
Title="Colors" Width="360" SizeToContent="Height"
|
||||
WindowStartupLocation="CenterOwner" CanResize="False">
|
||||
<DockPanel Margin="14">
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Center"
|
||||
Spacing="30" Margin="0,14,0,0">
|
||||
<Button Content="Ok" Width="85" HorizontalContentAlignment="Center"
|
||||
Click="OnOk" IsDefault="True" />
|
||||
<Button Content="Cancel" Width="85" HorizontalContentAlignment="Center"
|
||||
Click="OnCancel" IsCancel="True" />
|
||||
</StackPanel>
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Colors" FontSize="11" />
|
||||
<ComboBox Name="ThemeBox" HorizontalAlignment="Stretch" SelectionChanged="OnPicked" />
|
||||
<TextBlock Name="AboutText" FontSize="11" TextWrapping="Wrap" />
|
||||
<ItemsControl Name="Swatches" Margin="0,4,0,0">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,65 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Nonemm.App.Theming;
|
||||
|
||||
namespace Nonemm.App.Dialogs;
|
||||
|
||||
/// Which colours the program paints with. N1MM keeps skins, colours and fonts
|
||||
/// in one place; this picks between the themes that ship with the program and
|
||||
/// shows what each one paints a station.
|
||||
public sealed partial class ThemeDialog : Window
|
||||
{
|
||||
public ThemeDialog(string current)
|
||||
{
|
||||
InitializeComponent();
|
||||
ThemeBox.ItemsSource = Themes.All.Select(Label).ToList();
|
||||
ThemeBox.SelectedIndex = Math.Max(0, Themes.All.ToList().FindIndex(t => t.Name == Themes.Find(current).Name));
|
||||
}
|
||||
|
||||
private Theme Picked => Themes.All[Math.Max(0, ThemeBox.SelectedIndex)];
|
||||
|
||||
private static string Label(Theme theme) => theme.Name switch
|
||||
{
|
||||
"light" => "Light — N1MM's own colours",
|
||||
"dark" => "Dark — for operating at night",
|
||||
_ => theme.Name,
|
||||
};
|
||||
|
||||
private void OnPicked(object? sender, SelectionChangedEventArgs e) => ShowSwatches();
|
||||
|
||||
private void ShowSwatches()
|
||||
{
|
||||
Theme theme = Picked;
|
||||
AboutText.Text = "What a station is painted in the callsign box, left to right: worth " +
|
||||
"working, one new multiplier, more than one, a dupe.";
|
||||
Swatches.ItemsSource = new[]
|
||||
{
|
||||
Swatch(theme.Worth, theme.FieldBackground),
|
||||
Swatch(theme.Multiplier, theme.FieldBackground),
|
||||
Swatch(theme.Multipliers, theme.FieldBackground),
|
||||
Swatch(theme.Dupe, theme.FieldBackground),
|
||||
};
|
||||
}
|
||||
|
||||
private static Border Swatch(Color text, Color background) => new()
|
||||
{
|
||||
Background = new SolidColorBrush(background),
|
||||
Width = 66,
|
||||
Height = 26,
|
||||
Margin = new Avalonia.Thickness(0, 0, 6, 6),
|
||||
Child = new TextBlock
|
||||
{
|
||||
Text = "OM3KFF",
|
||||
FontSize = 11,
|
||||
Foreground = new SolidColorBrush(text),
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
},
|
||||
};
|
||||
|
||||
private void OnOk(object? sender, RoutedEventArgs e) => Close(Picked.Name);
|
||||
|
||||
private void OnCancel(object? sender, RoutedEventArgs e) => Close(null);
|
||||
}
|
||||
Reference in New Issue
Block a user