diff --git a/README.md b/README.md index 9ed426c..e3d5596 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,13 @@ in again while you are running, and `EsmSendsCorrectedCall` sends the call again in front of the last message when you have corrected it — copy `SM3AB`, fix it to `SM3ABC`, and the key sends `SM3ABC TU DL1ABC`. +### The band buttons + +Down the left of the entry window are the bands, CW in one column and phone in +the other, as N1MM has them. A button puts the radio where you left that band +and mode, or at the start of that part of the band the first time. The button +for where the radio is now is marked. + ### Where the other station is Under the entry window is the line N1MM writes there: the beam heading, the diff --git a/src/Nonemm.App/AppSession.cs b/src/Nonemm.App/AppSession.cs index b5035ef..f91e7f0 100644 --- a/src/Nonemm.App/AppSession.cs +++ b/src/Nonemm.App/AppSession.cs @@ -68,6 +68,9 @@ public sealed class AppSession : IDisposable public Bandmap Bandmap { get; } = new(); + /// Where the operator was last on each band and mode, for the band buttons. + public BandMemory BandMemory { get; } = new(); + /// The contest in progress: one log and one score, however many radios. public ContestSession? Logging { get; private set; } diff --git a/src/Nonemm.App/Windows/EntryWindow.Bands.cs b/src/Nonemm.App/Windows/EntryWindow.Bands.cs new file mode 100644 index 0000000..14bfe69 --- /dev/null +++ b/src/Nonemm.App/Windows/EntryWindow.Bands.cs @@ -0,0 +1,89 @@ +using Avalonia.Controls; +using Nonemm.Core; + +namespace Nonemm.App.Windows; + +/// The band buttons down the left of the window, CW in one column and phone in +/// the other, as N1MM has them. A button puts the radio where the operator left +/// that band, or at the start of that part of it. +public sealed partial class EntryWindow +{ + private static readonly IReadOnlyList BandColumn = + [ + Bands.Band160M, Bands.Band80M, Bands.Band40M, Bands.Band30M, Bands.Band20M, + Bands.Band17M, Bands.Band15M, Bands.Band12M, Bands.Band10M, Bands.Band6M, + ]; + + private readonly List<(Band Band, ModeCategory Mode, Button Button)> bandButtons = []; + + private void BuildBandButtons() + { + BandButtons.Children.Clear(); + BandButtons.RowDefinitions.Clear(); + bandButtons.Clear(); + BandButtons.RowDefinitions.Add(new RowDefinition(GridLength.Auto)); + Heading("CW", 0); + Heading("PH", 1); + for (int at = 0; at < BandColumn.Count; at++) + { + BandButtons.RowDefinitions.Add(new RowDefinition(GridLength.Auto)); + Add(BandColumn[at], ModeCategory.Cw, at + 1, column: 0); + Add(BandColumn[at], ModeCategory.Phone, at + 1, column: 1); + } + } + + private void Heading(string text, int column) + { + TextBlock heading = new() + { + Text = text, + FontSize = 10, + Opacity = 0.7, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + Margin = new Avalonia.Thickness(0, 0, 2, 2), + }; + Grid.SetColumn(heading, column); + BandButtons.Children.Add(heading); + } + + private void Add(Band band, ModeCategory mode, int row, int column) + { + Button button = new() { Content = band.MegahertzLabel.ToString("0.###") }; + button.Classes.Add("band"); + button.Click += (_, _) => MoveToBand(band, mode); + Grid.SetRow(button, row); + Grid.SetColumn(button, column); + BandButtons.Children.Add(button); + bandButtons.Add((band, mode, button)); + } + + private void MoveToBand(Band band, ModeCategory mode) + { + if (Logging is null) + { + return; + } + Frequency where = session.BandMemory.Where(band, mode, session.BandPlan); + Mode wanted = mode == ModeCategory.Phone ? Modes.ForSideband(where) : Modes.Cw; + Logging.Tune(where, wanted); + _ = session.Radio?.TuneAsync(where); + boxes[0].Focus(); + Refresh(); + } + + /// The button for the band and mode the radio is on is marked, and the + /// frequency is kept so the button goes back to it. + private void ShowBandButtons() + { + if (Logging is null) + { + return; + } + session.BandMemory.Remember(Logging.Frequency, Logging.Mode); + Band? here = Bands.ForFrequency(Logging.Frequency); + foreach ((Band band, ModeCategory mode, Button button) in bandButtons) + { + button.Classes.Set("here", band == here && mode == Logging.Mode.Category); + } + } +} diff --git a/src/Nonemm.App/Windows/EntryWindow.axaml b/src/Nonemm.App/Windows/EntryWindow.axaml index 0af9476..83e982f 100644 --- a/src/Nonemm.App/Windows/EntryWindow.axaml +++ b/src/Nonemm.App/Windows/EntryWindow.axaml @@ -17,6 +17,17 @@ + +