Multiprocotol Terminalprogram (BAT)
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.
MultiTerm/MultiTerm.Core/ViewModel/ShellViewModel.cs

189 lines
7.0 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);
// TEMP Init
//this.AppendTerminalWithSelectedViewType(ProtocolType.Serial);
}
/// <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
}