Files
Nonemm/src/Nonemm.App/Windows/AvailableWindow.axaml.cs
T
erikbrockoandClaude Sonnet 5.5 29d3a0f016 Name a monospace font list instead of the generic monospace
The generic name only resolves through fontconfig, so on Windows the
windows fell back to the proportional default.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 01:07:47 +00:00

112 lines
3.7 KiB
C#

using Nonemm.App.Theming;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Threading;
using Nonemm.Core;
using Nonemm.Session;
namespace Nonemm.App.Windows;
/// What is left to work, a column per band: the multipliers at the top of each
/// column, then the stations that are only points. Clicking one puts the radio
/// there with the call in the entry window, the same as clicking a spot on the
/// bandmap.
public sealed partial class AvailableWindow : RefreshableWindow
{
private readonly AppSession session;
private readonly Action<Frequency, string> tune;
public AvailableWindow(AppSession session, Action<Frequency, string> tune)
{
this.session = session;
this.tune = tune;
InitializeComponent();
MultsOnlyBox.IsCheckedChanged += (_, _) => Refresh();
session.Bandmap.Changed += (_, _) => Dispatcher.UIThread.Post(Refresh);
Refresh();
}
public override void Refresh()
{
Columns.Children.Clear();
Columns.ColumnDefinitions.Clear();
if (session.Available is null)
{
StatusText.Text = "no contest is open";
return;
}
session.Bandmap.DropOlderThan(DateTime.UtcNow);
bool multsOnly = MultsOnlyBox.IsChecked == true;
List<AvailableStation> stations = session.Available.All()
.Where(s => !multsOnly || s.IsMultiplier)
.ToList();
List<Band> bands = stations
.Select(s => s.Band)
.Distinct()
.OrderBy(b => b.Low.Hertz)
.ToList();
int at = 0;
foreach (Band band in bands)
{
Columns.ColumnDefinitions.Add(new ColumnDefinition(GridLength.Star));
Control column = BuildColumn(band, stations.Where(s => s.Band == band).ToList());
Grid.SetColumn(column, at++);
Columns.Children.Add(column);
}
int mults = stations.Count(s => s.IsMultiplier);
StatusText.Text = stations.Count == 0
? "nothing spotted that is not worked"
: $"{stations.Count} to work · {mults} multipliers";
}
private Control BuildColumn(Band band, IReadOnlyList<AvailableStation> stations)
{
StackPanel panel = new() { Margin = new Avalonia.Thickness(0, 0, 8, 0) };
panel.Children.Add(new TextBlock
{
Text = $"{band.Name} {stations.Count}",
FontSize = 11,
Opacity = 0.7,
Margin = new Avalonia.Thickness(0, 0, 0, 4),
});
foreach (AvailableStation station in stations)
{
panel.Children.Add(Row(station));
}
return panel;
}
private Control Row(AvailableStation station)
{
TextBlock text = new()
{
Text = Label(station),
FontFamily = Fonts.Mono,
FontSize = 13,
Foreground = Verdicts.Colour(station.Verdict),
HorizontalAlignment = HorizontalAlignment.Left,
Cursor = new Cursor(StandardCursorType.Hand),
};
ToolTip.SetTip(text, Tip(station));
text.PointerPressed += (_, _) => tune(station.Spot.Frequency, station.Spot.Call.Text);
return text;
}
private static string Label(AvailableStation station)
{
string call = $"{station.Spot.Frequency.Kilohertz,9:0.0} {station.Spot.Call.Text}";
return station.IsMultiplier ? $"{call} · {station.MultiplierText}" : call;
}
private static string Tip(AvailableStation station)
{
string who = station.Spot.Spotter.Length > 0 ? $" de {station.Spot.Spotter}" : "";
return $"{Verdicts.Describe(station.Verdict)}{who}";
}
}