Lay the menu bar out the way N1MM lays it out, and fill in the Edit menu
The menu tree comes from N1MM's EntryWindow.Designer.cs: File, Edit, View, Tools, Config, Window, with the items under the names N1MM gives them. The window list moved out of View into Window; the call history file moved from Config into File > Import. Ctrl+W, Ctrl+L and Ctrl+M now work, so the keys printed in the menu are real. Two commands that had no menu item before: the CW and SSB function key definitions, and the QTC setup area. The rest of the Edit menu: - Ctrl+N asks for a note and puts it in the comment of the contact in the boxes, or of the last logged contact when nothing is typed. - Edit Current Contact opens the Edit Contact form over what is typed but not logged. Update hands the values back to the entry boxes. - Ctrl+Q and Ctrl+A load a logged contact into the boxes and paint them pale yellow. Enter writes the change back, Esc puts back what was being typed, and stepping forward past the newest contact leaves quick edit. - Ctrl+U raises the received serial, or a numeric exchange box when the contest has no serial. - Ctrl+F shows the call being typed in the log window, then the next contact with that call. RadioPosition is now OperatingPosition: it is the operator at one radio, not a place on a band. Looked at under Xvfb on a 3775-contact log: quick edit back and forward, Esc, the note dialog, find, and Edit Current Contact putting a zone back into the entry boxes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,9 +5,9 @@
|
||||
WindowStartupLocation="CenterOwner" CanResize="False">
|
||||
<DockPanel Margin="14">
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Spacing="6" Margin="0,12,0,0">
|
||||
<Button Content="◀" Click="OnPrevious" ToolTip.Tip="Previous contact" />
|
||||
<Button Content="▶" Click="OnNext" ToolTip.Tip="Next contact" />
|
||||
<Button Content="Delete" Click="OnDelete" />
|
||||
<Button Name="PreviousButton" Content="◀" Click="OnPrevious" ToolTip.Tip="Previous contact" />
|
||||
<Button Name="NextButton" Content="▶" Click="OnNext" ToolTip.Tip="Next contact" />
|
||||
<Button Name="DeleteButton" Content="Delete" Click="OnDelete" />
|
||||
<Panel Width="120" />
|
||||
<Button Content="Close" Click="OnClose" IsCancel="True" />
|
||||
<Button Content="Update" Click="OnUpdate" IsDefault="True" />
|
||||
|
||||
@@ -34,18 +34,42 @@ public sealed partial class EditContactDialog : Window
|
||||
private readonly Dictionary<QsoField, TextBox> boxes = [];
|
||||
private int at;
|
||||
|
||||
/// Set when the dialog holds the contact still in the entry boxes rather
|
||||
/// than one from the log. Update hands it back instead of saving it, and
|
||||
/// there is nothing to step to or delete.
|
||||
private readonly Qso? inProgress;
|
||||
|
||||
public EditContactDialog(ContestSession logging, string contactId)
|
||||
{
|
||||
this.logging = logging;
|
||||
InitializeComponent();
|
||||
BuildFields(ContactFields, ContactRow);
|
||||
BuildFields(ExchangeFields, ExchangeRow);
|
||||
AddWideField(ExchangeFields, QsoField.Comment);
|
||||
Build();
|
||||
at = Math.Max(0, IndexOf(contactId));
|
||||
Display(Current);
|
||||
}
|
||||
|
||||
private Qso Current => logging.Log.Qsos[at];
|
||||
/// N1MM's Edit Current Contact: the same form over what is typed but not
|
||||
/// logged yet. Closes with the edited contact, or null when it is cancelled.
|
||||
public EditContactDialog(ContestSession logging, Qso inProgress)
|
||||
{
|
||||
this.logging = logging;
|
||||
this.inProgress = inProgress;
|
||||
InitializeComponent();
|
||||
Build();
|
||||
PreviousButton.IsVisible = false;
|
||||
NextButton.IsVisible = false;
|
||||
DeleteButton.IsVisible = false;
|
||||
Display(Current);
|
||||
}
|
||||
|
||||
private void Build()
|
||||
{
|
||||
BuildFields(ContactFields, ContactRow);
|
||||
BuildFields(ExchangeFields, ExchangeRow);
|
||||
AddWideField(ExchangeFields, QsoField.Comment);
|
||||
}
|
||||
|
||||
private Qso Current => inProgress ?? logging.Log.Qsos[at];
|
||||
|
||||
private int IndexOf(string id)
|
||||
{
|
||||
@@ -113,7 +137,9 @@ public sealed partial class EditContactDialog : Window
|
||||
}
|
||||
RunBox.IsChecked = qso.IsRunQso;
|
||||
ClaimedBox.IsChecked = qso.IsClaimed;
|
||||
PositionText.Text = $"contact {at + 1} of {logging.Log.Qsos.Count}";
|
||||
PositionText.Text = inProgress is null
|
||||
? $"contact {at + 1} of {logging.Log.Qsos.Count}"
|
||||
: "the contact in the entry boxes, not logged yet";
|
||||
DerivedText.Text =
|
||||
$"band {qso.Band?.Name ?? "off band"} · continent {Or(qso.Continent)} · " +
|
||||
$"station prefix {Or(qso.StationPrefix)} · {qso.Points} points · " +
|
||||
@@ -155,11 +181,17 @@ public sealed partial class EditContactDialog : Window
|
||||
}
|
||||
return false;
|
||||
}
|
||||
logging.Update(edit.Result with
|
||||
Qso changed = edit.Result with
|
||||
{
|
||||
IsRunQso = RunBox.IsChecked == true,
|
||||
IsClaimed = ClaimedBox.IsChecked == true,
|
||||
});
|
||||
};
|
||||
if (inProgress is not null)
|
||||
{
|
||||
Close(changed);
|
||||
return true;
|
||||
}
|
||||
logging.Update(changed);
|
||||
// editing the time re-sorts the log, so find the contact again
|
||||
at = IndexOf(before.Id);
|
||||
Display(Current);
|
||||
@@ -228,6 +260,11 @@ public sealed partial class EditContactDialog : Window
|
||||
|
||||
private async void OnClose(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (inProgress is not null)
|
||||
{
|
||||
Close(null);
|
||||
return;
|
||||
}
|
||||
if (await KeepChanges())
|
||||
{
|
||||
Close();
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Nonemm.App.Dialogs.NoteDialog"
|
||||
Title="Current Contact" Width="380" SizeToContent="Height"
|
||||
WindowStartupLocation="CenterOwner" CanResize="False">
|
||||
<DockPanel Margin="14">
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right"
|
||||
Spacing="6" Margin="0,12,0,0">
|
||||
<Button Content="Cancel" Click="OnCancel" IsCancel="True" />
|
||||
<Button Content="Ok" Click="OnOk" IsDefault="True" />
|
||||
</StackPanel>
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock Text="Enter note (comment)" />
|
||||
<TextBox Name="NoteBox" MaxLength="60" />
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,25 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace Nonemm.App.Dialogs;
|
||||
|
||||
/// The note N1MM's Ctrl+N asks for. It goes in the contact's comment, and N1MM
|
||||
/// keeps notes to 60 characters.
|
||||
public sealed partial class NoteDialog : Window
|
||||
{
|
||||
public NoteDialog(string title, string note)
|
||||
{
|
||||
InitializeComponent();
|
||||
Title = title;
|
||||
NoteBox.Text = note;
|
||||
Opened += (_, _) =>
|
||||
{
|
||||
NoteBox.Focus();
|
||||
NoteBox.CaretIndex = NoteBox.Text?.Length ?? 0;
|
||||
};
|
||||
}
|
||||
|
||||
private void OnOk(object? sender, RoutedEventArgs e) => Close(NoteBox.Text ?? "");
|
||||
|
||||
private void OnCancel(object? sender, RoutedEventArgs e) => Close(null);
|
||||
}
|
||||
Reference in New Issue
Block a user