Implemented exporting received messages to Tapeti.Cmd compatible JSON file
This commit is contained in:
parent
785ddbd5b2
commit
2505dad190
16
PettingZoo.Core/Export/ExportFormatProvider.cs
Normal file
16
PettingZoo.Core/Export/ExportFormatProvider.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PettingZoo.Core.Export
|
||||
{
|
||||
public class ExportFormatProvider : IExportFormatProvider
|
||||
{
|
||||
private readonly List<IExportFormat> formats;
|
||||
|
||||
public IEnumerable<IExportFormat> Formats => formats;
|
||||
|
||||
public ExportFormatProvider(params IExportFormat[] formats)
|
||||
{
|
||||
this.formats = new List<IExportFormat>(formats);
|
||||
}
|
||||
}
|
||||
}
|
14
PettingZoo.Core/Export/IExportFormat.cs
Normal file
14
PettingZoo.Core/Export/IExportFormat.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using PettingZoo.Core.Connection;
|
||||
|
||||
namespace PettingZoo.Core.Export
|
||||
{
|
||||
public interface IExportFormat
|
||||
{
|
||||
public string Filter { get; }
|
||||
|
||||
public Task Export(Stream stream, IEnumerable<ReceivedMessageInfo> messages);
|
||||
}
|
||||
}
|
9
PettingZoo.Core/Export/IExportFormatProvider.cs
Normal file
9
PettingZoo.Core/Export/IExportFormatProvider.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PettingZoo.Core.Export
|
||||
{
|
||||
public interface IExportFormatProvider
|
||||
{
|
||||
public IEnumerable<IExportFormat> Formats { get; }
|
||||
}
|
||||
}
|
119
PettingZoo.Tapeti/Export/TapetiCmdExportFormat.cs
Normal file
119
PettingZoo.Tapeti/Export/TapetiCmdExportFormat.cs
Normal file
@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Export;
|
||||
|
||||
namespace PettingZoo.Tapeti.Export
|
||||
{
|
||||
public class TapetiCmdExportFormat : IExportFormat
|
||||
{
|
||||
public string Filter => TapetiCmdExportStrings.TapetiCmdFilter;
|
||||
|
||||
|
||||
private static readonly JsonSerializerSettings SerializerSettings = new()
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
|
||||
|
||||
public async Task Export(Stream stream, IEnumerable<ReceivedMessageInfo> messages)
|
||||
{
|
||||
await using var exportFile = new StreamWriter(stream, Encoding.UTF8);
|
||||
|
||||
foreach (var message in messages)
|
||||
{
|
||||
var serializableMessage = new SerializableMessage
|
||||
{
|
||||
Exchange = message.Exchange,
|
||||
RoutingKey = message.RoutingKey,
|
||||
Properties = new SerializableMessageProperties
|
||||
{
|
||||
AppId = message.Properties.AppId,
|
||||
ContentEncoding = message.Properties.ContentEncoding,
|
||||
ContentType = message.Properties.ContentType,
|
||||
CorrelationId = message.Properties.CorrelationId,
|
||||
DeliveryMode = message.Properties.DeliveryMode switch
|
||||
{
|
||||
MessageDeliveryMode.Persistent => 2,
|
||||
_ => 1
|
||||
},
|
||||
Expiration = message.Properties.Expiration,
|
||||
Headers = message.Properties.Headers.Count > 0 ? message.Properties.Headers.ToDictionary(p => p.Key, p => p.Value) : null,
|
||||
MessageId = message.Properties.MessageId,
|
||||
Priority = message.Properties.Priority,
|
||||
ReplyTo = message.Properties.ReplyTo,
|
||||
Timestamp = message.Properties.Timestamp.HasValue ? new DateTimeOffset(message.Properties.Timestamp.Value).ToUnixTimeSeconds() : null,
|
||||
Type = message.Properties.Type,
|
||||
UserId = message.Properties.UserId
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var useRawBody = true;
|
||||
if (message.Properties.ContentType == @"application/json")
|
||||
{
|
||||
try
|
||||
{
|
||||
if (JToken.Parse(Encoding.UTF8.GetString(message.Body)) is JObject jsonBody)
|
||||
{
|
||||
serializableMessage.Body = jsonBody;
|
||||
useRawBody = false;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Use raw body
|
||||
}
|
||||
}
|
||||
|
||||
if (useRawBody)
|
||||
serializableMessage.RawBody = message.Body;
|
||||
|
||||
var serialized = JsonConvert.SerializeObject(serializableMessage, SerializerSettings);
|
||||
await exportFile.WriteLineAsync(serialized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// It would be nicer if Tapeti.Cmd exposed it's file format in a NuGet package... if only I knew the author ¯\_(ツ)_/¯
|
||||
public class SerializableMessage
|
||||
{
|
||||
//public ulong DeliveryTag;
|
||||
//public bool Redelivered;
|
||||
public string? Exchange;
|
||||
public string? RoutingKey;
|
||||
//public string? Queue;
|
||||
|
||||
// ReSharper disable once FieldCanBeMadeReadOnly.Local - must be settable by JSON deserialization
|
||||
public SerializableMessageProperties? Properties;
|
||||
|
||||
public JObject? Body;
|
||||
public byte[]? RawBody;
|
||||
}
|
||||
|
||||
|
||||
public class SerializableMessageProperties
|
||||
{
|
||||
public string? AppId;
|
||||
//public string? ClusterId;
|
||||
public string? ContentEncoding;
|
||||
public string? ContentType;
|
||||
public string? CorrelationId;
|
||||
public byte? DeliveryMode;
|
||||
public string? Expiration;
|
||||
public IDictionary<string, string>? Headers;
|
||||
public string? MessageId;
|
||||
public byte? Priority;
|
||||
public string? ReplyTo;
|
||||
public long? Timestamp;
|
||||
public string? Type;
|
||||
public string? UserId;
|
||||
}
|
||||
}
|
72
PettingZoo.Tapeti/Export/TapetiCmdExportStrings.Designer.cs
generated
Normal file
72
PettingZoo.Tapeti/Export/TapetiCmdExportStrings.Designer.cs
generated
Normal file
@ -0,0 +1,72 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace PettingZoo.Tapeti.Export {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class TapetiCmdExportStrings {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal TapetiCmdExportStrings() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Tapeti.Export.TapetiCmdExportStrings", typeof(TapetiCmdExportStrings).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tapeti.Cmd single-file JSON (*.json)|*.json.
|
||||
/// </summary>
|
||||
internal static string TapetiCmdFilter {
|
||||
get {
|
||||
return ResourceManager.GetString("TapetiCmdFilter", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
123
PettingZoo.Tapeti/Export/TapetiCmdExportStrings.resx
Normal file
123
PettingZoo.Tapeti/Export/TapetiCmdExportStrings.resx
Normal file
@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="TapetiCmdFilter" xml:space="preserve">
|
||||
<value>Tapeti.Cmd single-file JSON (*.json)|*.json</value>
|
||||
</data>
|
||||
</root>
|
@ -32,6 +32,11 @@
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>AssemblyParserStrings.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Export\TapetiCmdExportStrings.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>TapetiCmdExportStrings.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="UI\ClassSelection\ClassSelectionStrings.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
@ -57,6 +62,10 @@
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>AssemblyParserStrings.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Export\TapetiCmdExportStrings.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>TapetiCmdExportStrings.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="UI\ClassSelection\ClassSelectionStrings.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>ClassSelectionStrings.Designer.cs</LastGenOutput>
|
||||
|
@ -34,8 +34,6 @@ namespace PettingZoo.Tapeti
|
||||
.WithSourcesFrom(Path.Combine(PettingZooPaths.InstallationRoot, @"nuget.config"))
|
||||
.WithSourcesFrom(Path.Combine(PettingZooPaths.AppDataRoot, @"nuget.config"));
|
||||
|
||||
var dispatcher = Dispatcher.CurrentDispatcher;
|
||||
|
||||
var viewModel = new PackageSelectionViewModel(packageManager);
|
||||
var selectionWindow = new PackageSelectionWindow(viewModel)
|
||||
{
|
||||
@ -44,7 +42,7 @@ namespace PettingZoo.Tapeti
|
||||
|
||||
viewModel.Select += (_, args) =>
|
||||
{
|
||||
dispatcher.Invoke(() =>
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var windowBounds = selectionWindow.RestoreBounds;
|
||||
selectionWindow.Close();
|
||||
@ -65,7 +63,7 @@ namespace PettingZoo.Tapeti
|
||||
// var classes =
|
||||
var examples = LoadExamples(assemblies);
|
||||
|
||||
dispatcher.Invoke(() =>
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
progressWindow.Close();
|
||||
progressWindow = null;
|
||||
@ -90,7 +88,7 @@ namespace PettingZoo.Tapeti
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
dispatcher.Invoke(() =>
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
// ReSharper disable once ConstantConditionalAccessQualifier - if I remove it, there's a "Dereference of a possibly null reference" warning instead
|
||||
progressWindow?.Close();
|
||||
|
23
PettingZoo/Images/Export.svg
Normal file
23
PettingZoo/Images/Export.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<polygon style="fill:#EFEBDE;" points="46.5,14 32.5,0 1.5,0 1.5,58 46.5,58 "/>
|
||||
<g>
|
||||
<path style="fill:#D5D0BB;" d="M11.5,23h25c0.552,0,1-0.447,1-1s-0.448-1-1-1h-25c-0.552,0-1,0.447-1,1S10.948,23,11.5,23z"/>
|
||||
<path style="fill:#D5D0BB;" d="M11.5,15h10c0.552,0,1-0.447,1-1s-0.448-1-1-1h-10c-0.552,0-1,0.447-1,1S10.948,15,11.5,15z"/>
|
||||
<path style="fill:#D5D0BB;" d="M36.5,29h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S37.052,29,36.5,29z"/>
|
||||
<path style="fill:#D5D0BB;" d="M36.5,37h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S37.052,37,36.5,37z"/>
|
||||
<path style="fill:#D5D0BB;" d="M36.5,45h-25c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S37.052,45,36.5,45z"/>
|
||||
</g>
|
||||
<polygon style="fill:#D5D0BB;" points="32.5,0 32.5,14 46.5,14 "/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="34.5" y="36" style="fill:#21AE5E;" width="22" height="22"/>
|
||||
<rect x="44.5" y="37.586" style="fill:#FFFFFF;" width="2" height="16"/>
|
||||
<polygon style="fill:#FFFFFF;" points="45.5,55 38.5,48.293 39.976,46.879 45.5,52.172 51.024,46.879 52.5,48.293 "/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
23
PettingZoo/Images/Import.svg
Normal file
23
PettingZoo/Images/Import.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<polygon style="fill:#EFEBDE;" points="46,14 32,0 1,0 1,58 46,58 "/>
|
||||
<g>
|
||||
<path style="fill:#D5D0BB;" d="M11,23h25c0.552,0,1-0.447,1-1s-0.448-1-1-1H11c-0.552,0-1,0.447-1,1S10.448,23,11,23z"/>
|
||||
<path style="fill:#D5D0BB;" d="M11,15h10c0.552,0,1-0.447,1-1s-0.448-1-1-1H11c-0.552,0-1,0.447-1,1S10.448,15,11,15z"/>
|
||||
<path style="fill:#D5D0BB;" d="M36,29H11c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S36.552,29,36,29z"/>
|
||||
<path style="fill:#D5D0BB;" d="M36,37H11c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S36.552,37,36,37z"/>
|
||||
<path style="fill:#D5D0BB;" d="M36,45H11c-0.552,0-1,0.447-1,1s0.448,1,1,1h25c0.552,0,1-0.447,1-1S36.552,45,36,45z"/>
|
||||
</g>
|
||||
<polygon style="fill:#D5D0BB;" points="32,0 32,14 46,14 "/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="35" y="36" style="fill:#48A0DC;" width="22" height="22"/>
|
||||
<rect x="45" y="42" style="fill:#FFFFFF;" width="2" height="16"/>
|
||||
<polygon style="fill:#FFFFFF;" points="51.293,48.707 46,43.414 40.707,48.707 39.293,47.293 46,40.586 52.707,47.293 "/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -23,7 +23,9 @@
|
||||
<None Remove="Images\Dock.svg" />
|
||||
<None Remove="Images\Error.svg" />
|
||||
<None Remove="Images\Example.svg" />
|
||||
<None Remove="Images\Export.svg" />
|
||||
<None Remove="Images\Folder.svg" />
|
||||
<None Remove="Images\Import.svg" />
|
||||
<None Remove="Images\Ok.svg" />
|
||||
<None Remove="Images\PublishSend.svg" />
|
||||
<None Remove="Images\Undock.svg" />
|
||||
@ -36,7 +38,9 @@
|
||||
<Resource Include="Images\Dock.svg" />
|
||||
<Resource Include="Images\Error.svg" />
|
||||
<Resource Include="Images\Example.svg" />
|
||||
<Resource Include="Images\Export.svg" />
|
||||
<Resource Include="Images\Folder.svg" />
|
||||
<Resource Include="Images\Import.svg" />
|
||||
<Resource Include="Images\Ok.svg" />
|
||||
<Resource Include="Images\Publish.svg" />
|
||||
<Resource Include="Images\PublishSend.svg" />
|
||||
|
@ -4,14 +4,17 @@ using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Export;
|
||||
using PettingZoo.Core.Generator;
|
||||
using PettingZoo.Core.Settings;
|
||||
using PettingZoo.RabbitMQ;
|
||||
using PettingZoo.Settings.LiteDB;
|
||||
using PettingZoo.Tapeti;
|
||||
using PettingZoo.Tapeti.Export;
|
||||
using PettingZoo.UI.Connection;
|
||||
using PettingZoo.UI.Main;
|
||||
using PettingZoo.UI.Subscribe;
|
||||
using PettingZoo.UI.Tab;
|
||||
using Serilog;
|
||||
using SimpleInjector;
|
||||
|
||||
@ -79,6 +82,10 @@ namespace PettingZoo
|
||||
container.Register<IConnectionSettingsRepository, LiteDBConnectionSettingsRepository>();
|
||||
container.Register<IUISettingsRepository, LiteDBUISettingsRepository>();
|
||||
container.Register<IExampleGenerator, TapetiClassLibraryExampleGenerator>();
|
||||
container.Register<ITabHostProvider, TabHostProvider>();
|
||||
container.Register<ITabFactory, ViewTabFactory>();
|
||||
|
||||
container.RegisterInstance<IExportFormatProvider>(new ExportFormatProvider(new TapetiCmdExportFormat()));
|
||||
|
||||
container.Register<MainWindow>();
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
Should-have
|
||||
-----------
|
||||
- Save / load publisher messages (either as templates or to disk)
|
||||
- Tapeti: export received messages to Tapeti.Cmd JSON file / Tapeti.Cmd command-line
|
||||
- Tapeti: import Tapeti.Cmd JSON file into Subscriber-esque tab for easier browsing
|
||||
- Tapeti: fetch NuGet dependencies to improve the chances of succesfully loading the assembly, instead of the current "extraAssembliesPaths" workaround
|
||||
|
||||
|
@ -5,7 +5,6 @@ using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Generator;
|
||||
using PettingZoo.UI.Connection;
|
||||
using PettingZoo.UI.Subscribe;
|
||||
using PettingZoo.UI.Tab;
|
||||
@ -20,11 +19,12 @@ namespace PettingZoo.UI.Main
|
||||
public bool WasMaximized;
|
||||
|
||||
|
||||
public MainWindow(IConnectionFactory connectionFactory, IConnectionDialog connectionDialog, ISubscribeDialog subscribeDialog, IExampleGenerator exampleGenerator)
|
||||
public MainWindow(IConnectionFactory connectionFactory, IConnectionDialog connectionDialog, ISubscribeDialog subscribeDialog,
|
||||
ITabHostProvider tabHostProvider, ITabFactory tabFactory)
|
||||
{
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
|
||||
viewModel = new MainWindowViewModel(connectionFactory, connectionDialog, subscribeDialog, this, exampleGenerator)
|
||||
viewModel = new MainWindowViewModel(connectionFactory, connectionDialog, subscribeDialog, this, tabHostProvider, tabFactory)
|
||||
{
|
||||
TabHostWindow = this
|
||||
};
|
||||
|
@ -6,7 +6,6 @@ using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Generator;
|
||||
using PettingZoo.UI.Connection;
|
||||
using PettingZoo.UI.Subscribe;
|
||||
using PettingZoo.UI.Tab;
|
||||
@ -29,6 +28,7 @@ namespace PettingZoo.UI.Main
|
||||
private readonly IConnectionDialog connectionDialog;
|
||||
private readonly ISubscribeDialog subscribeDialog;
|
||||
private readonly ITabContainer tabContainer;
|
||||
private readonly ITabHostProvider tabHostProvider;
|
||||
private readonly ITabFactory tabFactory;
|
||||
|
||||
private SubscribeDialogParams? subscribeDialogParams;
|
||||
@ -103,12 +103,16 @@ namespace PettingZoo.UI.Main
|
||||
|
||||
|
||||
public MainWindowViewModel(IConnectionFactory connectionFactory, IConnectionDialog connectionDialog,
|
||||
ISubscribeDialog subscribeDialog, ITabContainer tabContainer, IExampleGenerator exampleGenerator)
|
||||
ISubscribeDialog subscribeDialog, ITabContainer tabContainer, ITabHostProvider tabHostProvider, ITabFactory tabFactory)
|
||||
{
|
||||
tabHostProvider.SetInstance(this);
|
||||
|
||||
this.connectionFactory = connectionFactory;
|
||||
this.connectionDialog = connectionDialog;
|
||||
this.subscribeDialog = subscribeDialog;
|
||||
this.tabContainer = tabContainer;
|
||||
this.tabHostProvider = tabHostProvider;
|
||||
this.tabFactory = tabFactory;
|
||||
|
||||
connectionStatus = GetConnectionStatus(null);
|
||||
connectionStatusType = ConnectionStatusType.Error;
|
||||
@ -120,8 +124,6 @@ namespace PettingZoo.UI.Main
|
||||
subscribeCommand = new DelegateCommand(SubscribeExecute, IsConnectedCanExecute);
|
||||
closeTabCommand = new DelegateCommand(CloseTabExecute, HasActiveTabCanExecute);
|
||||
undockTabCommand = new DelegateCommand(UndockTabExecute, HasActiveTabCanExecute);
|
||||
|
||||
tabFactory = new ViewTabFactory(this, exampleGenerator);
|
||||
}
|
||||
|
||||
|
||||
@ -226,7 +228,7 @@ namespace PettingZoo.UI.Main
|
||||
if (tab == null)
|
||||
return;
|
||||
|
||||
var tabHostWindow = UndockedTabHostWindow.Create(this, tab, tabContainer.TabWidth, tabContainer.TabHeight);
|
||||
var tabHostWindow = UndockedTabHostWindow.Create(tabHostProvider, tab, tabContainer.TabWidth, tabContainer.TabHeight);
|
||||
undockedTabs.Add(tab, tabHostWindow);
|
||||
|
||||
tabHostWindow.Show();
|
||||
@ -330,7 +332,7 @@ namespace PettingZoo.UI.Main
|
||||
|
||||
public class DesignTimeMainWindowViewModel : MainWindowViewModel
|
||||
{
|
||||
public DesignTimeMainWindowViewModel() : base(null!, null!, null!, null!, null!)
|
||||
public DesignTimeMainWindowViewModel() : base(null!, null!, null!, null!, null!, null!)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
9
PettingZoo/UI/Tab/ITabHostProvider.cs
Normal file
9
PettingZoo/UI/Tab/ITabHostProvider.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace PettingZoo.UI.Tab
|
||||
{
|
||||
public interface ITabHostProvider
|
||||
{
|
||||
public ITabHost Instance { get; }
|
||||
|
||||
public void SetInstance(ITabHost instance);
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
private readonly IConnection connection;
|
||||
private readonly IExampleGenerator exampleGenerator;
|
||||
private readonly ITabFactory tabFactory;
|
||||
private readonly ITabHost tabHost;
|
||||
private readonly ITabHostProvider tabHostProvider;
|
||||
|
||||
private bool sendToExchange = true;
|
||||
private string exchange = "";
|
||||
@ -156,12 +156,12 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
string IPublishDestination.RoutingKey => SendToExchange ? RoutingKey : Queue;
|
||||
|
||||
|
||||
public PublisherViewModel(ITabHost tabHost, ITabFactory tabFactory, IConnection connection, IExampleGenerator exampleGenerator, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||
public PublisherViewModel(ITabHostProvider tabHostProvider, ITabFactory tabFactory, IConnection connection, IExampleGenerator exampleGenerator, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.exampleGenerator = exampleGenerator;
|
||||
this.tabFactory = tabFactory;
|
||||
this.tabHost = tabHost;
|
||||
this.tabHostProvider = tabHostProvider;
|
||||
|
||||
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||
|
||||
@ -287,7 +287,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
|
||||
var subscriber = connection.Subscribe();
|
||||
var tab = tabFactory.CreateSubscriberTab(connection, subscriber);
|
||||
tabHost.AddTab(tab);
|
||||
tabHostProvider.Instance.AddTab(tab);
|
||||
|
||||
subscriber.Start();
|
||||
return subscriber.QueueName;
|
||||
|
@ -124,7 +124,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
{
|
||||
exampleGenerator.Select(tabHostWindow, example =>
|
||||
{
|
||||
Dispatcher.CurrentDispatcher.BeginInvoke(() =>
|
||||
Application.Current.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
switch (example)
|
||||
{
|
||||
|
@ -1,26 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
using Microsoft.Win32;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Export;
|
||||
using PettingZoo.Core.Rendering;
|
||||
using PettingZoo.WPF.ViewModel;
|
||||
using Serilog;
|
||||
using IConnection = PettingZoo.Core.Connection.IConnection;
|
||||
|
||||
namespace PettingZoo.UI.Tab.Subscriber
|
||||
{
|
||||
public class SubscriberViewModel : BaseViewModel, ITabToolbarCommands, ITabActivate
|
||||
{
|
||||
private readonly ITabHost tabHost;
|
||||
private readonly ILogger logger;
|
||||
private readonly ITabHostProvider tabHostProvider;
|
||||
private readonly ITabFactory tabFactory;
|
||||
private readonly IConnection connection;
|
||||
private readonly ISubscriber subscriber;
|
||||
private readonly Dispatcher dispatcher;
|
||||
private readonly IExportFormatProvider exportFormatProvider;
|
||||
private ReceivedMessageInfo? selectedMessage;
|
||||
private readonly DelegateCommand clearCommand;
|
||||
private readonly DelegateCommand exportCommand;
|
||||
private readonly TabToolbarCommand[] toolbarCommands;
|
||||
private IDictionary<string, string>? selectedMessageProperties;
|
||||
|
||||
@ -32,6 +39,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
|
||||
|
||||
public ICommand ClearCommand => clearCommand;
|
||||
public ICommand ExportCommand => exportCommand;
|
||||
|
||||
// ReSharper disable once UnusedMember.Global - it is, but via a proxy
|
||||
public ICommand CreatePublisherCommand => createPublisherCommand;
|
||||
@ -70,22 +78,25 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
||||
|
||||
|
||||
public SubscriberViewModel(ITabHost tabHost, ITabFactory tabFactory, IConnection connection, ISubscriber subscriber)
|
||||
public SubscriberViewModel(ILogger logger, ITabHostProvider tabHostProvider, ITabFactory tabFactory, IConnection connection, ISubscriber subscriber, IExportFormatProvider exportFormatProvider)
|
||||
{
|
||||
this.tabHost = tabHost;
|
||||
this.logger = logger;
|
||||
this.tabHostProvider = tabHostProvider;
|
||||
this.tabFactory = tabFactory;
|
||||
this.connection = connection;
|
||||
this.subscriber = subscriber;
|
||||
|
||||
dispatcher = Dispatcher.CurrentDispatcher;
|
||||
this.exportFormatProvider = exportFormatProvider;
|
||||
|
||||
Messages = new ObservableCollectionEx<ReceivedMessageInfo>();
|
||||
UnreadMessages = new ObservableCollectionEx<ReceivedMessageInfo>();
|
||||
clearCommand = new DelegateCommand(ClearExecute, ClearCanExecute);
|
||||
|
||||
clearCommand = new DelegateCommand(ClearExecute, HasMessagesCanExecute);
|
||||
exportCommand = new DelegateCommand(ExportExecute, HasMessagesCanExecute);
|
||||
|
||||
toolbarCommands = new[]
|
||||
{
|
||||
new TabToolbarCommand(ClearCommand, SubscriberViewStrings.CommandClear, SvgIconHelper.LoadFromResource("/Images/Clear.svg"))
|
||||
new TabToolbarCommand(ClearCommand, SubscriberViewStrings.CommandClear, SvgIconHelper.LoadFromResource("/Images/Clear.svg")),
|
||||
new TabToolbarCommand(ExportCommand, SubscriberViewStrings.CommandExport, SvgIconHelper.LoadFromResource("/Images/Export.svg"))
|
||||
};
|
||||
|
||||
createPublisherCommand = new DelegateCommand(CreatePublisherExecute, CreatePublisherCanExecute);
|
||||
@ -94,26 +105,82 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
subscriber.Start();
|
||||
}
|
||||
|
||||
|
||||
private void ClearExecute()
|
||||
{
|
||||
Messages.Clear();
|
||||
UnreadMessages.Clear();
|
||||
|
||||
HasMessagesChanged();
|
||||
RaisePropertyChanged(nameof(UnreadMessagesVisibility));
|
||||
clearCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
|
||||
private bool ClearCanExecute()
|
||||
private bool HasMessagesCanExecute()
|
||||
{
|
||||
return Messages.Count > 0;
|
||||
return Messages.Count > 0 || UnreadMessages.Count > 0;
|
||||
}
|
||||
|
||||
|
||||
private void HasMessagesChanged()
|
||||
{
|
||||
clearCommand.RaiseCanExecuteChanged();
|
||||
exportCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
|
||||
private void ExportExecute()
|
||||
{
|
||||
var formats = exportFormatProvider.Formats.ToArray();
|
||||
|
||||
var dialog = new SaveFileDialog
|
||||
{
|
||||
Filter = string.Join('|', formats.Select(f => f.Filter))
|
||||
};
|
||||
|
||||
if (!dialog.ShowDialog().GetValueOrDefault())
|
||||
return;
|
||||
|
||||
// 1-based? Seriously?
|
||||
if (dialog.FilterIndex <= 0 || dialog.FilterIndex > formats.Length)
|
||||
return;
|
||||
|
||||
var messages = Messages.Concat(UnreadMessages).ToArray();
|
||||
var filename = dialog.FileName;
|
||||
var format = formats[dialog.FilterIndex - 1];
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var exportFile = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
await format.Export(exportFile, messages);
|
||||
|
||||
await Application.Current.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
MessageBox.Show(string.Format(SubscriberViewStrings.ExportSuccess, messages.Length, filename),
|
||||
SubscriberViewStrings.ExportResultTitle,
|
||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error(e, "Error while exporting messages");
|
||||
|
||||
await Application.Current.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
MessageBox.Show(string.Format(SubscriberViewStrings.ExportError, e.Message),
|
||||
SubscriberViewStrings.ExportResultTitle,
|
||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void CreatePublisherExecute()
|
||||
{
|
||||
var publisherTab = tabFactory.CreatePublisherTab(connection, SelectedMessage);
|
||||
tabHost.AddTab(publisherTab);
|
||||
tabHostProvider.Instance.AddTab(publisherTab);
|
||||
}
|
||||
|
||||
|
||||
@ -125,7 +192,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
|
||||
private void SubscriberMessageReceived(object? sender, MessageReceivedEventArgs args)
|
||||
{
|
||||
dispatcher.BeginInvoke(() =>
|
||||
Application.Current.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
if (!tabActive)
|
||||
{
|
||||
@ -139,7 +206,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
else
|
||||
Messages.Add(args.MessageInfo);
|
||||
|
||||
clearCommand.RaiseCanExecuteChanged();
|
||||
HasMessagesChanged();
|
||||
});
|
||||
}
|
||||
|
||||
@ -168,7 +235,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
newMessageTimer = new Timer(
|
||||
_ =>
|
||||
{
|
||||
dispatcher.BeginInvoke(() =>
|
||||
Application.Current.Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
if (UnreadMessages.Count == 0)
|
||||
return;
|
||||
@ -210,7 +277,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
|
||||
public class DesignTimeSubscriberViewModel : SubscriberViewModel
|
||||
{
|
||||
public DesignTimeSubscriberViewModel() : base(null!, null!, null!, new DesignTimeSubscriber())
|
||||
public DesignTimeSubscriberViewModel() : base(null!, null!, null!, null!, new DesignTimeSubscriber(), null!)
|
||||
{
|
||||
for (var i = 1; i <= 5; i++)
|
||||
(i > 2 ? UnreadMessages : Messages).Add(new ReceivedMessageInfo(
|
||||
|
@ -69,6 +69,15 @@ namespace PettingZoo.UI.Tab.Subscriber {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Export....
|
||||
/// </summary>
|
||||
public static string CommandExport {
|
||||
get {
|
||||
return ResourceManager.GetString("CommandExport", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Open in new Publisher tab.
|
||||
/// </summary>
|
||||
@ -96,6 +105,33 @@ namespace PettingZoo.UI.Tab.Subscriber {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error while exporting messages: {0}.
|
||||
/// </summary>
|
||||
public static string ExportError {
|
||||
get {
|
||||
return ResourceManager.GetString("ExportError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Export.
|
||||
/// </summary>
|
||||
public static string ExportResultTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ExportResultTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Exported {0} message(s) to {1}.
|
||||
/// </summary>
|
||||
public static string ExportSuccess {
|
||||
get {
|
||||
return ResourceManager.GetString("ExportSuccess", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to New messages.
|
||||
/// </summary>
|
||||
|
@ -120,6 +120,9 @@
|
||||
<data name="CommandClear" xml:space="preserve">
|
||||
<value>Clear</value>
|
||||
</data>
|
||||
<data name="CommandExport" xml:space="preserve">
|
||||
<value>Export...</value>
|
||||
</data>
|
||||
<data name="ContextPublish" xml:space="preserve">
|
||||
<value>Open in new Publisher tab</value>
|
||||
</data>
|
||||
@ -129,6 +132,15 @@
|
||||
<data name="DeliveryModePersistent" xml:space="preserve">
|
||||
<value>Persistent</value>
|
||||
</data>
|
||||
<data name="ExportError" xml:space="preserve">
|
||||
<value>Error while exporting messages: {0}</value>
|
||||
</data>
|
||||
<data name="ExportResultTitle" xml:space="preserve">
|
||||
<value>Export</value>
|
||||
</data>
|
||||
<data name="ExportSuccess" xml:space="preserve">
|
||||
<value>Exported {0} message(s) to {1}</value>
|
||||
</data>
|
||||
<data name="LabelNewMessages" xml:space="preserve">
|
||||
<value>New messages</value>
|
||||
</data>
|
||||
|
18
PettingZoo/UI/Tab/TabHostProvider.cs
Normal file
18
PettingZoo/UI/Tab/TabHostProvider.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace PettingZoo.UI.Tab
|
||||
{
|
||||
public class TabHostProvider : ITabHostProvider
|
||||
{
|
||||
private ITabHost? instance;
|
||||
|
||||
public ITabHost Instance => instance ?? throw new InvalidOperationException("ITabHost instance must be initialized before acquiring");
|
||||
|
||||
|
||||
// ReSharper disable once ParameterHidesMember
|
||||
public void SetInstance(ITabHost instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ namespace PettingZoo.UI.Tab.Undocked
|
||||
{
|
||||
public class UndockedTabHostViewModel : BaseViewModel, ITabActivate
|
||||
{
|
||||
private readonly ITabHost tabHost;
|
||||
private readonly ITabHostProvider tabHostProvider;
|
||||
private readonly ITab tab;
|
||||
private readonly DelegateCommand dockCommand;
|
||||
|
||||
@ -25,9 +25,9 @@ namespace PettingZoo.UI.Tab.Undocked
|
||||
public ICommand DockCommand => dockCommand;
|
||||
|
||||
|
||||
public UndockedTabHostViewModel(ITabHost tabHost, ITab tab)
|
||||
public UndockedTabHostViewModel(ITabHostProvider tabHostProvider, ITab tab)
|
||||
{
|
||||
this.tabHost = tabHost;
|
||||
this.tabHostProvider = tabHostProvider;
|
||||
this.tab = tab;
|
||||
|
||||
tab.PropertyChanged += (_, args) =>
|
||||
@ -43,13 +43,13 @@ namespace PettingZoo.UI.Tab.Undocked
|
||||
|
||||
private void DockCommandExecute()
|
||||
{
|
||||
tabHost.DockTab(tab);
|
||||
tabHostProvider.Instance.DockTab(tab);
|
||||
}
|
||||
|
||||
|
||||
public void WindowClosed()
|
||||
{
|
||||
tabHost.UndockedTabClosed(tab);
|
||||
tabHostProvider.Instance.UndockedTabClosed(tab);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,9 +10,9 @@ namespace PettingZoo.UI.Tab.Undocked
|
||||
/// </summary>
|
||||
public partial class UndockedTabHostWindow
|
||||
{
|
||||
public static UndockedTabHostWindow Create(ITabHost tabHost, ITab tab, double width, double height)
|
||||
public static UndockedTabHostWindow Create(ITabHostProvider tabHostProvider, ITab tab, double width, double height)
|
||||
{
|
||||
var viewModel = new UndockedTabHostViewModel(tabHost, tab);
|
||||
var viewModel = new UndockedTabHostViewModel(tabHostProvider, tab);
|
||||
var window = new UndockedTabHostWindow(viewModel)
|
||||
{
|
||||
Width = width,
|
||||
|
@ -1,26 +1,32 @@
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Export;
|
||||
using PettingZoo.Core.Generator;
|
||||
using PettingZoo.UI.Tab.Publisher;
|
||||
using PettingZoo.UI.Tab.Subscriber;
|
||||
using Serilog;
|
||||
|
||||
namespace PettingZoo.UI.Tab
|
||||
{
|
||||
public class ViewTabFactory : ITabFactory
|
||||
{
|
||||
private readonly ITabHost tabHost;
|
||||
private readonly ILogger logger;
|
||||
private readonly ITabHostProvider tabHostProvider;
|
||||
private readonly IExampleGenerator exampleGenerator;
|
||||
private readonly IExportFormatProvider exportFormatProvider;
|
||||
|
||||
|
||||
public ViewTabFactory(ITabHost tabHost, IExampleGenerator exampleGenerator)
|
||||
public ViewTabFactory(ILogger logger, ITabHostProvider tabHostProvider, IExampleGenerator exampleGenerator, IExportFormatProvider exportFormatProvider)
|
||||
{
|
||||
this.tabHost = tabHost;
|
||||
this.logger = logger;
|
||||
this.tabHostProvider = tabHostProvider;
|
||||
this.exampleGenerator = exampleGenerator;
|
||||
this.exportFormatProvider = exportFormatProvider;
|
||||
}
|
||||
|
||||
|
||||
public ITab CreateSubscriberTab(IConnection connection, ISubscriber subscriber)
|
||||
{
|
||||
var viewModel = new SubscriberViewModel(tabHost, this, connection, subscriber);
|
||||
var viewModel = new SubscriberViewModel(logger, tabHostProvider, this, connection, subscriber, exportFormatProvider);
|
||||
return new ViewTab<SubscriberView, SubscriberViewModel>(
|
||||
new SubscriberView(viewModel),
|
||||
viewModel,
|
||||
@ -30,7 +36,7 @@ namespace PettingZoo.UI.Tab
|
||||
|
||||
public ITab CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||
{
|
||||
var viewModel = new PublisherViewModel(tabHost, this, connection, exampleGenerator, fromReceivedMessage);
|
||||
var viewModel = new PublisherViewModel(tabHostProvider, this, connection, exampleGenerator, fromReceivedMessage);
|
||||
return new ViewTab<PublisherView, PublisherViewModel>(
|
||||
new PublisherView(viewModel),
|
||||
viewModel,
|
||||
|
Loading…
Reference in New Issue
Block a user