Walk the entry boxes the way N1MM walks them

Space and tab were moving through every box in turn, and since the name and
comment boxes arrived, into those as well. N1MM does neither.

Its EntryWindow.NextTab walks the boxes the contest declares plus the callsign,
skips SNTText and RCVText, and comes round to the callsign from the last one.
For CQ WW that means the callsign and the zone, and nothing else: the entry
items are SNTText, RCVText and CQZoneText, and the first two are stepped over.
So this steps over report boxes as well, and the name and comment boxes are out
of the walk, as they are out of N1MM's.

Skipping the reports only works because they are filled in. N1MM's TabPressed
puts the report for the mode into an empty Snt or Rcv box when the callsign box
is left, and FillReports does the same here: 599 on CW and digital, 59 on phone.
A report the operator typed is left alone, and a report box is still there to
click when a contact is not 599.

The test that said space walks every box in turn now says it steps over the
report, which is the behaviour that was asked for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-28 10:04:48 +00:00
parent 7c2a2ed768
commit f102e0a304
5 changed files with 103 additions and 40 deletions

View File

@@ -311,7 +311,7 @@ public sealed partial class EntryWindow : Window
e.Handled = true;
session.SwapRadio();
break;
case Key.Tab when FocusedIsEntryBox() || FocusedIsNoteBox():
case Key.Tab when FocusedIsEntryBox():
e.Handled = true;
MoveFocus(forward: !e.KeyModifiers.HasFlag(KeyModifiers.Shift));
break;
@@ -394,40 +394,24 @@ public sealed partial class EntryWindow : Window
boxes[0].Focus();
}
/// Tab and space walk the callsign box, the exchange boxes, then the name
/// and comment boxes, and round again.
/// Tab and space walk the callsign box and the exchange boxes, and round
/// again, as N1MM's do. The name and comment boxes are not in the walk,
/// because they are not part of the exchange; they are there for the mouse.
private void MoveFocus(bool forward)
{
if (Logging is null || boxes.Count == 0)
{
return;
}
List<TextBox> notes = [.. new[] { nameBox, commentBox }.OfType<TextBox>()];
int inNotes = notes.FindIndex(box => box.IsFocused);
if (inNotes >= 0)
{
int next = inNotes + (forward ? 1 : -1);
if (next >= 0 && next < notes.Count)
{
notes[next].Focus();
return;
}
Logging.Entry.FocusOn(forward ? 0 : Logging.Entry.FieldCount - 1);
FocusEntryBox();
return;
}
if (forward && notes.Count > 0 && Logging.Entry.Focus == Logging.Entry.FieldCount - 1)
{
notes[0].Focus();
return;
}
if (forward)
{
// leaving the callsign box is the moment the call is settled, which
// is when the call history can say what the exchange will be
// is when the call history can say what the exchange will be and
// the reports can be filled in
if (Logging.Entry.Focus == 0)
{
bool filled = Logging.FillFromHistory();
bool filled = Logging.FillReports();
filled |= Logging.FillFromHistory();
filled |= FillNameFromHistory();
if (filled)
{
@@ -472,8 +456,6 @@ public sealed partial class EntryWindow : Window
private bool FocusedIsEntryBox() => boxes.Any(b => b.IsFocused);
private bool FocusedIsNoteBox() => nameBox?.IsFocused == true || commentBox?.IsFocused == true;
/// The buttons N1MM puts under its function keys. Each one does what its
/// key does, so there is one place deciding what happens.
private void OnStopSending(object? sender, RoutedEventArgs e)