From 3539ecb0dafbdbb6350dd2058f5c846465a08fef Mon Sep 17 00:00:00 2001 From: Jonas Arnold Date: Wed, 24 May 2023 17:21:51 +0200 Subject: [PATCH] implemented first version of send history, implemented IHistoryElement, StringHistoryElement, ICloneable for MultiFormatString, fixed MultiFormatTextBox not resetting when overwritten --- MultiTerm.Core/Model/IHistoryElement.cs | 14 ++++ MultiTerm.Core/Model/MultiFormatString.cs | 17 ++++- MultiTerm.Core/Model/StringHistoryElement.cs | 23 +++++++ MultiTerm.Core/ViewModel/ConsoleViewModel.cs | 10 +++ .../ViewModel/SendReceiveViewModel.cs | 10 +++ MultiTerm.Core/ViewModel/TerminalViewModel.cs | 42 ++++++++++++ .../MultiFormatTextBox/MultiFormatTextBox.cs | 8 ++- MultiTerm.Wpf/Assets/mdi-import.png | Bin 0 -> 506 bytes MultiTerm.Wpf/MultiTerm.Wpf.csproj | 2 + MultiTerm.Wpf/View/ShellView.xaml | 61 +++++++++++++++--- 10 files changed, 176 insertions(+), 11 deletions(-) create mode 100644 MultiTerm.Core/Model/IHistoryElement.cs create mode 100644 MultiTerm.Core/Model/StringHistoryElement.cs create mode 100644 MultiTerm.Wpf/Assets/mdi-import.png diff --git a/MultiTerm.Core/Model/IHistoryElement.cs b/MultiTerm.Core/Model/IHistoryElement.cs new file mode 100644 index 0000000..fc9f025 --- /dev/null +++ b/MultiTerm.Core/Model/IHistoryElement.cs @@ -0,0 +1,14 @@ +namespace MultiTerm.Core.Model; + +/// +/// Represents an element of a history. +/// Required to have a common property to access. +/// Must also implement in order to clone the object before saving it to the history. +/// +public interface IHistoryElement : ICloneable +{ + /// + /// Displayable text of this element. + /// + string DisplayText { get; } +} diff --git a/MultiTerm.Core/Model/MultiFormatString.cs b/MultiTerm.Core/Model/MultiFormatString.cs index 829b568..56de25d 100644 --- a/MultiTerm.Core/Model/MultiFormatString.cs +++ b/MultiTerm.Core/Model/MultiFormatString.cs @@ -7,11 +7,18 @@ namespace MultiTerm.Core.Model; /// /// A string that contains symbols of multiple formats such as a standard character as well as hexadecimal or binary parts. /// -public class MultiFormatString: ObservableCollection +public class MultiFormatString: ObservableCollection, IHistoryElement, ICloneable { private const int charsPerHexBundle = 2; private const int charsPerBinBundle = 8; + #region IHistoryElement implementation + public string DisplayText => this.ToAsciiEncodedString(); + #endregion + + public MultiFormatString() { } + public MultiFormatString(IEnumerable collection) : base(collection) { } + #region Insertion / Removal of Characters /// /// Inserts item at given index after checking if its valid using . @@ -341,5 +348,13 @@ public class MultiFormatString: ObservableCollection var bytes = GetBytesFromString(binaryString, 2, charsPerBinBundle); return Encoding.ASCII.GetString(bytes); } + + #endregion + + #region ICloneable implementation + public object Clone() + { + return new MultiFormatString(this); + } #endregion } diff --git a/MultiTerm.Core/Model/StringHistoryElement.cs b/MultiTerm.Core/Model/StringHistoryElement.cs new file mode 100644 index 0000000..cebea33 --- /dev/null +++ b/MultiTerm.Core/Model/StringHistoryElement.cs @@ -0,0 +1,23 @@ +namespace MultiTerm.Core.Model; + +/// +/// Generic history element, which allows to use a string as history element. +/// +public class StringHistoryElement : IHistoryElement, ICloneable +{ + public string Text { get; } + + public string DisplayText => this.Text; + + public StringHistoryElement(string text) + { + Text = text; + } + + #region ICloneable implementation + public object Clone() + { + return this.MemberwiseClone(); + } + #endregion +} diff --git a/MultiTerm.Core/ViewModel/ConsoleViewModel.cs b/MultiTerm.Core/ViewModel/ConsoleViewModel.cs index a12c0aa..84c3016 100644 --- a/MultiTerm.Core/ViewModel/ConsoleViewModel.cs +++ b/MultiTerm.Core/ViewModel/ConsoleViewModel.cs @@ -3,6 +3,7 @@ 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; @@ -76,11 +77,20 @@ public partial class ConsoleViewModel : TerminalViewModel // 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; + } + /// /// Command to clear the data that was received. /// diff --git a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs index fa071f3..db26204 100644 --- a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs +++ b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs @@ -53,11 +53,21 @@ public partial class SendReceiveViewModel : TerminalViewModel // send data if (this.SendToCommunicationProtocol(this.SendableData.GetBytes())) { + // add to history + this.AddToSendHistory(this.SendableData); // clear textbox if send was successful this.SendableData.Clear(); } } + protected override void HandleInsertElementFromHistory(object element) + { + if(element is not MultiFormatString mfs) { throw new Exception($"'{HandleInsertElementFromHistory}()' in {nameof(SendReceiveViewModel)} got wrong type of element. Got Type: {element.GetType()}"); } + + // overwrite + this.SendableData = mfs; + } + public override void DisplayNewReceivedData(IEnumerable newData) { this.ReceivedData!.HandleNewData(newData); diff --git a/MultiTerm.Core/ViewModel/TerminalViewModel.cs b/MultiTerm.Core/ViewModel/TerminalViewModel.cs index a1fcb48..ab928c5 100644 --- a/MultiTerm.Core/ViewModel/TerminalViewModel.cs +++ b/MultiTerm.Core/ViewModel/TerminalViewModel.cs @@ -4,11 +4,13 @@ using Common.Messaging; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; +using MultiTerm.Core.Model; using MultiTerm.Core.Types; using MultiTerm.Protocols; using MultiTerm.Protocols.Model; using MultiTerm.Protocols.Types; using System.Collections.Concurrent; +using System.Collections.ObjectModel; namespace MultiTerm.Core.ViewModel; @@ -94,6 +96,11 @@ public abstract partial class TerminalViewModel : ObservableObject, ITerminalVie [ObservableProperty] private string communicationProtocolLongIdentifier = string.Empty; + /// + /// Collection of sent messages as . + /// + [ObservableProperty] + ObservableCollection sentMessagesHistory = new(); #endregion @@ -331,4 +338,39 @@ public abstract partial class TerminalViewModel : ObservableObject, ITerminalVie } #endregion + #region History + /// + /// Creates a clone of the passed element and saves that to the . + /// + /// element to add to the history + protected void AddToSendHistory(IHistoryElement element) + { + // shallow copy of element (so that element can be changed externally) + var copy = (IHistoryElement)element.Clone(); + + // add to list + this.SentMessagesHistory.Add(copy); + } + + /// + /// Shall handle the insertion of an element from the + /// into the current sendable message area. + /// + /// copy of element as object + protected abstract void HandleInsertElementFromHistory(object element); + + /// + /// Allows to insert an element from the history into the current send message. + /// Creates a copy of the object, so it can be changed externally. + /// + [RelayCommand] + public void InsertElementFromHistory(IHistoryElement element) + { + // shallow copy of element (so that element can be changed externally) + var copy = (IHistoryElement)element.Clone(); + + // let inheriting classes handle it + this.HandleInsertElementFromHistory(copy); + } + #endregion } diff --git a/MultiTerm.Wpf.CustomControl/MultiFormatTextBox/MultiFormatTextBox.cs b/MultiTerm.Wpf.CustomControl/MultiFormatTextBox/MultiFormatTextBox.cs index 7f658de..2f5c88a 100644 --- a/MultiTerm.Wpf.CustomControl/MultiFormatTextBox/MultiFormatTextBox.cs +++ b/MultiTerm.Wpf.CustomControl/MultiFormatTextBox/MultiFormatTextBox.cs @@ -137,10 +137,14 @@ public class MultiFormatTextBox : Control incc.CollectionChanged += mftb.MultiFormatString_CollectionChanged; } } - else if(mftb.CurrentMultiFormatString == null) + + // reset textbox and insert items if there are any + mftb.ResetTextBox(); + if(mftb.CurrentMultiFormatString.Count > 0) { - mftb.ResetTextBox(); + mftb.AddItemsToTextBox(mftb.CurrentMultiFormatString, 0); } + } /// diff --git a/MultiTerm.Wpf/Assets/mdi-import.png b/MultiTerm.Wpf/Assets/mdi-import.png new file mode 100644 index 0000000000000000000000000000000000000000..e72569fc8759a90ce637afed1bba87b0e941cb7d GIT binary patch literal 506 zcmVPx$v`IukR7gvWRqa*7Fbq6R!eatDO4%UYfDK@jWP^^t3T#j|U<2{u*s^4u1NqVC zCi*z(PO`u~0zmr@P|nqWy!W4rRkaalb(8YS9_}!+NY);SokN0-B7)~BW(mCY5yzsX zj`)x1oCCFPjxk5LR{-w39Lg=CzBo06k;Hod^ZIa!<8!7DQJ}q%g#@rM^|I)2{zQ=X6q9$lF9s}L8~%Z zp;&@KYz~UW$sEKzUg{I59Cw4Qd9Hz316QEhTsh<_naX0ngsgy;)}95Hs5R^r3oST0g+*V wcUm;hJ|}_z3Y+g#hbFAPQT$8{Yr{bN0^N1kC7Tzbg8%>k07*qoM6N<$f~3URl>h($ literal 0 HcmV?d00001 diff --git a/MultiTerm.Wpf/MultiTerm.Wpf.csproj b/MultiTerm.Wpf/MultiTerm.Wpf.csproj index 742d7e9..86713c1 100644 --- a/MultiTerm.Wpf/MultiTerm.Wpf.csproj +++ b/MultiTerm.Wpf/MultiTerm.Wpf.csproj @@ -9,6 +9,7 @@ + @@ -29,6 +30,7 @@ + diff --git a/MultiTerm.Wpf/View/ShellView.xaml b/MultiTerm.Wpf/View/ShellView.xaml index feb2393..26632d8 100644 --- a/MultiTerm.Wpf/View/ShellView.xaml +++ b/MultiTerm.Wpf/View/ShellView.xaml @@ -97,11 +97,6 @@ - - - - - @@ -109,8 +104,8 @@ - - + + @@ -141,6 +136,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - +