From 42476140353765365a897f5c07a07dceb336adde Mon Sep 17 00:00:00 2001 From: Jonas Arnold Date: Wed, 24 May 2023 14:48:09 +0200 Subject: [PATCH] implemented first version of console view, newline separator on received data not implemented yet, some changes on the send receive model --- MultiTerm.Core/Helpers/ServiceExtensions.cs | 2 +- MultiTerm.Core/Types/EncodingType.cs | 35 ++++ MultiTerm.Core/ViewModel/ConsoleViewModel.cs | 149 ++++++++++++++++++ .../ViewModel/SendReceiveViewModel.cs | 6 +- MultiTerm.Wpf/View/ConsoleView.xaml | 119 ++++++++++++++ MultiTerm.Wpf/View/ConsoleView.xaml.cs | 48 ++++++ MultiTerm.Wpf/View/SendReceiveView.xaml | 3 +- MultiTerm.Wpf/View/ShellView.xaml | 3 + 8 files changed, 358 insertions(+), 7 deletions(-) create mode 100644 MultiTerm.Core/Types/EncodingType.cs create mode 100644 MultiTerm.Core/ViewModel/ConsoleViewModel.cs create mode 100644 MultiTerm.Wpf/View/ConsoleView.xaml create mode 100644 MultiTerm.Wpf/View/ConsoleView.xaml.cs diff --git a/MultiTerm.Core/Helpers/ServiceExtensions.cs b/MultiTerm.Core/Helpers/ServiceExtensions.cs index 224e8f2..2a3edef 100644 --- a/MultiTerm.Core/Helpers/ServiceExtensions.cs +++ b/MultiTerm.Core/Helpers/ServiceExtensions.cs @@ -15,7 +15,7 @@ public static class ServiceExtensions { // add all implementations to the services collection services.AddTransient(); - // TODO extend + services.AddTransient(); // add a function to the services collection, which is used by the TerminalViewModelFactory // to get a list of all registered implementations of ITerminalViewModel diff --git a/MultiTerm.Core/Types/EncodingType.cs b/MultiTerm.Core/Types/EncodingType.cs new file mode 100644 index 0000000..d0faa54 --- /dev/null +++ b/MultiTerm.Core/Types/EncodingType.cs @@ -0,0 +1,35 @@ +using System.ComponentModel; + +namespace MultiTerm.Core.Types; + +/// +/// Encoding types that are supported by this application. +/// Numbers correspond to the codepage number from the class by Microsoft. +/// +public enum EncodingType +{ + /* Special Case Code Pages */ + + [Description("UTF-16")] + UTF16 = 1200, + [Description("UTF-16 Big Endian")] + UTF16_BE = 1201, + + /* Latin 1 & ASCII Code Pages */ + + [Description("ASCII")] + ASCII = 20127, + [Description("Latin1 (ISO 8859-1)")] + Latin1 = 28591, + + /* Special code pages */ + + [Description("UTF-7")] + UTF7 = 65000, + [Description("UTF-8")] + UTF8 = 65001, + [Description("UTF-32")] + UTF32 = 12000, + [Description("UTF-32 Big Endian")] + UTF32_BE = 12001 +} diff --git a/MultiTerm.Core/ViewModel/ConsoleViewModel.cs b/MultiTerm.Core/ViewModel/ConsoleViewModel.cs new file mode 100644 index 0000000..a12c0aa --- /dev/null +++ b/MultiTerm.Core/ViewModel/ConsoleViewModel.cs @@ -0,0 +1,149 @@ +using Common.AppSettings; +using Common.Logging; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.Messaging; +using MultiTerm.Core.Types; +using MultiTerm.Protocols.Model; +using System.Text; + +namespace MultiTerm.Core.ViewModel; + +public partial class ConsoleViewModel : TerminalViewModel +{ + public override TerminalViewType ViewType => TerminalViewType.Console; + + private readonly ILogger logger; + private Encoding currentEncoding; + + /* settings */ + private readonly Encoding defaultEncoding = Encoding.ASCII; // default encoding instance + private const EncodingType defaultEncodingType = EncodingType.ASCII; // default encoding type + private const int DataMaxLength = 5000; // maximum amount of characters stored int the data textbox + + #region Observable Properties + /// + /// Holds Console content. + /// + [ObservableProperty] + private string data = string.Empty; + + /// + /// Encoding type of the sent and received messages. + /// + [ObservableProperty] + private EncodingType selectedEncodingType = defaultEncodingType; + + /// + /// Holds message that is to be sent next. E.g. currently being typed in. + /// + [ObservableProperty] + private string sendableMessage = string.Empty; + #endregion + + public ConsoleViewModel(IAppSettingsProvider appSettings, IMessenger messenger, ILogger logger) : base(appSettings, messenger) + { + this.logger = logger; + this.currentEncoding = this.GetEncoding(this.SelectedEncodingType); + } + + public override void DisplayNewReceivedData(IEnumerable newData) + { + // extract bytes + var bytes = newData.Select(b => b.Byte).ToArray(); + string newDataDecoded = currentEncoding.GetString(bytes); + // calculate new legth + int newTotalLength = this.Data.Length + newDataDecoded.Length; + // trim current data at the beginning if new length is too long + if (newTotalLength > DataMaxLength) + { + // trim overshoot from start of string + this.Data = this.Data[(newTotalLength - DataMaxLength)..]; + } + // append data + this.Data += newDataDecoded; + } + + /// + /// Command to send a prepared message. + /// + [RelayCommand] + public void Send() + { + // encode + var encodedBytes = this.currentEncoding.GetBytes(this.SendableMessage); + + // send + if (this.SendToCommunicationProtocol(encodedBytes)) + { + // clear if sending was successful + this.SendableMessage = string.Empty; + } + } + + /// + /// Command to clear the data that was received. + /// + [RelayCommand] + public void ClearData() + { + this.Data = string.Empty; + } + + /// + /// Handles changing of encoding type. + /// + /// new value + partial void OnSelectedEncodingTypeChanged(EncodingType value) + { + this.currentEncoding = this.GetEncoding(value); + } + + #region Unused Methods + public override void DisplayNewSentData(IEnumerable newData) + { + // no display of sent data + } + + protected override void ActOnDataDisplayNewlineSeparatorTypeChanged(NewlineSeparatorType newType) + { + // No change when data display newline separator type changed + } + + #endregion + + #region Helpers + /// + /// Returns instance of . + /// If the is not supported or any issue arrived, the is set to ASCII and ASCII is returned. + /// + /// type of encoding + /// encoding instance + private Encoding GetEncoding(EncodingType encodingType) + { + Encoding? encoding; + + try + { + // Encoding Type value corresponds to codepage number, therefore can be get by cast to int + encoding = Encoding.GetEncoding(Convert.ToInt32(encodingType)); + } + catch (Exception) + { + // log exception and set encoding to null + this.logger.LogWarn($"'{nameof(GetEncoding)}()' failed to resolve encoding type {encodingType} (codepage {Convert.ToInt32(encodingType)}). Reverted to default.", nameof(ConsoleViewModel)); + encoding = null; + } + + // failed to get encoding or got null encoding + if (encoding == null) + { + // set selected encoding type to default and return default encoding + this.SelectedEncodingType = defaultEncodingType; + encoding = defaultEncoding; + } + + return encoding!; + } + #endregion +} diff --git a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs index 29d7c7d..fa071f3 100644 --- a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs +++ b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs @@ -51,11 +51,9 @@ public partial class SendReceiveViewModel : TerminalViewModel private void Send() { // send data - bool successfullySent = this.SendToCommunicationProtocol(this.SendableData.GetBytes()); - - if (successfullySent) + if (this.SendToCommunicationProtocol(this.SendableData.GetBytes())) { - // clear textbox + // clear textbox if send was successful this.SendableData.Clear(); } } diff --git a/MultiTerm.Wpf/View/ConsoleView.xaml b/MultiTerm.Wpf/View/ConsoleView.xaml new file mode 100644 index 0000000..e5a6ad6 --- /dev/null +++ b/MultiTerm.Wpf/View/ConsoleView.xaml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +