Edit the function key messages as their file
The messages were twelve boxes in a dialog, which meant no labels, no search-and-pounce set, and no way to read a file somebody published. They are now the file itself: right-click any function key button under the entry window, or the two buttons in Config ▸ Keyer and messages, and the text of an N1MM .mc file opens in a plain editor with Import, Export and Back to the defaults. MessageFile reads that format by N1MM's rules. A line starting with # is a comment; every other line is a label, a comma and the message, with && standing for one & in a label. Which key a line belongs to is decided by where it is and nothing else: the first twelve lines are F1 to F12 while running, the next twelve the same keys while searching, and a file that stops part way through the second twelve leaves the rest sending what they send while running. A blank line in the middle is a key with nothing in it, which is what the manual says; the newline that ends the last line is not, which it does not say, but no .mc file in the world means its final newline as a message. Two things fall out of this. The buttons now say what the file says, and they change when the operator moves between running and searching, so the labels are the documentation N1MM's manual suggests writing them as. And the search set is real: ESM's F2 while searching can be a different message from the one it sends while running, which is how the file was always meant to be used. Settings keep the file text and carry the twelve stored messages into it on first read, with the labels this program used then, so nobody loses what they had typed. The editor is deliberately a text box rather than a grid of fields: importing, exporting and editing are then the same thing, and the comments an operator writes in the file survive being edited here. The telnet window's buttons can use the same editor later. Running it caught two: Save as the default button ate the Enter key that a multi-line editor needs, and the button labels did not follow the move between run and search until they were redrawn rather than only rebuilt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -120,13 +120,18 @@ public sealed partial class EntryWindow
|
||||
_ = SendKeysAsync(lastKeys);
|
||||
}
|
||||
|
||||
private void ShowEsmKeys()
|
||||
/// The buttons say what the file says, which is a different twelve labels
|
||||
/// while running and while searching, and the ones ESM would send next are
|
||||
/// highlighted.
|
||||
private void ShowFunctionKeys()
|
||||
{
|
||||
EsmItem.IsChecked = IsEsmOn;
|
||||
IReadOnlyList<int> keys = IsEsmOn ? NextEsmAction().Keys : [];
|
||||
IReadOnlyList<int> next = IsEsmOn ? NextEsmAction().Keys : [];
|
||||
IReadOnlyList<FunctionKey> keys = Keys();
|
||||
for (int at = 0; at < functionButtons.Count; at++)
|
||||
{
|
||||
functionButtons[at].Classes.Set("esm", keys.Contains(at));
|
||||
functionButtons[at].Content = keys[at].Label.Length > 0 ? keys[at].Label : $"F{at + 1}";
|
||||
functionButtons[at].Classes.Set("esm", next.Contains(at));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Avalonia.Threading;
|
||||
using Nonemm.App.Dialogs;
|
||||
using Nonemm.Core;
|
||||
using Nonemm.Keying;
|
||||
using Nonemm.Session;
|
||||
@@ -15,6 +16,35 @@ public sealed partial class EntryWindow
|
||||
/// actions after `{END}` still run.
|
||||
private static readonly TimeSpan SendingPatience = TimeSpan.FromMinutes(2);
|
||||
|
||||
/// The twelve keys for this radio, which are a different twelve while
|
||||
/// running and while searching, as N1MM's file holds them.
|
||||
private IReadOnlyList<FunctionKey> Keys() =>
|
||||
Messages
|
||||
.For(
|
||||
Logging?.Mode.Category ?? Core.ModeCategory.Cw,
|
||||
session.Settings.CwMessageFile,
|
||||
session.Settings.PhoneMessageFile)
|
||||
.Keys(Logging?.IsRunning ?? false);
|
||||
|
||||
/// Right-clicking a function key button opens the messages for the mode the
|
||||
/// radio is in, which is where import and export live too.
|
||||
private async Task EditMessages()
|
||||
{
|
||||
ModeCategory mode = Logging?.Mode.Category ?? ModeCategory.Cw;
|
||||
string stored = mode == ModeCategory.Phone
|
||||
? session.Settings.PhoneMessageFile
|
||||
: session.Settings.CwMessageFile;
|
||||
if (await new MessagesDialog(mode, stored).ShowDialog<string?>(this) is not { } edited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
session.Save(mode == ModeCategory.Phone
|
||||
? session.Settings with { PhoneMessageFile = edited }
|
||||
: session.Settings with { CwMessageFile = edited });
|
||||
BuildFunctionKeys();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void SendMessage(int index) => _ = SendKeyAsync(index);
|
||||
|
||||
/// Sends one function key's message. The task finishes when the text has
|
||||
@@ -27,10 +57,7 @@ public sealed partial class EntryWindow
|
||||
{
|
||||
return;
|
||||
}
|
||||
string template = Messages.For(
|
||||
Logging.Mode.Category,
|
||||
session.Settings.CwMessages,
|
||||
session.Settings.PhoneMessages)[index];
|
||||
string template = Keys()[index].Message;
|
||||
if (template.Length == 0)
|
||||
{
|
||||
return;
|
||||
@@ -238,10 +265,10 @@ public sealed partial class EntryWindow
|
||||
{
|
||||
return;
|
||||
}
|
||||
string template = Messages.For(
|
||||
other.Mode.Category,
|
||||
session.Settings.CwMessages,
|
||||
session.Settings.PhoneMessages)[number - 1];
|
||||
string template = Messages
|
||||
.For(other.Mode.Category, session.Settings.CwMessageFile, session.Settings.PhoneMessageFile)
|
||||
.Keys(other.IsRunning)[number - 1]
|
||||
.Message;
|
||||
if (template.Length == 0)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -395,7 +395,7 @@ public sealed partial class EntryWindow : Window
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
ShowEsmKeys();
|
||||
ShowFunctionKeys();
|
||||
if (Logging is null)
|
||||
{
|
||||
VerdictText.Text = "";
|
||||
@@ -450,17 +450,26 @@ public sealed partial class EntryWindow : Window
|
||||
|
||||
private void Status(string text) => StatusText.Text = text;
|
||||
|
||||
/// The labels come from the message file, so what the buttons say is what
|
||||
/// the operator wrote. Right-clicking one opens the editor, as it does on
|
||||
/// the telnet window's buttons.
|
||||
private void BuildFunctionKeys()
|
||||
{
|
||||
FunctionKeys.Children.Clear();
|
||||
functionButtons.Clear();
|
||||
for (int at = 0; at < Messages.Keys.Count; at++)
|
||||
for (int at = 0; at < MessageFile.KeyCount; at++)
|
||||
{
|
||||
int index = at;
|
||||
(string key, string label) = Messages.Keys[at];
|
||||
Button button = new() { Content = $"{key} {label}" };
|
||||
Button button = new();
|
||||
button.Classes.Add("fkey");
|
||||
button.Click += (_, _) => RunFunctionKey(index);
|
||||
button.PointerReleased += (_, e) =>
|
||||
{
|
||||
if (e.InitialPressMouseButton == MouseButton.Right)
|
||||
{
|
||||
_ = EditMessages();
|
||||
}
|
||||
};
|
||||
FunctionKeys.Children.Add(button);
|
||||
functionButtons.Add(button);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user