You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
6.9 KiB
186 lines
6.9 KiB
using Common.AppSettings;
|
|
using Common.Logging;
|
|
using Common.Helpers;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using MultiTerm.Core.Factories;
|
|
using System.Collections.ObjectModel;
|
|
using MultiTerm.Core.Types;
|
|
using MultiTerm.Protocols.Types;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
using Common.Messaging;
|
|
using System.Timers;
|
|
|
|
namespace MultiTerm.Core.ViewModel;
|
|
|
|
public partial class ShellViewModel : ObservableObject, IRecipient<IUserInterfaceMessage>
|
|
{
|
|
private const string defaultReceiveNewlineSeparatorAppSettingsKey = "DefaultReceiveNewlineSeparator";
|
|
private const string defaultSendNewlineSeparatorAppSettingsKey = "DefaultSendNewlineSeparator";
|
|
private const int statusBarMessageDurationMs = 12000; // how long the status bar shall be displayed
|
|
|
|
#region Terminal collection
|
|
[ObservableProperty]
|
|
private ObservableCollection<ITerminalViewModel> terminalViewModels = new();
|
|
|
|
[ObservableProperty]
|
|
private ITerminalViewModel? selectedTerminalViewModel;
|
|
#endregion
|
|
|
|
#region Settings Menu Bar
|
|
[ObservableProperty]
|
|
private NewlineSeparatorType defaultReceiveNewlineSeparator = NewlineSeparatorType.None;
|
|
|
|
[ObservableProperty]
|
|
private NewlineSeparatorType defaultSendNewlineSeparator = NewlineSeparatorType.None;
|
|
#endregion
|
|
|
|
#region New Terminal Context Menu
|
|
[ObservableProperty]
|
|
private TerminalViewType selectedTerminalViewType = TerminalViewType.SendReceive;
|
|
#endregion
|
|
|
|
#region Status Bar
|
|
private System.Timers.Timer? statusBarMessageTimer;
|
|
private const int statusBarMessageTimerIntervalMs = 100; // After x milliseconds the timer shall be called
|
|
|
|
[ObservableProperty]
|
|
private string statusBarMessage = "";
|
|
|
|
[ObservableProperty]
|
|
private MessageImportance statusBarMessageImportance = MessageImportance.Normal;
|
|
|
|
[ObservableProperty]
|
|
private double statusBarMessageDurationPercentage = 0;
|
|
#endregion
|
|
|
|
private readonly ITerminalViewModelFactory terminalViewModelFactory;
|
|
private readonly ILogger logger;
|
|
private readonly IAppSettingsProvider appSettings;
|
|
private readonly IMessenger messenger;
|
|
|
|
public ShellViewModel(ITerminalViewModelFactory terminalViewModelFactory, ILogger logger, IAppSettingsProvider appSettings, IMessenger messenger)
|
|
{
|
|
this.terminalViewModelFactory = terminalViewModelFactory;
|
|
this.logger = logger;
|
|
this.appSettings = appSettings;
|
|
this.messenger = messenger;
|
|
|
|
// intialize values from app settings
|
|
this.LoadFromAppSettings();
|
|
|
|
// register to messages
|
|
this.messenger.Register(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Forcefully close all <see cref="TerminalViewModel"/>s.
|
|
/// </summary>
|
|
public void Teardown()
|
|
{
|
|
// iterate through all terminals
|
|
foreach (ITerminalViewModel terminal in this.TerminalViewModels)
|
|
{
|
|
// forcefully close
|
|
terminal.ForceClose();
|
|
// do not remove from collection, otherwise the collection was changed
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void AppendTerminalWithSelectedViewType(ProtocolType protocolType)
|
|
{
|
|
this.logger.LogInfo($"Adding new Terminal with ViewType '{this.SelectedTerminalViewType}' and ProtocolType '{protocolType}'", nameof(ShellViewModel));
|
|
this.AppendConfiguredTerminal(this.terminalViewModelFactory.Create(this.SelectedTerminalViewType, protocolType));
|
|
}
|
|
|
|
private void AppendConfiguredTerminal(ITerminalViewModel? newTerminal)
|
|
{
|
|
// guard null value
|
|
if(newTerminal == null) { return; }
|
|
|
|
// add to collection and register closing event handler
|
|
this.TerminalViewModels.Add(newTerminal);
|
|
newTerminal.ClosingEvent += Terminal_ClosingEvent;
|
|
|
|
// set as selected
|
|
this.SelectedTerminalViewModel = newTerminal;
|
|
}
|
|
|
|
private void Terminal_ClosingEvent(object? sender, EventArgs e)
|
|
{
|
|
if(sender is not ITerminalViewModel tvm) { throw new ArgumentException($"{nameof(Terminal_ClosingEvent)} failed to convert sender to {nameof(ITerminalViewModel)}"); }
|
|
this.RemoveTerminal(tvm);
|
|
}
|
|
|
|
private void RemoveTerminal(ITerminalViewModel terminalToRemove)
|
|
{
|
|
// guard null value
|
|
if(terminalToRemove == null) { return; }
|
|
|
|
this.TerminalViewModels.Remove(terminalToRemove);
|
|
}
|
|
|
|
#region App Settings handling
|
|
private void LoadFromAppSettings()
|
|
{
|
|
// initialize newline separators from persistent settings
|
|
this.appSettings.TryReadSettingOrAddDefault(defaultReceiveNewlineSeparatorAppSettingsKey, out string settingValueReceiveNLSep, NewlineSeparatorType.None.ToString());
|
|
this.DefaultReceiveNewlineSeparator = EnumHelpers.ParseEnum<NewlineSeparatorType>(settingValueReceiveNLSep);
|
|
this.appSettings.TryReadSettingOrAddDefault(defaultSendNewlineSeparatorAppSettingsKey, out string settingValueSendNLSep, NewlineSeparatorType.None.ToString());
|
|
this.DefaultSendNewlineSeparator = EnumHelpers.ParseEnum<NewlineSeparatorType>(settingValueSendNLSep);
|
|
}
|
|
|
|
partial void OnDefaultReceiveNewlineSeparatorChanged(NewlineSeparatorType value)
|
|
{
|
|
// update setting in app settings
|
|
this.appSettings.WriteSetting(defaultReceiveNewlineSeparatorAppSettingsKey, value.ToString());
|
|
}
|
|
|
|
partial void OnDefaultSendNewlineSeparatorChanged(NewlineSeparatorType value)
|
|
{
|
|
// update setting in app settings
|
|
this.appSettings.WriteSetting(defaultSendNewlineSeparatorAppSettingsKey, value.ToString());
|
|
}
|
|
#endregion
|
|
|
|
#region Messaging handling
|
|
public void Receive(IUserInterfaceMessage message)
|
|
{
|
|
// reset percentage
|
|
this.StatusBarMessageDurationPercentage = 100;
|
|
|
|
// display message
|
|
this.StatusBarMessage = message.ToString();
|
|
this.StatusBarMessageImportance = message.Importance;
|
|
|
|
// start timer
|
|
if(this.statusBarMessageTimer == null)
|
|
{
|
|
this.statusBarMessageTimer = new System.Timers.Timer(statusBarMessageTimerIntervalMs);
|
|
this.statusBarMessageTimer.Elapsed += StatusBarMessageTimer_Elapsed;
|
|
this.statusBarMessageTimer.AutoReset = true; // restart after elapsed
|
|
this.statusBarMessageTimer.Enabled = true; // start timer
|
|
}
|
|
}
|
|
|
|
private void StatusBarMessageTimer_Elapsed(object? sender, ElapsedEventArgs e)
|
|
{
|
|
float differencePercentage = (statusBarMessageDurationMs / statusBarMessageTimerIntervalMs) / 100;
|
|
|
|
// if not yet done
|
|
if(this.StatusBarMessageDurationPercentage - differencePercentage > 0)
|
|
{
|
|
this.StatusBarMessageDurationPercentage -= differencePercentage;
|
|
return;
|
|
}
|
|
|
|
// clear message and kill timer when finished
|
|
this.StatusBarMessage = "";
|
|
this.StatusBarMessageDurationPercentage = 0;
|
|
this.statusBarMessageTimer!.Enabled = false;
|
|
this.statusBarMessageTimer.Dispose();
|
|
this.statusBarMessageTimer = null;
|
|
}
|
|
#endregion
|
|
}
|
|
|