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.
159 lines
5.4 KiB
159 lines
5.4 KiB
using Common.AppSettings;
|
|
using Common.Logging;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
using MultiTerm.Core.Model;
|
|
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
|
|
/// <summary>
|
|
/// Holds Console content.
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private string data = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Encoding type of the sent and received messages.
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private EncodingType selectedEncodingType = defaultEncodingType;
|
|
|
|
/// <summary>
|
|
/// Holds message that is to be sent next. E.g. currently being typed in.
|
|
/// </summary>
|
|
[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<ExtendedByte> 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command to send a prepared message.
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public void Send()
|
|
{
|
|
// encode
|
|
var encodedBytes = this.currentEncoding.GetBytes(this.SendableMessage);
|
|
|
|
// send
|
|
if (this.SendToCommunicationProtocol(encodedBytes))
|
|
{
|
|
// add to history
|
|
this.AddToSendHistory(new StringHistoryElement(this.SendableMessage));
|
|
// clear if sending was successful
|
|
this.SendableMessage = string.Empty;
|
|
}
|
|
}
|
|
|
|
protected override void HandleInsertElementFromHistory(object element)
|
|
{
|
|
if(element is not StringHistoryElement elementString) { throw new Exception($"'{HandleInsertElementFromHistory}()' in {nameof(ConsoleViewModel)} got wrong type of element. Got Type: {element.GetType()}"); }
|
|
// overwrite sendable message with history element
|
|
this.SendableMessage = elementString.Text;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command to clear the data that was received.
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public void ClearData()
|
|
{
|
|
this.Data = string.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles changing of encoding type.
|
|
/// </summary>
|
|
/// <param name="value">new value</param>
|
|
partial void OnSelectedEncodingTypeChanged(EncodingType value)
|
|
{
|
|
this.currentEncoding = this.GetEncoding(value);
|
|
}
|
|
|
|
#region Unused Methods
|
|
public override void DisplayNewSentData(IEnumerable<ExtendedByte> newData)
|
|
{
|
|
// no display of sent data
|
|
}
|
|
|
|
protected override void ActOnDataDisplayNewlineSeparatorTypeChanged(NewlineSeparatorType newType)
|
|
{
|
|
// No change when data display newline separator type changed
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helpers
|
|
/// <summary>
|
|
/// Returns <see cref="Encoding"/> instance of <paramref name="encodingType"/>.
|
|
/// If the <paramref name="encodingType"/> is not supported or any issue arrived, the <see cref="SelectedEncodingType"/> is set to ASCII and ASCII <see cref="Encoding"/> is returned.
|
|
/// </summary>
|
|
/// <param name="encodingType">type of encoding</param>
|
|
/// <returns>encoding instance</returns>
|
|
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
|
|
}
|
|
|