Give each operator his windows back
The program stored an operator's window positions but never used them at startup: the entry window was not placed and no window was reopened. It now restores the whole screen both at startup and on a change of operator: the windows that operator had open, where he had them, and the ones he did not have closed. The second radio's entry window no longer saves the layout. It has none of the other windows open, so saving from it dropped every window the first one had. Ctrl+O gets six buttons for the operators last at the radio, newest first. One click changes to that operator. The recordings folder is no longer asked for. It is `Wav/<callsign>` under the data folder, which is where N1MM plays them from, so `StoredOperator.WavPath` is gone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0157i7PiZyqBkquxS9A6FTdQ
This commit is contained in:
@@ -37,11 +37,10 @@ public sealed partial class EntryWindow
|
||||
|
||||
private void ChangeTo(Settings settings, StoredOperator wanted)
|
||||
{
|
||||
StoredOperator stored = settings.Operators.FirstOrDefault(o => Is(o, wanted.Callsign)) is { } known
|
||||
? known with { WavPath = wanted.WavPath }
|
||||
StoredOperator stored = settings.Operators.FirstOrDefault(o => Is(o, wanted.Callsign))
|
||||
// a new operator starts with the windows and colours on the screen
|
||||
: wanted with { Theme = settings.Theme, Windows = Layout() };
|
||||
stored = stored with { WavPath = WavFolder(stored) };
|
||||
?? wanted with { Theme = settings.Theme, Windows = Layout() };
|
||||
MakeWavFolder(stored.Callsign);
|
||||
session.Save(settings with
|
||||
{
|
||||
Operators = [.. settings.Operators.Where(o => !Is(o, stored.Callsign)), stored],
|
||||
@@ -56,35 +55,70 @@ public sealed partial class EntryWindow
|
||||
{
|
||||
logging.Operator = stored.Callsign;
|
||||
}
|
||||
foreach (Window window in Placed())
|
||||
{
|
||||
Place(window, stored);
|
||||
}
|
||||
Restore(stored);
|
||||
Status($"operator {stored.Callsign}");
|
||||
}
|
||||
|
||||
/// The operator's recordings folder: the one he named, or `Wav/<callsign>`
|
||||
/// beside the rest of the files, which is where N1MM keeps them. The folder
|
||||
/// is made, so there is somewhere to put the files rather than a path that
|
||||
/// is not there.
|
||||
private string WavFolder(StoredOperator stored)
|
||||
/// Makes `Wav/<callsign>` beside the rest of the files, which is where N1MM
|
||||
/// plays an operator's recordings from, so there is somewhere to put them.
|
||||
private void MakeWavFolder(string callsign)
|
||||
{
|
||||
string folder = stored.WavPath.Trim().Length > 0
|
||||
? stored.WavPath.Trim()
|
||||
: session.Paths.WavFor(stored.Callsign);
|
||||
string folder = session.Paths.WavFor(callsign);
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(folder);
|
||||
}
|
||||
catch (Exception failure) when (failure is IOException or UnauthorizedAccessException)
|
||||
{
|
||||
// a folder on a drive that is not there is still worth keeping: it
|
||||
// is the operator's own setting, and he is the one who fixes it
|
||||
Status($"{folder} could not be made: {failure.Message}");
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
/// Puts the screen back the way this operator left it: the windows he had
|
||||
/// open, where he had them, and the ones he did not have closed. The second
|
||||
/// radio's window is another view of the same screen, so it restores
|
||||
/// nothing.
|
||||
private void Restore(StoredOperator? stored)
|
||||
{
|
||||
if (radioNumber > 1 || stored is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
HashSet<string> wanted = [.. stored.Windows.Select(w => w.Name)];
|
||||
foreach ((string name, Action open) in Openable())
|
||||
{
|
||||
if (wanted.Contains(name))
|
||||
{
|
||||
open();
|
||||
}
|
||||
}
|
||||
foreach (Window window in openWindows.Values.Where(w => !wanted.Contains(w.GetType().Name)).ToList())
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
foreach (Window window in Placed())
|
||||
{
|
||||
Place(window, stored);
|
||||
}
|
||||
}
|
||||
|
||||
/// The windows an operator can have open, under the names they are stored
|
||||
/// as. The call stack window is not one of them: the program opens and
|
||||
/// closes that itself as calls go on and off the stack.
|
||||
private (string Name, Action Open)[] Openable() =>
|
||||
[
|
||||
(nameof(LogWindow), () => _ = Show(() => new LogWindow(session), activate: false)),
|
||||
(nameof(CheckWindow), () => _ = Show(() => new CheckWindow(session), activate: false)),
|
||||
(nameof(BandmapWindow), () => _ = Show(() => new BandmapWindow(session, Tune), activate: false)),
|
||||
(nameof(AvailableWindow), () => _ = Show(() => new AvailableWindow(session, Tune), activate: false)),
|
||||
(nameof(ScoreWindow), () => _ = Show(() => new ScoreWindow(session), activate: false)),
|
||||
(nameof(StatisticsWindow), () => _ = Show(() => new StatisticsWindow(session), activate: false)),
|
||||
(nameof(NetworkStatusWindow), () => _ = Show(() => new NetworkStatusWindow(session), activate: false)),
|
||||
(nameof(GraylineWindow), () => _ = Show(() => new GraylineWindow(session), activate: false)),
|
||||
(nameof(TelnetWindow), () => _ = Show(() => new TelnetWindow(session, Tune), activate: false)),
|
||||
(nameof(DigitalWindow), () => _ = Show(() => new DigitalWindow(session, this, radioNumber), activate: false)),
|
||||
];
|
||||
|
||||
/// Puts a window where this operator last had it. Windows are opened one at
|
||||
/// a time, so each one is placed as it appears rather than all at once.
|
||||
private void Place(Window window, StoredOperator? stored = null)
|
||||
@@ -108,7 +142,9 @@ public sealed partial class EntryWindow
|
||||
/// at the radio. With nobody named there is nowhere to keep them.
|
||||
private Settings WithLayout(Settings settings)
|
||||
{
|
||||
if (Current() is not { } stored)
|
||||
// the second radio's window has none of the others open, so saving from
|
||||
// it would drop every window the first one has
|
||||
if (radioNumber > 1 || Current() is not { } stored)
|
||||
{
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ public sealed partial class EntryWindow : Window
|
||||
StartConnections();
|
||||
BuildEntryBoxes();
|
||||
ShowSecondRadio();
|
||||
Restore(Current());
|
||||
}
|
||||
|
||||
/// A second radio gets its own entry window: the two share one log and one
|
||||
|
||||
Reference in New Issue
Block a user