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 tune; public AvailableWindow(AppSession session, Action 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 stations = session.Available.All() .Where(s => !multsOnly || s.IsMultiplier) .ToList(); List 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 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 = new FontFamily("monospace"), 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}"; } }