From c8c53221d3edbe9afe013b72d202beb476e73002 Mon Sep 17 00:00:00 2001 From: Jonas Arnold Date: Wed, 12 Apr 2023 18:24:02 +0200 Subject: [PATCH] added check if SettingsViewModel implements IProtocolSettings in CommunicationProtocolFactory, implemented COM Port readout, fixed functionality of AreEditable for the ProtocolSettingsViewModel, implemented EnumValueToDescriptionConverter using Humanizer package, implemented IntToStringConverter, implemented SerialSettingsView --- .../Factories/CommunicationProtocolFactory.cs | 13 +++- .../IProtocolSettingsViewModel.cs | 5 ++ .../ProtocolSettingsViewModel.cs | 10 ++- .../Serial/SerialProtocolSettingsViewModel.cs | 20 +++++- MultiTerm.Wpf/MultiTerm.Wpf.csproj | 1 + .../EnumValueToEnumDescriptionConverter.cs | 55 ++++++++++++++++ .../ValueConverters/IntToStringConverter.cs | 22 +++++++ MultiTerm.Wpf/View/SendReceiveView.xaml | 2 +- .../View/SettingsView/SerialSettingsView.xaml | 66 ++++++++++++++++++- .../SettingsView/SerialSettingsView.xaml.cs | 29 ++------ 10 files changed, 185 insertions(+), 38 deletions(-) create mode 100644 MultiTerm.Wpf/ValueConverters/EnumValueToEnumDescriptionConverter.cs create mode 100644 MultiTerm.Wpf/ValueConverters/IntToStringConverter.cs diff --git a/MultiTerm.Protocols/Factories/CommunicationProtocolFactory.cs b/MultiTerm.Protocols/Factories/CommunicationProtocolFactory.cs index c0ae114..cc11da5 100644 --- a/MultiTerm.Protocols/Factories/CommunicationProtocolFactory.cs +++ b/MultiTerm.Protocols/Factories/CommunicationProtocolFactory.cs @@ -44,7 +44,8 @@ public class CommunicationProtocolFactory : ICommunicationProtocolFactory } catch (Exception ex) { - throw new NotImplementedException($"'{nameof(CommunicationProtocolFactory)}' cannot create CommunicationProtocol with {nameof(ProtocolType)} {protocolType}", ex); + throw new NotImplementedException($"'{nameof(CommunicationProtocolFactory)}' cannot create " + + $"CommunicationProtocol with {nameof(ProtocolType)} {protocolType}", ex); } // search for correct type of settings View Model implementation by ProtocolType @@ -54,7 +55,15 @@ public class CommunicationProtocolFactory : ICommunicationProtocolFactory } catch (Exception ex) { - throw new NotImplementedException($"'{nameof(CommunicationProtocolFactory)}' cannot create ProtocolSettingsViewModel with {nameof(ProtocolType)} {protocolType}", ex); + throw new NotImplementedException($"'{nameof(CommunicationProtocolFactory)}' cannot create " + + $"ProtocolSettingsViewModel with {nameof(ProtocolType)} {protocolType}", ex); + } + + // check if settings viewmodel also implements IProtocolSettings, which it must + if(settingsViewModel is not IProtocolSettings) + { + throw new NotImplementedException($"'{nameof(CommunicationProtocolFactory)}' cannot create " + + $"CommunicationProtocol since {settingsViewModel.GetType()} does not implement {nameof(IProtocolSettings)}."); } // return the filled up instances diff --git a/MultiTerm.Protocols/IProtocolSettingsViewModel.cs b/MultiTerm.Protocols/IProtocolSettingsViewModel.cs index 9f61bd5..8306773 100644 --- a/MultiTerm.Protocols/IProtocolSettingsViewModel.cs +++ b/MultiTerm.Protocols/IProtocolSettingsViewModel.cs @@ -9,6 +9,11 @@ public interface IProtocolSettingsViewModel /// ProtocolType ProtocolType { get; } + /// + /// Indicates wether the settings can currently be edited. + /// + bool AreEditable { get; } + /// /// Event that is thrown when the user requested to connect to the device with the entered settings. /// Provides protocol settings to use for connection. diff --git a/MultiTerm.Protocols/ProtocolSettingsViewModel.cs b/MultiTerm.Protocols/ProtocolSettingsViewModel.cs index 83c7bc1..af23709 100644 --- a/MultiTerm.Protocols/ProtocolSettingsViewModel.cs +++ b/MultiTerm.Protocols/ProtocolSettingsViewModel.cs @@ -21,15 +21,13 @@ public abstract partial class ProtocolSettingsViewModel : ObservableObject, IPro public abstract ProtocolType ProtocolType { get; } - /// - /// Indicates wether the settings can currently be edited. - /// Initially are editable - /// - public bool AreEditable = true; - [ObservableProperty] private string connectDisconnectButtonText = disconnectedStateButtonText; + [ObservableProperty] + private bool areEditable = true; // initially editable + + public ProtocolSettingsViewModel(IMessenger messenger) { this.messenger = messenger; diff --git a/MultiTerm.Protocols/Serial/SerialProtocolSettingsViewModel.cs b/MultiTerm.Protocols/Serial/SerialProtocolSettingsViewModel.cs index d3014ae..34af6c9 100644 --- a/MultiTerm.Protocols/Serial/SerialProtocolSettingsViewModel.cs +++ b/MultiTerm.Protocols/Serial/SerialProtocolSettingsViewModel.cs @@ -1,5 +1,6 @@ using Common.Messaging; using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using MultiTerm.Protocols.Types; @@ -13,7 +14,7 @@ public partial class SerialProtocolSettingsViewModel : ProtocolSettingsViewModel private int baudRate = 115200; [ObservableProperty] - private string portName = ""; + private string portName; [ObservableProperty] private Parity parity = Parity.None; @@ -27,6 +28,14 @@ public partial class SerialProtocolSettingsViewModel : ProtocolSettingsViewModel [ObservableProperty] private Handshake handshake = Handshake.None; + [ObservableProperty] + private IEnumerable comPorts = new string[] { }; + + [RelayCommand] + private void ReloadComPorts() + { + this.ComPorts = SerialProtocol.GetPortNames(); + } // TODO public string NewlineSequenceOnSend => throw new NotImplementedException(); @@ -34,7 +43,12 @@ public partial class SerialProtocolSettingsViewModel : ProtocolSettingsViewModel public string NewlineOnReceivedSequence => throw new NotImplementedException(); - public SerialProtocolSettingsViewModel(IMessenger messenger) : base(messenger) { } + public SerialProtocolSettingsViewModel(IMessenger messenger) : base(messenger) + { + // load com ports initially + this.ReloadComPorts(); + this.portName = this.ComPorts.FirstOrDefault(string.Empty); + } public bool AreValid() { @@ -48,7 +62,7 @@ public partial class SerialProtocolSettingsViewModel : ProtocolSettingsViewModel this.messenger.Send(new ProtocolSettingsInvalidMessage(nameof(this.PortName), "Must start with COM")); return false; } - if (this.DataBits < 5 && this.DataBits > 8 && this.DataBits != 16) + if ((this.DataBits < 5 || this.DataBits > 8) && this.DataBits != 16) { this.messenger.Send(new ProtocolSettingsInvalidMessage(nameof(this.DataBits), "Must be 5...8 or 16")); return false; diff --git a/MultiTerm.Wpf/MultiTerm.Wpf.csproj b/MultiTerm.Wpf/MultiTerm.Wpf.csproj index dd866f9..abd55f9 100644 --- a/MultiTerm.Wpf/MultiTerm.Wpf.csproj +++ b/MultiTerm.Wpf/MultiTerm.Wpf.csproj @@ -8,6 +8,7 @@ + diff --git a/MultiTerm.Wpf/ValueConverters/EnumValueToEnumDescriptionConverter.cs b/MultiTerm.Wpf/ValueConverters/EnumValueToEnumDescriptionConverter.cs new file mode 100644 index 0000000..74cfb06 --- /dev/null +++ b/MultiTerm.Wpf/ValueConverters/EnumValueToEnumDescriptionConverter.cs @@ -0,0 +1,55 @@ +using Humanizer; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Windows.Data; + +namespace MultiTerm.Wpf.ValueConverters; + +/// +/// Can convert an enum value to a human readable string. Therefore it uses the Description attribute if set. +/// +[ValueConversion(typeof(Enum), typeof(Enum))] +public class EnumValueToEnumDescriptionConverter : IValueConverter +{ + /// + /// Converts complete enum to of . + /// Also converts single enum values to . + /// + /// description or humanized string of the enum value + /// if is another type than an or + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if(value is IEnumerable arrayOfEnumValues) + { + List outputValues = new(); + foreach (var item in arrayOfEnumValues) + { + outputValues.Add(((Enum)item).Humanize()); + } + return outputValues; + } + else if(value is Enum) + { + return ((Enum)value).Humanize(); + } + else + { + throw new NotImplementedException(); + } + } + + /// + /// Converts single string values to Enum of . + /// + /// enum value + /// if value is not a string + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + // guard that it is a string, cannot be a collection + if (value is not string stringValue) { throw new ArgumentException("Can only convert string values."); } + + return stringValue.DehumanizeTo(targetType); + } +} diff --git a/MultiTerm.Wpf/ValueConverters/IntToStringConverter.cs b/MultiTerm.Wpf/ValueConverters/IntToStringConverter.cs new file mode 100644 index 0000000..2829f5e --- /dev/null +++ b/MultiTerm.Wpf/ValueConverters/IntToStringConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace MultiTerm.Wpf.ValueConverters; + +public class IntToStringConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + // guard type + if(value is not int integerVal) { throw new ArgumentException("Can only convert from integer value"); } + return integerVal.ToString(); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + // guard type + if (value is not string stringVal) { throw new ArgumentException("Can only convert from string value"); } + return int.Parse(stringVal); + } +} diff --git a/MultiTerm.Wpf/View/SendReceiveView.xaml b/MultiTerm.Wpf/View/SendReceiveView.xaml index 2bbc142..73e5219 100644 --- a/MultiTerm.Wpf/View/SendReceiveView.xaml +++ b/MultiTerm.Wpf/View/SendReceiveView.xaml @@ -20,7 +20,7 @@ - + diff --git a/MultiTerm.Wpf/View/SettingsView/SerialSettingsView.xaml b/MultiTerm.Wpf/View/SettingsView/SerialSettingsView.xaml index 3cac99e..427e56e 100644 --- a/MultiTerm.Wpf/View/SettingsView/SerialSettingsView.xaml +++ b/MultiTerm.Wpf/View/SettingsView/SerialSettingsView.xaml @@ -3,10 +3,70 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:MultiTerm.Wpf.View.SettingsView" + xmlns:conv="clr-namespace:MultiTerm.Wpf.ValueConverters" + xmlns:serial_protocol="clr-namespace:MultiTerm.Protocols.Serial;assembly=MultiTerm.Protocols" mc:Ignorable="d" d:DesignHeight="50" d:DesignWidth="800"> - - - + +