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; namespace MultiTerm.Core.ViewModel; public partial class ShellViewModel : ObservableObject { private const string defaultReceiveNewlineSeparatorAppSettingsKey = "DefaultReceiveNewlineSeparator"; private const string defaultSendNewlineSeparatorAppSettingsKey = "DefaultSendNewlineSeparator"; #region Terminal collection [ObservableProperty] private ObservableCollection 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 private readonly ITerminalViewModelFactory terminalViewModelFactory; private readonly ILogger logger; private readonly IAppSettingsProvider appSettings; public ShellViewModel(ITerminalViewModelFactory terminalViewModelFactory, ILogger logger, IAppSettingsProvider appSettings) { this.terminalViewModelFactory = terminalViewModelFactory; this.logger = logger; this.appSettings = appSettings; // intialize values from app settings this.LoadFromAppSettings(); // TEMP Init this.AppendTerminalWithSelectedViewType(ProtocolType.Serial); } [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(settingValueReceiveNLSep); this.appSettings.TryReadSettingOrAddDefault(defaultSendNewlineSeparatorAppSettingsKey, out string settingValueSendNLSep, NewlineSeparatorType.None.ToString()); this.DefaultSendNewlineSeparator = EnumHelpers.ParseEnum(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 }