Merge branch 'release/1.3'
This commit is contained in:
commit
2cfb341f47
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace PettingZoo.Core.Connection
|
namespace PettingZoo.Core.Connection
|
||||||
{
|
{
|
||||||
public interface ISubscriber : IAsyncDisposable
|
public interface ISubscriber : IDisposable
|
||||||
{
|
{
|
||||||
string? QueueName { get; }
|
string? QueueName { get; }
|
||||||
string? Exchange {get; }
|
string? Exchange {get; }
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
|
|
||||||
namespace PettingZoo.Core.ExportImport
|
namespace PettingZoo.Core.ExportImport
|
||||||
@ -13,7 +12,10 @@ namespace PettingZoo.Core.ExportImport
|
|||||||
public string? QueueName { get; }
|
public string? QueueName { get; }
|
||||||
public string? Exchange => null;
|
public string? Exchange => null;
|
||||||
public string? RoutingKey => null;
|
public string? RoutingKey => null;
|
||||||
|
|
||||||
|
#pragma warning disable CS0067 // "The event ... is never used" - it's part of the interface so it's required.
|
||||||
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
||||||
|
#pragma warning restore CS0067
|
||||||
|
|
||||||
|
|
||||||
public ImportSubscriber(string filename, IReadOnlyList<ReceivedMessageInfo> messages)
|
public ImportSubscriber(string filename, IReadOnlyList<ReceivedMessageInfo> messages)
|
||||||
@ -23,10 +25,9 @@ namespace PettingZoo.Core.ExportImport
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
return default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ namespace PettingZoo.Core.ExportImport
|
|||||||
public StreamWrapper(StreamProgressDecorator owner, Stream decoratedStream)
|
public StreamWrapper(StreamProgressDecorator owner, Stream decoratedStream)
|
||||||
{
|
{
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.DecoratedStream = decoratedStream;
|
DecoratedStream = decoratedStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,11 +17,13 @@ namespace PettingZoo.Core.Generator
|
|||||||
|
|
||||||
public interface IClassTypeExample : IExample
|
public interface IClassTypeExample : IExample
|
||||||
{
|
{
|
||||||
public string AssemblyName { get; }
|
string AssemblyName { get; }
|
||||||
public string? Namespace { get; }
|
string? Namespace { get; }
|
||||||
public string ClassName { get; }
|
string ClassName { get; }
|
||||||
|
|
||||||
public string FullClassName => (!string.IsNullOrEmpty(Namespace) ? Namespace + "." : "") + ClassName;
|
string FullClassName => (!string.IsNullOrEmpty(Namespace) ? Namespace + "." : "") + ClassName;
|
||||||
|
|
||||||
|
bool TryGetPublishDestination(out string exchange, out string routingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
22
PettingZoo.Core/Macros/BasePayloadMacro.cs
Normal file
22
PettingZoo.Core/Macros/BasePayloadMacro.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
namespace PettingZoo.Core.Macros
|
||||||
|
{
|
||||||
|
public abstract class BasePayloadMacro : IPayloadMacro
|
||||||
|
{
|
||||||
|
public string DisplayName { get; }
|
||||||
|
public string MacroText { get; }
|
||||||
|
|
||||||
|
public string MacroCommand { get; }
|
||||||
|
|
||||||
|
|
||||||
|
protected BasePayloadMacro(string macroCommand, string displayName)
|
||||||
|
{
|
||||||
|
MacroCommand = macroCommand;
|
||||||
|
|
||||||
|
DisplayName = displayName;
|
||||||
|
MacroText = "{{" + macroCommand + "}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract string GetValue();
|
||||||
|
}
|
||||||
|
}
|
18
PettingZoo.Core/Macros/DateTimePayloadMacro.cs
Normal file
18
PettingZoo.Core/Macros/DateTimePayloadMacro.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PettingZoo.Core.Macros
|
||||||
|
{
|
||||||
|
public class JsonDateTimePayloadMacro : BasePayloadMacro
|
||||||
|
{
|
||||||
|
public JsonDateTimePayloadMacro()
|
||||||
|
: base("JsonUtcNow", "Current date/time (yyyy-mm-ddThh:mm:ss.mmmZ)")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override string GetValue()
|
||||||
|
{
|
||||||
|
return DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
PettingZoo.Core/Macros/IPayloadMacroProcessor.cs
Normal file
18
PettingZoo.Core/Macros/IPayloadMacroProcessor.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace PettingZoo.Core.Macros
|
||||||
|
{
|
||||||
|
public interface IPayloadMacroProcessor
|
||||||
|
{
|
||||||
|
string Apply(string payload);
|
||||||
|
|
||||||
|
IEnumerable<IPayloadMacro> Macros { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IPayloadMacro
|
||||||
|
{
|
||||||
|
public string DisplayName { get; }
|
||||||
|
public string MacroText { get; }
|
||||||
|
}
|
||||||
|
}
|
18
PettingZoo.Core/Macros/NewGuidPayloadMacro.cs
Normal file
18
PettingZoo.Core/Macros/NewGuidPayloadMacro.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace PettingZoo.Core.Macros
|
||||||
|
{
|
||||||
|
public class NewGuidPayloadMacro : BasePayloadMacro
|
||||||
|
{
|
||||||
|
public NewGuidPayloadMacro()
|
||||||
|
: base("NewGuid", "Generate GUID")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override string GetValue()
|
||||||
|
{
|
||||||
|
return Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
PettingZoo.Core/Macros/PayloadMacroProcessor.cs
Normal file
41
PettingZoo.Core/Macros/PayloadMacroProcessor.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace PettingZoo.Core.Macros
|
||||||
|
{
|
||||||
|
public class PayloadMacroProcessor : IPayloadMacroProcessor
|
||||||
|
{
|
||||||
|
private readonly BasePayloadMacro[] macros;
|
||||||
|
public IEnumerable<IPayloadMacro> Macros => macros;
|
||||||
|
|
||||||
|
|
||||||
|
public PayloadMacroProcessor()
|
||||||
|
{
|
||||||
|
macros = new BasePayloadMacro[]
|
||||||
|
{
|
||||||
|
new NewGuidPayloadMacro(),
|
||||||
|
new JsonDateTimePayloadMacro()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For now we only support simple one-keyboard macros, but this could be extended with parameters if required
|
||||||
|
private static readonly Regex MacroRegex = new("{{(.+?)}}", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
|
||||||
|
public string Apply(string payload)
|
||||||
|
{
|
||||||
|
return MacroRegex.Replace(payload, match =>
|
||||||
|
{
|
||||||
|
var macroCommand = match.Groups[1].Value.Trim();
|
||||||
|
var macro = macros.FirstOrDefault(m => string.Equals(m.MacroCommand, macroCommand, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|
||||||
|
return macro != null
|
||||||
|
? macro.GetValue()
|
||||||
|
: match.Groups[0].Value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
using RabbitMQ.Client.Events;
|
using RabbitMQ.Client.Events;
|
||||||
@ -29,14 +28,12 @@ namespace PettingZoo.RabbitMQ
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ValueTask DisposeAsync()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
if (model != null && consumerTag != null && model.IsOpen)
|
if (model != null && consumerTag != null && model.IsOpen)
|
||||||
model.BasicCancelNoWait(consumerTag);
|
model.BasicCancelNoWait(consumerTag);
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ using System.Runtime.Loader;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using PettingZoo.Core.Generator;
|
using PettingZoo.Core.Generator;
|
||||||
using PettingZoo.Core.Validation;
|
using PettingZoo.Core.Validation;
|
||||||
|
using Tapeti.Default;
|
||||||
|
|
||||||
namespace PettingZoo.Tapeti.AssemblyParser
|
namespace PettingZoo.Tapeti.AssemblyParser
|
||||||
{
|
{
|
||||||
@ -83,6 +84,24 @@ namespace PettingZoo.Tapeti.AssemblyParser
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool TryGetPublishDestination(out string exchange, out string routingKey)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Assume default strategies are used
|
||||||
|
exchange = new NamespaceMatchExchangeStrategy().GetExchange(type);
|
||||||
|
routingKey = new TypeNameRoutingKeyStrategy().GetRoutingKey(type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
exchange = "";
|
||||||
|
routingKey = "";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool CanValidate()
|
public bool CanValidate()
|
||||||
{
|
{
|
||||||
return InitializeValidation();
|
return InitializeValidation();
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="6.0.0" />
|
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Tapeti" Version="2.8.2" />
|
||||||
<PackageReference Include="Tapeti.Annotations" Version="3.0.0" />
|
<PackageReference Include="Tapeti.Annotations" Version="3.0.0" />
|
||||||
<PackageReference Include="Tapeti.DataAnnotations.Extensions" Version="3.0.0" />
|
<PackageReference Include="Tapeti.DataAnnotations.Extensions" Version="3.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -5,7 +5,6 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Threading;
|
|
||||||
using PettingZoo.Core.Generator;
|
using PettingZoo.Core.Generator;
|
||||||
using PettingZoo.Core.Settings;
|
using PettingZoo.Core.Settings;
|
||||||
using PettingZoo.Tapeti.AssemblyLoader;
|
using PettingZoo.Tapeti.AssemblyLoader;
|
||||||
|
@ -300,6 +300,14 @@ namespace PettingZoo.Tapeti.UI.ClassSelection
|
|||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool TryGetPublishDestination(out string exchange, out string routingKey)
|
||||||
|
{
|
||||||
|
exchange = "";
|
||||||
|
routingKey = "";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,12 @@
|
|||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Key="ButtonIcon" TargetType="{x:Type Image}">
|
||||||
|
<Setter Property="Margin" Value="0,0,8,0" />
|
||||||
|
<Setter Property="Width" Value="16" />
|
||||||
|
<Setter Property="Height" Value="16" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
<Style x:Key="Timestamp" TargetType="{x:Type TextBlock}">
|
<Style x:Key="Timestamp" TargetType="{x:Type TextBlock}">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
|
6
PettingZoo/Images/RabbitMQ.svg
Normal file
6
PettingZoo/Images/RabbitMQ.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="256px" height="271px" viewBox="0 0 256 271" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||||
|
<g>
|
||||||
|
<path d="M245.44,108.307692 L160.349538,108.307692 C156.081231,108.307692 152.615385,104.841846 152.615385,100.573538 L152.615385,11.8941538 C152.615385,5.32676923 147.288615,0 140.726154,0 L110.350769,0 C103.783385,0 98.4615385,5.32676923 98.4615385,11.8941538 L98.4615385,100.036923 C98.4615385,104.610462 94.7643077,108.327385 90.1907692,108.347077 L62.3064615,108.48 C57.6935385,108.504615 53.9470769,104.763077 53.9569231,100.155077 L54.1292308,11.9138462 C54.144,5.33661538 48.8172308,0 42.24,0 L11.8892308,0 C5.32184615,0 0,5.32676923 0,11.8941538 L0,260.209231 C0,266.043077 4.72615385,270.769231 10.5550769,270.769231 L245.44,270.769231 C251.273846,270.769231 256,266.043077 256,260.209231 L256,118.867692 C256,113.033846 251.273846,108.307692 245.44,108.307692 L245.44,108.307692 Z M205.538462,201.540923 C205.538462,209.186462 199.340308,215.384615 191.694769,215.384615 L167.689846,215.384615 C160.044308,215.384615 153.846154,209.186462 153.846154,201.540923 L153.846154,177.536 C153.846154,169.890462 160.044308,163.692308 167.689846,163.692308 L191.694769,163.692308 C199.340308,163.692308 205.538462,169.890462 205.538462,177.536 L205.538462,201.540923 L205.538462,201.540923 Z" fill="#FF6600"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
BIN
PettingZoo/Images/Tapeti.png
Normal file
BIN
PettingZoo/Images/Tapeti.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
@ -28,6 +28,8 @@
|
|||||||
<None Remove="Images\Import.svg" />
|
<None Remove="Images\Import.svg" />
|
||||||
<None Remove="Images\Ok.svg" />
|
<None Remove="Images\Ok.svg" />
|
||||||
<None Remove="Images\PublishSend.svg" />
|
<None Remove="Images\PublishSend.svg" />
|
||||||
|
<None Remove="Images\RabbitMQ.svg" />
|
||||||
|
<None Remove="Images\Tapeti.png" />
|
||||||
<None Remove="Images\Undock.svg" />
|
<None Remove="Images\Undock.svg" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@ -44,6 +46,7 @@
|
|||||||
<Resource Include="Images\Ok.svg" />
|
<Resource Include="Images\Ok.svg" />
|
||||||
<Resource Include="Images\Publish.svg" />
|
<Resource Include="Images\Publish.svg" />
|
||||||
<Resource Include="Images\PublishSend.svg" />
|
<Resource Include="Images\PublishSend.svg" />
|
||||||
|
<Resource Include="Images\RabbitMQ.svg" />
|
||||||
<Resource Include="Images\Subscribe.svg" />
|
<Resource Include="Images\Subscribe.svg" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@ -66,6 +69,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Resource Include="Images\Tapeti.png" />
|
||||||
<Resource Include="Images\Undock.svg" />
|
<Resource Include="Images\Undock.svg" />
|
||||||
<Resource Include="Images\Busy.svg" />
|
<Resource Include="Images\Busy.svg" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -144,7 +148,7 @@
|
|||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Update="UI\Tab\Publisher\PayloadEditorStrings.resx">
|
<EmbeddedResource Update="UI\Tab\Publisher\PayloadEditorStrings.resx">
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
<LastGenOutput>PayloadEditorStrings.Designer.cs</LastGenOutput>
|
<LastGenOutput>PayloadEditorStrings.Designer.cs</LastGenOutput>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Update="UI\Tab\Publisher\TapetiPublisherViewStrings.resx">
|
<EmbeddedResource Update="UI\Tab\Publisher\TapetiPublisherViewStrings.resx">
|
||||||
|
@ -6,6 +6,7 @@ using System.Windows.Markup;
|
|||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using PettingZoo.Core.ExportImport;
|
using PettingZoo.Core.ExportImport;
|
||||||
using PettingZoo.Core.Generator;
|
using PettingZoo.Core.Generator;
|
||||||
|
using PettingZoo.Core.Macros;
|
||||||
using PettingZoo.Core.Settings;
|
using PettingZoo.Core.Settings;
|
||||||
using PettingZoo.RabbitMQ;
|
using PettingZoo.RabbitMQ;
|
||||||
using PettingZoo.Settings.LiteDB;
|
using PettingZoo.Settings.LiteDB;
|
||||||
@ -84,6 +85,7 @@ namespace PettingZoo
|
|||||||
container.Register<IExampleGenerator, TapetiClassLibraryExampleGenerator>();
|
container.Register<IExampleGenerator, TapetiClassLibraryExampleGenerator>();
|
||||||
container.RegisterSingleton<ITabHostProvider, TabHostProvider>();
|
container.RegisterSingleton<ITabHostProvider, TabHostProvider>();
|
||||||
container.Register<ITabFactory, ViewTabFactory>();
|
container.Register<ITabFactory, ViewTabFactory>();
|
||||||
|
container.RegisterSingleton<IPayloadMacroProcessor, PayloadMacroProcessor>();
|
||||||
|
|
||||||
container.RegisterInstance<IExportImportFormatProvider>(new ExportImportFormatProvider(
|
container.RegisterInstance<IExportImportFormatProvider>(new ExportImportFormatProvider(
|
||||||
new TapetiCmdExportFormat(),
|
new TapetiCmdExportFormat(),
|
||||||
|
@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
Should-have
|
Should-have
|
||||||
-----------
|
-----------
|
||||||
- Single tab for responses, don't create a new subscriber tab for 1 message each time
|
|
||||||
Use the CorrelationId in the list for such cases instead of the routing key (which is the name of the dynamic queue for the responses).
|
|
||||||
Set the CorrelationId to the request routing key for example, so the different responses can be somewhat identified.
|
|
||||||
|
|
||||||
|
|
||||||
Nice-to-have
|
Nice-to-have
|
||||||
|
@ -170,7 +170,7 @@ namespace PettingZoo.UI.Main
|
|||||||
if (connectionSettings.Subscribe)
|
if (connectionSettings.Subscribe)
|
||||||
{
|
{
|
||||||
var subscriber = connection.Subscribe(connectionSettings.Exchange, connectionSettings.RoutingKey);
|
var subscriber = connection.Subscribe(connectionSettings.Exchange, connectionSettings.RoutingKey);
|
||||||
AddTab(tabFactory.CreateSubscriberTab(connection, subscriber));
|
tabFactory.CreateSubscriberTab(connection, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionChanged();
|
ConnectionChanged();
|
||||||
@ -214,7 +214,7 @@ namespace PettingZoo.UI.Main
|
|||||||
subscribeDialogParams = newParams;
|
subscribeDialogParams = newParams;
|
||||||
|
|
||||||
var subscriber = connection.Subscribe(subscribeDialogParams.Exchange, subscribeDialogParams.RoutingKey);
|
var subscriber = connection.Subscribe(subscribeDialogParams.Exchange, subscribeDialogParams.RoutingKey);
|
||||||
AddTab(tabFactory.CreateSubscriberTab(connection, subscriber));
|
tabFactory.CreateSubscriberTab(connection, subscriber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ namespace PettingZoo.UI.Main
|
|||||||
if (connection == null)
|
if (connection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AddTab(tabFactory.CreatePublisherTab(connection));
|
tabFactory.CreatePublisherTab(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -235,7 +235,8 @@ namespace PettingZoo.UI.Main
|
|||||||
|
|
||||||
private void CloseTabExecute()
|
private void CloseTabExecute()
|
||||||
{
|
{
|
||||||
RemoveActiveTab();
|
var tab = RemoveActiveTab();
|
||||||
|
(tab as IDisposable)?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -300,8 +301,7 @@ namespace PettingZoo.UI.Main
|
|||||||
progressWindow.Close();
|
progressWindow.Close();
|
||||||
progressWindow = null;
|
progressWindow = null;
|
||||||
|
|
||||||
AddTab(tabFactory.CreateSubscriberTab(connection,
|
tabFactory.CreateSubscriberTab(connection, new ImportSubscriber(filename, messages));
|
||||||
new ImportSubscriber(filename, messages)));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
@ -377,6 +377,15 @@ namespace PettingZoo.UI.Main
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ActivateTab(ITab tab)
|
||||||
|
{
|
||||||
|
if (undockedTabs.TryGetValue(tab, out var window))
|
||||||
|
window.Activate();
|
||||||
|
else if (Tabs.Contains(tab))
|
||||||
|
ActiveTab = tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void DockTab(ITab tab)
|
public void DockTab(ITab tab)
|
||||||
{
|
{
|
||||||
if (undockedTabs.Remove(tab, out var tabHostWindow))
|
if (undockedTabs.Remove(tab, out var tabHostWindow))
|
||||||
|
@ -2,13 +2,10 @@
|
|||||||
|
|
||||||
namespace PettingZoo.UI.Tab
|
namespace PettingZoo.UI.Tab
|
||||||
{
|
{
|
||||||
// Passing the closeTabCommand is necessary because I haven't figured out how to bind the main window's
|
|
||||||
// context menu items for the tab to the main window's datacontext yet. RelativeSource doesn't seem to work
|
|
||||||
// because the popup is it's own window. Refactor if a better solution is found.
|
|
||||||
|
|
||||||
public interface ITabFactory
|
public interface ITabFactory
|
||||||
{
|
{
|
||||||
ITab CreateSubscriberTab(IConnection? connection, ISubscriber subscriber);
|
void CreateSubscriberTab(IConnection? connection, ISubscriber subscriber);
|
||||||
ITab CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null);
|
string CreateReplySubscriberTab(IConnection connection);
|
||||||
|
void CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
public interface ITabHost
|
public interface ITabHost
|
||||||
{
|
{
|
||||||
void AddTab(ITab tab);
|
void AddTab(ITab tab);
|
||||||
|
void ActivateTab(ITab tab);
|
||||||
|
|
||||||
void DockTab(ITab tab);
|
void DockTab(ITab tab);
|
||||||
void UndockedTabClosed(ITab tab);
|
void UndockedTabClosed(ITab tab);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
string Exchange { get; }
|
string Exchange { get; }
|
||||||
string RoutingKey { get; }
|
string RoutingKey { get; }
|
||||||
|
|
||||||
string? GetReplyTo();
|
string? GetReplyTo(ref string? correlationId);
|
||||||
|
void SetExchangeDestination(string exchange, string routingKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,18 +21,36 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Visibility="{Binding ValidationVisibility}" Margin="0,8,0,0">
|
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Visibility="{Binding ValidationVisibility}" Margin="0,8,0,0">
|
||||||
<Image Source="{svgc:SvgImage Source=/Images/Ok.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="4" Visibility="{Binding ValidationOk}" />
|
<Image Source="{svgc:SvgImage Source=/Images/Ok.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="1,4,0,0" Visibility="{Binding ValidationOk}" />
|
||||||
<Image Source="{svgc:SvgImage Source=/Images/Error.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="4" Visibility="{Binding ValidationError}" />
|
<Image Source="{svgc:SvgImage Source=/Images/Error.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="1,4,0,0" Visibility="{Binding ValidationError}" />
|
||||||
<Image Source="{svgc:SvgImage Source=/Images/Busy.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="4" Visibility="{Binding ValidationValidating}" />
|
<Image Source="{svgc:SvgImage Source=/Images/Busy.svg, AppName=PettingZoo}" Width="16" Height="16" Margin="1,4,0,0" Visibility="{Binding ValidationValidating}" />
|
||||||
<TextBlock Text="{Binding ValidationMessage}" Margin="4" />
|
<TextBlock Text="{Binding ValidationMessage}" Margin="4" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Margin="0,8,0,0">
|
||||||
|
<CheckBox Content="{x:Static publisher:PayloadEditorStrings.CheckEnableMacros}" VerticalAlignment="Center" IsChecked="{Binding EnableMacros}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
|
||||||
<Border Style="{StaticResource ControlBorder}" Name="EditorBorder">
|
<Border Style="{StaticResource ControlBorder}" Name="EditorBorder">
|
||||||
<avalonedit:TextEditor
|
<avalonedit:TextEditor
|
||||||
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
|
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
|
||||||
Name="Editor"
|
Name="Editor"
|
||||||
SyntaxHighlighting="{Binding SyntaxHighlighting}"
|
SyntaxHighlighting="{Binding SyntaxHighlighting}"
|
||||||
Style="{StaticResource Payload}" />
|
Style="{StaticResource Payload}">
|
||||||
|
<avalonedit:TextEditor.ContextMenu>
|
||||||
|
<ContextMenu Opened="ContextMenu_OnOpened">
|
||||||
|
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuUndo}" Name="ContextMenuUndo" Click="Undo_Click" InputGestureText="Ctrl+Z" />
|
||||||
|
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuRedo}" Name="ContextMenuRedo" Click="Redo_Click" InputGestureText="Ctrl+Y "/>
|
||||||
|
<Separator/>
|
||||||
|
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuCut}" Name="ContextMenuCut" Click="Cut_Click" InputGestureText="Ctrl+X "/>
|
||||||
|
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuCopy}" Name="ContextMenuCopy" Click="Copy_Click" InputGestureText="Ctrl+C "/>
|
||||||
|
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuPaste}" Name="ContextMenuPaste" Click="Paste_Click" InputGestureText="Ctrl+V "/>
|
||||||
|
<Separator/>
|
||||||
|
<MenuItem Header="{x:Static publisher:PayloadEditorStrings.ContextMenuInsertMacro}" Name="ContextMenuInsertMacro" />
|
||||||
|
</ContextMenu>
|
||||||
|
</avalonedit:TextEditor.ContextMenu>
|
||||||
|
</avalonedit:TextEditor>
|
||||||
</Border>
|
</Border>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
|
using PettingZoo.Core.Macros;
|
||||||
using PettingZoo.Core.Validation;
|
using PettingZoo.Core.Validation;
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Publisher
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
@ -88,6 +90,32 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly DependencyProperty EnableMacrosProperty
|
||||||
|
= DependencyProperty.Register(
|
||||||
|
"EnableMacros",
|
||||||
|
typeof(bool),
|
||||||
|
typeof(PayloadEditorControl),
|
||||||
|
new FrameworkPropertyMetadata(false)
|
||||||
|
{
|
||||||
|
BindsTwoWayByDefault = true,
|
||||||
|
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
public bool EnableMacros
|
||||||
|
{
|
||||||
|
get => viewModel.EnableMacros;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == viewModel.EnableMacros)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetValue(EnableMacrosProperty, value);
|
||||||
|
viewModel.EnableMacros = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IPayloadValidator? Validator
|
public IPayloadValidator? Validator
|
||||||
{
|
{
|
||||||
get => viewModel.Validator;
|
get => viewModel.Validator;
|
||||||
@ -95,6 +123,21 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private IPayloadMacroProcessor? macroProcessor;
|
||||||
|
public IPayloadMacroProcessor? MacroProcessor
|
||||||
|
{
|
||||||
|
get => macroProcessor;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == macroProcessor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
macroProcessor = value;
|
||||||
|
UpdateMacroContextMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private readonly ErrorHighlightingTransformer errorHighlightingTransformer = new();
|
private readonly ErrorHighlightingTransformer errorHighlightingTransformer = new();
|
||||||
|
|
||||||
public PayloadEditorControl()
|
public PayloadEditorControl()
|
||||||
@ -123,6 +166,12 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
viewModel.Payload = value;
|
viewModel.Payload = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.OnPropertyChanges<bool>(EnableMacrosProperty)
|
||||||
|
.ObserveOn(SynchronizationContext.Current!)
|
||||||
|
.Subscribe(value =>
|
||||||
|
{
|
||||||
|
viewModel.EnableMacros = value;
|
||||||
|
});
|
||||||
|
|
||||||
viewModel.PropertyChanged += (_, args) =>
|
viewModel.PropertyChanged += (_, args) =>
|
||||||
{
|
{
|
||||||
@ -139,6 +188,10 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
case nameof(viewModel.Payload):
|
case nameof(viewModel.Payload):
|
||||||
SetValue(PayloadProperty, viewModel.Payload);
|
SetValue(PayloadProperty, viewModel.Payload);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case nameof(viewModel.EnableMacros):
|
||||||
|
SetValue(EnableMacrosProperty, viewModel.EnableMacros);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -207,5 +260,70 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
// so I've moved the ViewModel one level down to get the best of both worlds...
|
// so I've moved the ViewModel one level down to get the best of both worlds...
|
||||||
DataContextContainer.DataContext = viewModel;
|
DataContextContainer.DataContext = viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void UpdateMacroContextMenu()
|
||||||
|
{
|
||||||
|
ContextMenuInsertMacro.Items.Clear();
|
||||||
|
|
||||||
|
if (macroProcessor == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var macro in macroProcessor.Macros)
|
||||||
|
{
|
||||||
|
var macroMenuItem = new MenuItem
|
||||||
|
{
|
||||||
|
Header = macro.DisplayName
|
||||||
|
};
|
||||||
|
|
||||||
|
macroMenuItem.Click += (_, _) =>
|
||||||
|
{
|
||||||
|
Editor.SelectedText = macro.MacroText;
|
||||||
|
|
||||||
|
var length = Editor.SelectionLength;
|
||||||
|
Editor.SelectionLength = 0;
|
||||||
|
Editor.SelectionStart += length;
|
||||||
|
|
||||||
|
viewModel.EnableMacros = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ContextMenuInsertMacro.Items.Add(macroMenuItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Undo_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Editor.Undo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Redo_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Editor.Redo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cut_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Editor.Cut();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Copy_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Editor.Copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Paste_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Editor.Paste();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ContextMenu_OnOpened(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ContextMenuUndo.IsEnabled = Editor.CanUndo;
|
||||||
|
ContextMenuRedo.IsEnabled = Editor.CanRedo;
|
||||||
|
ContextMenuCut.IsEnabled = Editor.SelectionLength > 0;
|
||||||
|
ContextMenuCopy.IsEnabled = Editor.SelectionLength > 0;
|
||||||
|
ContextMenuPaste.IsEnabled = Clipboard.ContainsText();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
internal class PayloadEditorStrings {
|
public class PayloadEditorStrings {
|
||||||
|
|
||||||
private static global::System.Resources.ResourceManager resourceMan;
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
/// Returns the cached ResourceManager instance used by this class.
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
public static global::System.Resources.ResourceManager ResourceManager {
|
||||||
get {
|
get {
|
||||||
if (object.ReferenceEquals(resourceMan, null)) {
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.UI.Tab.Publisher.PayloadEditorStrings", typeof(PayloadEditorStrings).Assembly);
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.UI.Tab.Publisher.PayloadEditorStrings", typeof(PayloadEditorStrings).Assembly);
|
||||||
@ -51,7 +51,7 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
/// resource lookups using this strongly typed resource class.
|
/// resource lookups using this strongly typed resource class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
internal static global::System.Globalization.CultureInfo Culture {
|
public static global::System.Globalization.CultureInfo Culture {
|
||||||
get {
|
get {
|
||||||
return resourceCulture;
|
return resourceCulture;
|
||||||
}
|
}
|
||||||
@ -60,10 +60,19 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Enable macros (right-click editor to insert).
|
||||||
|
/// </summary>
|
||||||
|
public static string CheckEnableMacros {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("CheckEnableMacros", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to JSON.
|
/// Looks up a localized string similar to JSON.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ContentTypeJson {
|
public static string ContentTypeJson {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ContentTypeJson", resourceCulture);
|
return ResourceManager.GetString("ContentTypeJson", resourceCulture);
|
||||||
}
|
}
|
||||||
@ -72,7 +81,7 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Other.
|
/// Looks up a localized string similar to Other.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ContentTypeOther {
|
public static string ContentTypeOther {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ContentTypeOther", resourceCulture);
|
return ResourceManager.GetString("ContentTypeOther", resourceCulture);
|
||||||
}
|
}
|
||||||
@ -81,16 +90,79 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Plain text.
|
/// Looks up a localized string similar to Plain text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ContentTypePlain {
|
public static string ContentTypePlain {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ContentTypePlain", resourceCulture);
|
return ResourceManager.GetString("ContentTypePlain", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Copy.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContextMenuCopy {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContextMenuCopy", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Cut.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContextMenuCut {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContextMenuCut", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Insert macro.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContextMenuInsertMacro {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContextMenuInsertMacro", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Paste.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContextMenuPaste {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContextMenuPaste", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Redo.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContextMenuRedo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContextMenuRedo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Undo.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContextMenuUndo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContextMenuUndo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Show available macros.
|
||||||
|
/// </summary>
|
||||||
|
public static string ShowMacrosHint {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ShowMacrosHint", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Invalid: {0}.
|
/// Looks up a localized string similar to Invalid: {0}.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ValidationError {
|
public static string ValidationError {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ValidationError", resourceCulture);
|
return ResourceManager.GetString("ValidationError", resourceCulture);
|
||||||
}
|
}
|
||||||
@ -99,7 +171,7 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Valid.
|
/// Looks up a localized string similar to Valid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ValidationOk {
|
public static string ValidationOk {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ValidationOk", resourceCulture);
|
return ResourceManager.GetString("ValidationOk", resourceCulture);
|
||||||
}
|
}
|
||||||
@ -108,7 +180,7 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Valid syntax.
|
/// Looks up a localized string similar to Valid syntax.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ValidationOkSyntax {
|
public static string ValidationOkSyntax {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ValidationOkSyntax", resourceCulture);
|
return ResourceManager.GetString("ValidationOkSyntax", resourceCulture);
|
||||||
}
|
}
|
||||||
@ -117,7 +189,7 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Validating....
|
/// Looks up a localized string similar to Validating....
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string ValidationValidating {
|
public static string ValidationValidating {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("ValidationValidating", resourceCulture);
|
return ResourceManager.GetString("ValidationValidating", resourceCulture);
|
||||||
}
|
}
|
||||||
|
@ -117,6 +117,9 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<data name="CheckEnableMacros" xml:space="preserve">
|
||||||
|
<value>Enable macros (right-click editor to insert)</value>
|
||||||
|
</data>
|
||||||
<data name="ContentTypeJson" xml:space="preserve">
|
<data name="ContentTypeJson" xml:space="preserve">
|
||||||
<value>JSON</value>
|
<value>JSON</value>
|
||||||
</data>
|
</data>
|
||||||
@ -126,6 +129,27 @@
|
|||||||
<data name="ContentTypePlain" xml:space="preserve">
|
<data name="ContentTypePlain" xml:space="preserve">
|
||||||
<value>Plain text</value>
|
<value>Plain text</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ContextMenuCopy" xml:space="preserve">
|
||||||
|
<value>Copy</value>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenuCut" xml:space="preserve">
|
||||||
|
<value>Cut</value>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenuInsertMacro" xml:space="preserve">
|
||||||
|
<value>Insert macro</value>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenuPaste" xml:space="preserve">
|
||||||
|
<value>Paste</value>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenuRedo" xml:space="preserve">
|
||||||
|
<value>Redo</value>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenuUndo" xml:space="preserve">
|
||||||
|
<value>Undo</value>
|
||||||
|
</data>
|
||||||
|
<data name="ShowMacrosHint" xml:space="preserve">
|
||||||
|
<value>Show available macros</value>
|
||||||
|
</data>
|
||||||
<data name="ValidationError" xml:space="preserve">
|
<data name="ValidationError" xml:space="preserve">
|
||||||
<value>Invalid: {0}</value>
|
<value>Invalid: {0}</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
using ICSharpCode.AvalonEdit.Highlighting;
|
using ICSharpCode.AvalonEdit.Highlighting;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
@ -64,6 +65,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
private ValidationInfo validationInfo = new(ValidationStatus.OkSyntax);
|
private ValidationInfo validationInfo = new(ValidationStatus.OkSyntax);
|
||||||
|
|
||||||
private string payload = "";
|
private string payload = "";
|
||||||
|
private bool enableMacros;
|
||||||
|
|
||||||
|
|
||||||
public string ContentType
|
public string ContentType
|
||||||
@ -136,6 +138,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
public Visibility ContentTypeVisibility => FixedJson ? Visibility.Collapsed : Visibility.Visible;
|
public Visibility ContentTypeVisibility => FixedJson ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public string Payload
|
public string Payload
|
||||||
{
|
{
|
||||||
get => payload;
|
get => payload;
|
||||||
@ -143,6 +146,13 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool EnableMacros
|
||||||
|
{
|
||||||
|
get => enableMacros;
|
||||||
|
set => SetField(ref enableMacros, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public IHighlightingDefinition? SyntaxHighlighting => ContentTypeSelection == PayloadEditorContentType.Json
|
public IHighlightingDefinition? SyntaxHighlighting => ContentTypeSelection == PayloadEditorContentType.Json
|
||||||
? HighlightingManager.Instance.GetDefinition(@"Json")
|
? HighlightingManager.Instance.GetDefinition(@"Json")
|
||||||
: null;
|
: null;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:res="clr-namespace:PettingZoo.UI.Tab.Publisher"
|
xmlns:res="clr-namespace:PettingZoo.UI.Tab.Publisher"
|
||||||
xmlns:controls="clr-namespace:PettingZoo.WPF.Controls;assembly=PettingZoo.WPF"
|
xmlns:controls="clr-namespace:PettingZoo.WPF.Controls;assembly=PettingZoo.WPF"
|
||||||
|
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
@ -13,6 +14,8 @@
|
|||||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<controls:GridLayout Style="{StaticResource Form}" Margin="4" Grid.IsSharedSizeScope="True">
|
<controls:GridLayout Style="{StaticResource Form}" Margin="4" Grid.IsSharedSizeScope="True">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="8"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
@ -20,8 +23,7 @@
|
|||||||
<RowDefinition Height="16"/>
|
<RowDefinition Height="16"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="16"/>
|
<RowDefinition Height="16" />
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
@ -30,37 +32,47 @@
|
|||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="1">
|
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1">
|
||||||
|
<ToggleButton Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeRaw}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="{svgc:SvgImage Source=/Images/RabbitMQ.svg, AppName=PettingZoo}" Style="{StaticResource ButtonIcon}" />
|
||||||
|
<TextBlock Text="{x:Static res:PublisherViewStrings.OptionMessageTypeRaw}" />
|
||||||
|
</StackPanel>
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeTapeti}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="/Images/Tapeti.png" Style="{StaticResource ButtonIcon}" />
|
||||||
|
<TextBlock Text="{x:Static res:PublisherViewStrings.OptionMessageTypeTapeti}" />
|
||||||
|
</StackPanel>
|
||||||
|
</ToggleButton>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<Label Grid.Row="2" Grid.Column="1">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelSendToExchange}" IsChecked="{Binding SendToExchange}" Style="{StaticResource TypeSelection}" />
|
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelSendToExchange}" IsChecked="{Binding SendToExchange}" Style="{StaticResource TypeSelection}" />
|
||||||
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelSendToQueue}" IsChecked="{Binding SendToQueue}" Style="{StaticResource TypeSelection}" />
|
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelSendToQueue}" IsChecked="{Binding SendToQueue}" Style="{StaticResource TypeSelection}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Label>
|
</Label>
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelExchange}" Visibility="{Binding ExchangeVisibility}" />
|
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelExchange}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Exchange, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding ExchangeVisibility}" />
|
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Exchange, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelRoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
<Label Grid.Row="4" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelRoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding RoutingKey, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding ExchangeVisibility}" />
|
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding RoutingKey, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelQueue}" Visibility="{Binding QueueVisibility}" />
|
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelQueue}" Visibility="{Binding QueueVisibility}" />
|
||||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Queue, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding QueueVisibility}" />
|
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding Queue, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding QueueVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelReplyTo}" />
|
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelReplyTo}" />
|
||||||
<StackPanel Orientation="Horizontal" Grid.Row="5" Grid.Column="1">
|
<StackPanel Orientation="Horizontal" Grid.Row="7" Grid.Column="1">
|
||||||
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelReplyToSpecified}" IsChecked="{Binding ReplyToSpecified}" Style="{StaticResource TypeSelection}" />
|
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelReplyToSpecified}" IsChecked="{Binding ReplyToSpecified}" Style="{StaticResource TypeSelection}" />
|
||||||
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelReplyToNewSubscriber}" IsChecked="{Binding ReplyToNewSubscriber}" Style="{StaticResource TypeSelection}" />
|
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelReplyToNewSubscriber}" IsChecked="{Binding ReplyToNewSubscriber}" Style="{StaticResource TypeSelection}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding ReplyTo}" IsEnabled="{Binding ReplyToSpecified}" />
|
<TextBox Grid.Row="8" Grid.Column="1" Text="{Binding ReplyTo}" IsEnabled="{Binding ReplyToSpecified}" />
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center">
|
<ContentControl Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="2" Margin="0 8 0 0" Content="{Binding MessageTypeControl}" />
|
||||||
<ToggleButton Content="{x:Static res:PublisherViewStrings.OptionMessageTypeRaw}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeRaw}" />
|
|
||||||
<ToggleButton Content="{x:Static res:PublisherViewStrings.OptionMessageTypeTapeti}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeTapeti}" />
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<ContentControl Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="2" Margin="0 8 0 0" Content="{Binding MessageTypeControl}" />
|
<Button Grid.Row="11" Grid.Column="1" Command="{Binding PublishCommand}" Content="{x:Static res:PublisherViewStrings.CommandPublish}" HorizontalAlignment="Left" />
|
||||||
|
|
||||||
<Button Grid.Row="10" Grid.Column="1" Command="{Binding PublishCommand}" Content="{x:Static res:PublisherViewStrings.CommandPublish}" HorizontalAlignment="Left" />
|
|
||||||
</controls:GridLayout>
|
</controls:GridLayout>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -5,6 +5,7 @@ using System.Windows.Controls;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using PettingZoo.Core.Generator;
|
using PettingZoo.Core.Generator;
|
||||||
|
using PettingZoo.Core.Macros;
|
||||||
using PettingZoo.WPF.ViewModel;
|
using PettingZoo.WPF.ViewModel;
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Publisher
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
@ -20,8 +21,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
{
|
{
|
||||||
private readonly IConnection connection;
|
private readonly IConnection connection;
|
||||||
private readonly IExampleGenerator exampleGenerator;
|
private readonly IExampleGenerator exampleGenerator;
|
||||||
|
private readonly IPayloadMacroProcessor payloadMacroProcessor;
|
||||||
private readonly ITabFactory tabFactory;
|
private readonly ITabFactory tabFactory;
|
||||||
private readonly ITabHostProvider tabHostProvider;
|
|
||||||
|
|
||||||
private bool sendToExchange = true;
|
private bool sendToExchange = true;
|
||||||
private string exchange = "";
|
private string exchange = "";
|
||||||
@ -156,12 +157,12 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
string IPublishDestination.RoutingKey => SendToExchange ? RoutingKey : Queue;
|
string IPublishDestination.RoutingKey => SendToExchange ? RoutingKey : Queue;
|
||||||
|
|
||||||
|
|
||||||
public PublisherViewModel(ITabHostProvider tabHostProvider, ITabFactory tabFactory, IConnection connection, IExampleGenerator exampleGenerator, ReceivedMessageInfo? fromReceivedMessage = null)
|
public PublisherViewModel(ITabFactory tabFactory, IConnection connection, IExampleGenerator exampleGenerator, IPayloadMacroProcessor payloadMacroProcessor, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||||
{
|
{
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.exampleGenerator = exampleGenerator;
|
this.exampleGenerator = exampleGenerator;
|
||||||
|
this.payloadMacroProcessor = payloadMacroProcessor;
|
||||||
this.tabFactory = tabFactory;
|
this.tabFactory = tabFactory;
|
||||||
this.tabHostProvider = tabHostProvider;
|
|
||||||
|
|
||||||
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||||
|
|
||||||
@ -209,7 +210,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
if (rawPublisherView == null)
|
if (rawPublisherView == null)
|
||||||
{
|
{
|
||||||
rawPublisherViewModel = new RawPublisherViewModel(connection, this);
|
rawPublisherViewModel = new RawPublisherViewModel(connection, this, payloadMacroProcessor);
|
||||||
rawPublisherViewModel.PublishCommand.CanExecuteChanged += (_, _) =>
|
rawPublisherViewModel.PublishCommand.CanExecuteChanged += (_, _) =>
|
||||||
{
|
{
|
||||||
publishCommand.RaiseCanExecuteChanged();
|
publishCommand.RaiseCanExecuteChanged();
|
||||||
@ -230,7 +231,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
if (tapetiPublisherView == null)
|
if (tapetiPublisherView == null)
|
||||||
{
|
{
|
||||||
tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, exampleGenerator);
|
tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, exampleGenerator, payloadMacroProcessor);
|
||||||
tapetiPublisherViewModel.PublishCommand.CanExecuteChanged += (_, _) =>
|
tapetiPublisherViewModel.PublishCommand.CanExecuteChanged += (_, _) =>
|
||||||
{
|
{
|
||||||
publishCommand.RaiseCanExecuteChanged();
|
publishCommand.RaiseCanExecuteChanged();
|
||||||
@ -265,14 +266,14 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
if (TapetiPublisherViewModel.IsTapetiMessage(fromReceivedMessage))
|
if (TapetiPublisherViewModel.IsTapetiMessage(fromReceivedMessage))
|
||||||
{
|
{
|
||||||
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, exampleGenerator, fromReceivedMessage);
|
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, exampleGenerator, payloadMacroProcessor, fromReceivedMessage);
|
||||||
tapetiPublisherView = new TapetiPublisherView(tapetiPublisherViewModel);
|
tapetiPublisherView = new TapetiPublisherView(tapetiPublisherViewModel);
|
||||||
|
|
||||||
MessageType = MessageType.Tapeti;
|
MessageType = MessageType.Tapeti;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var rawPublisherViewModel = new RawPublisherViewModel(connection, this, fromReceivedMessage);
|
var rawPublisherViewModel = new RawPublisherViewModel(connection, this, payloadMacroProcessor, fromReceivedMessage);
|
||||||
rawPublisherView = new RawPublisherView(rawPublisherViewModel);
|
rawPublisherView = new RawPublisherView(rawPublisherViewModel);
|
||||||
|
|
||||||
MessageType = MessageType.Raw;
|
MessageType = MessageType.Raw;
|
||||||
@ -280,17 +281,20 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public string? GetReplyTo()
|
public string? GetReplyTo(ref string? correlationId)
|
||||||
{
|
{
|
||||||
if (ReplyToSpecified)
|
if (ReplyToSpecified)
|
||||||
return string.IsNullOrEmpty(ReplyTo) ? null : ReplyTo;
|
return string.IsNullOrEmpty(ReplyTo) ? null : ReplyTo;
|
||||||
|
|
||||||
var subscriber = connection.Subscribe();
|
correlationId = PublisherViewStrings.ReplyToCorrelationIdPrefix + (SendToExchange ? RoutingKey : Queue);
|
||||||
var tab = tabFactory.CreateSubscriberTab(connection, subscriber);
|
return tabFactory.CreateReplySubscriberTab(connection);
|
||||||
tabHostProvider.Instance.AddTab(tab);
|
}
|
||||||
|
|
||||||
subscriber.Start();
|
|
||||||
return subscriber.QueueName;
|
public void SetExchangeDestination(string newExchange, string newRoutingKey)
|
||||||
|
{
|
||||||
|
Exchange = newExchange;
|
||||||
|
RoutingKey = newRoutingKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,6 +168,15 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Re: .
|
||||||
|
/// </summary>
|
||||||
|
public static string ReplyToCorrelationIdPrefix {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ReplyToCorrelationIdPrefix", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Publish: {0}.
|
/// Looks up a localized string similar to Publish: {0}.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -112,10 +112,10 @@
|
|||||||
<value>2.0</value>
|
<value>2.0</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="reader">
|
<resheader name="reader">
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="CommandPublish" xml:space="preserve">
|
<data name="CommandPublish" xml:space="preserve">
|
||||||
<value>Publish</value>
|
<value>Publish</value>
|
||||||
@ -153,6 +153,9 @@
|
|||||||
<data name="OptionMessageTypeTapeti" xml:space="preserve">
|
<data name="OptionMessageTypeTapeti" xml:space="preserve">
|
||||||
<value>Tapeti message</value>
|
<value>Tapeti message</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ReplyToCorrelationIdPrefix" xml:space="preserve">
|
||||||
|
<value>Re: </value>
|
||||||
|
</data>
|
||||||
<data name="TabTitle" xml:space="preserve">
|
<data name="TabTitle" xml:space="preserve">
|
||||||
<value>Publish: {0}</value>
|
<value>Publish: {0}</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -131,6 +131,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Label Grid.Row="14" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPayload}" />
|
<Label Grid.Row="14" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPayload}" />
|
||||||
<publisher:PayloadEditorControl Grid.Row="14" Grid.Column="1" Payload="{Binding Payload}" ContentType="{Binding ContentType}" Height="350"/>
|
<publisher:PayloadEditorControl Grid.Row="14" Grid.Column="1" Payload="{Binding Payload}" ContentType="{Binding ContentType}" Height="350" x:Name="PayloadEditor"
|
||||||
|
EnableMacros="{Binding EnableMacros}" />
|
||||||
</controls:GridLayout>
|
</controls:GridLayout>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
using PettingZoo.Core.Macros;
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Publisher
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
{
|
{
|
||||||
@ -22,6 +23,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
PayloadEditor.MacroProcessor = viewModel.PayloadMacroProcessor;
|
||||||
|
|
||||||
checkEmptyHeaderTimer = new DispatcherTimer();
|
checkEmptyHeaderTimer = new DispatcherTimer();
|
||||||
checkEmptyHeaderTimer.Tick += CheckEmptyHeaderTimerOnTick;
|
checkEmptyHeaderTimer.Tick += CheckEmptyHeaderTimerOnTick;
|
||||||
checkEmptyHeaderTimer.Interval = TimeSpan.FromMilliseconds(50);
|
checkEmptyHeaderTimer.Interval = TimeSpan.FromMilliseconds(50);
|
||||||
|
@ -7,6 +7,7 @@ using System.Text;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
|
using PettingZoo.Core.Macros;
|
||||||
using PettingZoo.WPF.ViewModel;
|
using PettingZoo.WPF.ViewModel;
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Publisher
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
@ -32,6 +33,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
private string typeProperty = "";
|
private string typeProperty = "";
|
||||||
private string userId = "";
|
private string userId = "";
|
||||||
private string payload = "";
|
private string payload = "";
|
||||||
|
private bool enableMacros;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -118,6 +120,12 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
set => SetField(ref payload, value, delegateCommandsChanged: new [] { publishCommand });
|
set => SetField(ref payload, value, delegateCommandsChanged: new [] { publishCommand });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool EnableMacros
|
||||||
|
{
|
||||||
|
get => enableMacros;
|
||||||
|
set => SetField(ref enableMacros, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ObservableCollection<Header> Headers { get; } = new();
|
public ObservableCollection<Header> Headers { get; } = new();
|
||||||
|
|
||||||
@ -125,6 +133,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
public ICommand PublishCommand => publishCommand;
|
public ICommand PublishCommand => publishCommand;
|
||||||
public ICommand PropertiesExpandCollapseCommand => propertiesExpandCollapseCommand;
|
public ICommand PropertiesExpandCollapseCommand => propertiesExpandCollapseCommand;
|
||||||
|
|
||||||
|
public IPayloadMacroProcessor PayloadMacroProcessor { get; }
|
||||||
|
|
||||||
|
|
||||||
public bool PropertiesExpanded
|
public bool PropertiesExpanded
|
||||||
{
|
{
|
||||||
@ -145,8 +155,10 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
protected Header LastHeader;
|
protected Header LastHeader;
|
||||||
|
|
||||||
|
|
||||||
public RawPublisherViewModel(IConnection connection, IPublishDestination publishDestination, BaseMessageInfo? receivedMessage = null)
|
public RawPublisherViewModel(IConnection connection, IPublishDestination publishDestination, IPayloadMacroProcessor payloadMacroProcessor, BaseMessageInfo? receivedMessage = null)
|
||||||
{
|
{
|
||||||
|
PayloadMacroProcessor = payloadMacroProcessor;
|
||||||
|
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.publishDestination = publishDestination;
|
this.publishDestination = publishDestination;
|
||||||
|
|
||||||
@ -242,24 +254,31 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var encodedPayload = Encoding.UTF8.GetBytes(
|
||||||
|
EnableMacros
|
||||||
|
? PayloadMacroProcessor.Apply(Payload)
|
||||||
|
: Payload
|
||||||
|
);
|
||||||
|
|
||||||
var headers = Headers.Where(h => h.IsValid()).ToDictionary(h => h.Key, h => h.Value);
|
var headers = Headers.Where(h => h.IsValid()).ToDictionary(h => h.Key, h => h.Value);
|
||||||
|
var publishCorrelationId = NullIfEmpty(CorrelationId);
|
||||||
|
var replyTo = publishDestination.GetReplyTo(ref publishCorrelationId);
|
||||||
|
|
||||||
connection.Publish(new PublishMessageInfo(
|
connection.Publish(new PublishMessageInfo(
|
||||||
publishDestination.Exchange,
|
publishDestination.Exchange,
|
||||||
publishDestination.RoutingKey,
|
publishDestination.RoutingKey,
|
||||||
Encoding.UTF8.GetBytes(Payload),
|
encodedPayload,
|
||||||
new MessageProperties(headers)
|
new MessageProperties(headers)
|
||||||
{
|
{
|
||||||
AppId = NullIfEmpty(AppId),
|
AppId = NullIfEmpty(AppId),
|
||||||
ContentEncoding = NullIfEmpty(ContentEncoding),
|
ContentEncoding = NullIfEmpty(ContentEncoding),
|
||||||
ContentType = NullIfEmpty(ContentType),
|
ContentType = NullIfEmpty(ContentType),
|
||||||
CorrelationId = NullIfEmpty(CorrelationId),
|
CorrelationId = publishCorrelationId,
|
||||||
DeliveryMode = deliveryMode,
|
DeliveryMode = deliveryMode,
|
||||||
Expiration = NullIfEmpty(Expiration),
|
Expiration = NullIfEmpty(Expiration),
|
||||||
MessageId = NullIfEmpty(MessageId),
|
MessageId = NullIfEmpty(MessageId),
|
||||||
Priority = priorityValue,
|
Priority = priorityValue,
|
||||||
ReplyTo = publishDestination.GetReplyTo(),
|
ReplyTo = replyTo,
|
||||||
Timestamp = timestampValue,
|
Timestamp = timestampValue,
|
||||||
Type = NullIfEmpty(TypeProperty),
|
Type = NullIfEmpty(TypeProperty),
|
||||||
UserId = NullIfEmpty(UserId)
|
UserId = NullIfEmpty(UserId)
|
||||||
@ -309,7 +328,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
public class DesignTimeRawPublisherViewModel : RawPublisherViewModel
|
public class DesignTimeRawPublisherViewModel : RawPublisherViewModel
|
||||||
{
|
{
|
||||||
public DesignTimeRawPublisherViewModel() : base(null!, null!)
|
public DesignTimeRawPublisherViewModel() : base(null!, null!, null!)
|
||||||
{
|
{
|
||||||
PropertiesExpanded = true;
|
PropertiesExpanded = true;
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelPayload}" />
|
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelPayload}" />
|
||||||
<publisher:PayloadEditorControl Grid.Row="6" Grid.Column="1" Payload="{Binding Payload}" FixedJson="True" Height="350" x:Name="PayloadEditor"/>
|
<publisher:PayloadEditorControl Grid.Row="6" Grid.Column="1" Payload="{Binding Payload}" FixedJson="True" Height="350" x:Name="PayloadEditor"
|
||||||
|
EnableMacros="{Binding EnableMacros}" />
|
||||||
</controls:GridLayout>
|
</controls:GridLayout>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using PettingZoo.Core.Macros;
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Publisher
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
{
|
{
|
||||||
@ -15,6 +16,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
PayloadEditor.Validator = viewModel;
|
PayloadEditor.Validator = viewModel;
|
||||||
|
PayloadEditor.MacroProcessor = viewModel.PayloadMacroProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Threading;
|
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using PettingZoo.Core.Generator;
|
using PettingZoo.Core.Generator;
|
||||||
|
using PettingZoo.Core.Macros;
|
||||||
using PettingZoo.Core.Validation;
|
using PettingZoo.Core.Validation;
|
||||||
using PettingZoo.WPF.ViewModel;
|
using PettingZoo.WPF.ViewModel;
|
||||||
using IConnection = PettingZoo.Core.Connection.IConnection;
|
using IConnection = PettingZoo.Core.Connection.IConnection;
|
||||||
@ -21,6 +21,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
private string correlationId = "";
|
private string correlationId = "";
|
||||||
private string payload = "";
|
private string payload = "";
|
||||||
|
private bool enableMacros;
|
||||||
private string className = "";
|
private string className = "";
|
||||||
private string assemblyName = "";
|
private string assemblyName = "";
|
||||||
private Window? tabHostWindow;
|
private Window? tabHostWindow;
|
||||||
@ -68,9 +69,17 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool EnableMacros
|
||||||
|
{
|
||||||
|
get => enableMacros;
|
||||||
|
set => SetField(ref enableMacros, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ICommand PublishCommand => publishCommand;
|
public ICommand PublishCommand => publishCommand;
|
||||||
public ICommand BrowseClassCommand => browseClassCommand;
|
public ICommand BrowseClassCommand => browseClassCommand;
|
||||||
|
|
||||||
|
public IPayloadMacroProcessor PayloadMacroProcessor { get; }
|
||||||
|
|
||||||
|
|
||||||
public static bool IsTapetiMessage(ReceivedMessageInfo receivedMessage)
|
public static bool IsTapetiMessage(ReceivedMessageInfo receivedMessage)
|
||||||
@ -100,8 +109,11 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TapetiPublisherViewModel(IConnection connection, IPublishDestination publishDestination, IExampleGenerator exampleGenerator, ReceivedMessageInfo? receivedMessage = null)
|
public TapetiPublisherViewModel(IConnection connection, IPublishDestination publishDestination, IExampleGenerator exampleGenerator,
|
||||||
|
IPayloadMacroProcessor payloadMacroProcessor, ReceivedMessageInfo? receivedMessage = null)
|
||||||
{
|
{
|
||||||
|
PayloadMacroProcessor = payloadMacroProcessor;
|
||||||
|
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.publishDestination = publishDestination;
|
this.publishDestination = publishDestination;
|
||||||
this.exampleGenerator = exampleGenerator;
|
this.exampleGenerator = exampleGenerator;
|
||||||
@ -135,6 +147,9 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
AssemblyName = classTypeExample.AssemblyName;
|
AssemblyName = classTypeExample.AssemblyName;
|
||||||
ClassName = classTypeExample.FullClassName;
|
ClassName = classTypeExample.FullClassName;
|
||||||
|
|
||||||
|
if (classTypeExample.TryGetPublishDestination(out var exchange, out var routingKey))
|
||||||
|
publishDestination.SetExchangeDestination(exchange, routingKey);
|
||||||
|
|
||||||
validatingExample = classTypeExample as IValidatingExample;
|
validatingExample = classTypeExample as IValidatingExample;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -152,19 +167,29 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
return string.IsNullOrEmpty(value) ? null : value;
|
return string.IsNullOrEmpty(value) ? null : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var encodedPayload = Encoding.UTF8.GetBytes(
|
||||||
|
EnableMacros
|
||||||
|
? PayloadMacroProcessor.Apply(Payload)
|
||||||
|
: Payload
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
var publishCorrelationId = NullIfEmpty(CorrelationId);
|
||||||
|
var replyTo = publishDestination.GetReplyTo(ref publishCorrelationId);
|
||||||
|
|
||||||
connection.Publish(new PublishMessageInfo(
|
connection.Publish(new PublishMessageInfo(
|
||||||
publishDestination.Exchange,
|
publishDestination.Exchange,
|
||||||
publishDestination.RoutingKey,
|
publishDestination.RoutingKey,
|
||||||
Encoding.UTF8.GetBytes(Payload),
|
encodedPayload,
|
||||||
new MessageProperties(new Dictionary<string, string>
|
new MessageProperties(new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
{ @"classType", $"{ClassName}:{AssemblyName}" }
|
{ @"classType", $"{ClassName}:{AssemblyName}" }
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ContentType = @"application/json",
|
ContentType = @"application/json",
|
||||||
CorrelationId = NullIfEmpty(CorrelationId),
|
CorrelationId = publishCorrelationId,
|
||||||
DeliveryMode = MessageDeliveryMode.Persistent,
|
DeliveryMode = MessageDeliveryMode.Persistent,
|
||||||
ReplyTo = publishDestination.GetReplyTo()
|
ReplyTo = replyTo
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +224,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
public class DesignTimeTapetiPublisherViewModel : TapetiPublisherViewModel
|
public class DesignTimeTapetiPublisherViewModel : TapetiPublisherViewModel
|
||||||
{
|
{
|
||||||
public DesignTimeTapetiPublisherViewModel() : base(null!, null!, null!)
|
public DesignTimeTapetiPublisherViewModel() : base(null!, null!, null!, null!)
|
||||||
{
|
{
|
||||||
AssemblyName = "Messaging.Example";
|
AssemblyName = "Messaging.Example";
|
||||||
ClassName = "Messaging.Example.ExampleMessage";
|
ClassName = "Messaging.Example.ExampleMessage";
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Data;
|
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Subscriber
|
|
||||||
{
|
|
||||||
public class SameMessageVisibilityConverter : IMultiValueConverter
|
|
||||||
{
|
|
||||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
|
||||||
{
|
|
||||||
return ReferenceEquals(values[0], values[1])
|
|
||||||
? Visibility.Visible
|
|
||||||
: Visibility.Collapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,9 +13,6 @@
|
|||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance res:DesignTimeSubscriberViewModel, IsDesignTimeCreatable=True}"
|
d:DataContext="{d:DesignInstance res:DesignTimeSubscriberViewModel, IsDesignTimeCreatable=True}"
|
||||||
Background="White">
|
Background="White">
|
||||||
<UserControl.Resources>
|
|
||||||
<res:SameMessageVisibilityConverter x:Key="SameMessageVisibilityConverter" />
|
|
||||||
</UserControl.Resources>
|
|
||||||
<Grid Margin="4">
|
<Grid Margin="4">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
@ -64,7 +61,8 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock Grid.Column="0" Text="{Binding ReceivedTimestamp, StringFormat=g}" Style="{StaticResource Timestamp}" />
|
<TextBlock Grid.Column="0" Text="{Binding ReceivedTimestamp, StringFormat=g}" Style="{StaticResource Timestamp}" />
|
||||||
<TextBlock Grid.Column="1" Text="{Binding RoutingKey}" Style="{StaticResource RoutingKey}" />
|
<TextBlock Grid.Column="1" Text="{Binding RoutingKey}" Style="{StaticResource RoutingKey}" Visibility="{Binding DataContext.StandardTabVisibility, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" />
|
||||||
|
<TextBlock Grid.Column="1" Text="{Binding Properties.CorrelationId}" Style="{StaticResource RoutingKey}" Visibility="{Binding DataContext.ReplyTabVisibility, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" />
|
||||||
|
|
||||||
<Grid.ContextMenu>
|
<Grid.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
|
@ -21,10 +21,9 @@ using Timer = System.Threading.Timer;
|
|||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Subscriber
|
namespace PettingZoo.UI.Tab.Subscriber
|
||||||
{
|
{
|
||||||
public class SubscriberViewModel : BaseViewModel, ITabToolbarCommands, ITabActivate
|
public class SubscriberViewModel : BaseViewModel, IDisposable, ITabToolbarCommands, ITabActivate
|
||||||
{
|
{
|
||||||
private readonly ILogger logger;
|
private readonly ILogger logger;
|
||||||
private readonly ITabHostProvider tabHostProvider;
|
|
||||||
private readonly ITabFactory tabFactory;
|
private readonly ITabFactory tabFactory;
|
||||||
private readonly IConnection? connection;
|
private readonly IConnection? connection;
|
||||||
private readonly ISubscriber subscriber;
|
private readonly ISubscriber subscriber;
|
||||||
@ -76,16 +75,43 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
set => SetField(ref selectedMessageProperties, value);
|
set => SetField(ref selectedMessageProperties, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Title =>
|
public string Title
|
||||||
(subscriber.Exchange != null ? $"{subscriber.Exchange} - {subscriber.RoutingKey}" : $"{subscriber.QueueName}") +
|
{
|
||||||
(tabActive || unreadCount == 0 ? "" : $" ({unreadCount})");
|
get
|
||||||
|
{
|
||||||
|
var title = new StringBuilder();
|
||||||
|
|
||||||
|
if (IsReplyTab)
|
||||||
|
title.Append(SubscriberViewStrings.ReplyTabTitle);
|
||||||
|
else if (subscriber.Exchange != null)
|
||||||
|
title.Append(subscriber.Exchange).Append(" - ").Append(subscriber.RoutingKey);
|
||||||
|
else
|
||||||
|
title.Append(subscriber.QueueName);
|
||||||
|
|
||||||
|
if (!tabActive && unreadCount > 0)
|
||||||
|
title.Append(" (").Append(unreadCount).Append(')');
|
||||||
|
|
||||||
|
return title.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
||||||
|
|
||||||
|
|
||||||
public SubscriberViewModel(ILogger logger, ITabHostProvider tabHostProvider, ITabFactory tabFactory, IConnection? connection, ISubscriber subscriber, IExportImportFormatProvider exportImportFormatProvider)
|
public bool IsReplyTab { get; }
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global - used via BindingProxy
|
||||||
|
public Visibility StandardTabVisibility => !IsReplyTab ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
public Visibility ReplyTabVisibility => IsReplyTab ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
|
public SubscriberViewModel(ILogger logger, ITabFactory tabFactory, IConnection? connection, ISubscriber subscriber, IExportImportFormatProvider exportImportFormatProvider, bool isReplyTab)
|
||||||
{
|
{
|
||||||
|
IsReplyTab = isReplyTab;
|
||||||
|
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.tabHostProvider = tabHostProvider;
|
|
||||||
this.tabFactory = tabFactory;
|
this.tabFactory = tabFactory;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.subscriber = subscriber;
|
this.subscriber = subscriber;
|
||||||
@ -111,6 +137,15 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
subscriber.Start();
|
subscriber.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
newMessageTimer?.Dispose();
|
||||||
|
subscriber.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void ClearExecute()
|
private void ClearExecute()
|
||||||
{
|
{
|
||||||
Messages.Clear();
|
Messages.Clear();
|
||||||
@ -222,8 +257,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
if (connection == null)
|
if (connection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var publisherTab = tabFactory.CreatePublisherTab(connection, SelectedMessage);
|
tabFactory.CreatePublisherTab(connection, SelectedMessage);
|
||||||
tabHostProvider.Instance.AddTab(publisherTab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -320,7 +354,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
|
|
||||||
public class DesignTimeSubscriberViewModel : SubscriberViewModel
|
public class DesignTimeSubscriberViewModel : SubscriberViewModel
|
||||||
{
|
{
|
||||||
public DesignTimeSubscriberViewModel() : base(null!, null!, null!, null!, new DesignTimeSubscriber(), null!)
|
public DesignTimeSubscriberViewModel() : base(null!, null!, null!, new DesignTimeSubscriber(), null!, false)
|
||||||
{
|
{
|
||||||
for (var i = 1; i <= 5; i++)
|
for (var i = 1; i <= 5; i++)
|
||||||
(i > 2 ? UnreadMessages : Messages).Add(new ReceivedMessageInfo(
|
(i > 2 ? UnreadMessages : Messages).Add(new ReceivedMessageInfo(
|
||||||
@ -340,9 +374,9 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
|
|
||||||
private class DesignTimeSubscriber : ISubscriber
|
private class DesignTimeSubscriber : ISubscriber
|
||||||
{
|
{
|
||||||
public ValueTask DisposeAsync()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
return default;
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,5 +185,14 @@ namespace PettingZoo.UI.Tab.Subscriber {
|
|||||||
return ResourceManager.GetString("PropertyValue", resourceCulture);
|
return ResourceManager.GetString("PropertyValue", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Replies.
|
||||||
|
/// </summary>
|
||||||
|
public static string ReplyTabTitle {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ReplyTabTitle", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,4 +159,7 @@
|
|||||||
<data name="PropertyValue" xml:space="preserve">
|
<data name="PropertyValue" xml:space="preserve">
|
||||||
<value>Value</value>
|
<value>Value</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ReplyTabTitle" xml:space="preserve">
|
||||||
|
<value>Replies</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
@ -13,6 +14,7 @@ namespace PettingZoo.UI.Tab.Undocked
|
|||||||
private readonly ITabHostProvider tabHostProvider;
|
private readonly ITabHostProvider tabHostProvider;
|
||||||
private readonly ITab tab;
|
private readonly ITab tab;
|
||||||
private readonly DelegateCommand dockCommand;
|
private readonly DelegateCommand dockCommand;
|
||||||
|
private bool docked;
|
||||||
|
|
||||||
|
|
||||||
public string Title => tab.Title;
|
public string Title => tab.Title;
|
||||||
@ -43,13 +45,18 @@ namespace PettingZoo.UI.Tab.Undocked
|
|||||||
|
|
||||||
private void DockCommandExecute()
|
private void DockCommandExecute()
|
||||||
{
|
{
|
||||||
|
docked = true;
|
||||||
tabHostProvider.Instance.DockTab(tab);
|
tabHostProvider.Instance.DockTab(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void WindowClosed()
|
public void WindowClosed()
|
||||||
{
|
{
|
||||||
|
if (docked)
|
||||||
|
return;
|
||||||
|
|
||||||
tabHostProvider.Instance.UndockedTabClosed(tab);
|
tabHostProvider.Instance.UndockedTabClosed(tab);
|
||||||
|
(tab as IDisposable)?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System.Windows;
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Threading;
|
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Undocked
|
namespace PettingZoo.UI.Tab.Undocked
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ using System.Windows.Controls;
|
|||||||
|
|
||||||
namespace PettingZoo.UI.Tab
|
namespace PettingZoo.UI.Tab
|
||||||
{
|
{
|
||||||
public class ViewTab<TView, TViewModel> : ITab, ITabToolbarCommands, ITabActivate, ITabHostWindowNotify where TView : ContentControl where TViewModel : INotifyPropertyChanged
|
public class ViewTab<TView, TViewModel> : IDisposable, ITab, ITabToolbarCommands, ITabActivate, ITabHostWindowNotify where TView : ContentControl where TViewModel : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
public string Title => getTitle(viewModel);
|
public string Title => getTitle(viewModel);
|
||||||
public ContentControl Content { get; }
|
public ContentControl Content { get; }
|
||||||
@ -63,5 +63,12 @@ namespace PettingZoo.UI.Tab
|
|||||||
{
|
{
|
||||||
(viewModel as ITabHostWindowNotify)?.HostWindowChanged(hostWindow);
|
(viewModel as ITabHostWindowNotify)?.HostWindowChanged(hostWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
(viewModel as IDisposable)?.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
using PettingZoo.Core.Connection;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using PettingZoo.Core.Connection;
|
||||||
using PettingZoo.Core.ExportImport;
|
using PettingZoo.Core.ExportImport;
|
||||||
using PettingZoo.Core.Generator;
|
using PettingZoo.Core.Generator;
|
||||||
|
using PettingZoo.Core.Macros;
|
||||||
using PettingZoo.UI.Tab.Publisher;
|
using PettingZoo.UI.Tab.Publisher;
|
||||||
using PettingZoo.UI.Tab.Subscriber;
|
using PettingZoo.UI.Tab.Subscriber;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
@ -13,34 +16,119 @@ namespace PettingZoo.UI.Tab
|
|||||||
private readonly ITabHostProvider tabHostProvider;
|
private readonly ITabHostProvider tabHostProvider;
|
||||||
private readonly IExampleGenerator exampleGenerator;
|
private readonly IExampleGenerator exampleGenerator;
|
||||||
private readonly IExportImportFormatProvider exportImportFormatProvider;
|
private readonly IExportImportFormatProvider exportImportFormatProvider;
|
||||||
|
private readonly IPayloadMacroProcessor payloadMacroProcessor;
|
||||||
|
|
||||||
|
// Not the cleanest way, but this factory itself can't be singleton without (justifyable) upsetting SimpleInjector
|
||||||
|
private static ISubscriber? replySubscriber;
|
||||||
|
private static ITab? replySubscriberTab;
|
||||||
|
|
||||||
|
|
||||||
public ViewTabFactory(ILogger logger, ITabHostProvider tabHostProvider, IExampleGenerator exampleGenerator, IExportImportFormatProvider exportImportFormatProvider)
|
public ViewTabFactory(ILogger logger, ITabHostProvider tabHostProvider, IExampleGenerator exampleGenerator, IExportImportFormatProvider exportImportFormatProvider,
|
||||||
|
IPayloadMacroProcessor payloadMacroProcessor)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.tabHostProvider = tabHostProvider;
|
this.tabHostProvider = tabHostProvider;
|
||||||
this.exampleGenerator = exampleGenerator;
|
this.exampleGenerator = exampleGenerator;
|
||||||
this.exportImportFormatProvider = exportImportFormatProvider;
|
this.exportImportFormatProvider = exportImportFormatProvider;
|
||||||
|
this.payloadMacroProcessor = payloadMacroProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ITab CreateSubscriberTab(IConnection? connection, ISubscriber subscriber)
|
public void CreateSubscriberTab(IConnection? connection, ISubscriber subscriber)
|
||||||
{
|
{
|
||||||
var viewModel = new SubscriberViewModel(logger, tabHostProvider, this, connection, subscriber, exportImportFormatProvider);
|
InternalCreateSubscriberTab(connection, subscriber, false);
|
||||||
return new ViewTab<SubscriberView, SubscriberViewModel>(
|
|
||||||
new SubscriberView(viewModel),
|
|
||||||
viewModel,
|
|
||||||
vm => vm.Title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ITab CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
public string CreateReplySubscriberTab(IConnection connection)
|
||||||
{
|
{
|
||||||
var viewModel = new PublisherViewModel(tabHostProvider, this, connection, exampleGenerator, fromReceivedMessage);
|
if (replySubscriber?.QueueName != null && replySubscriberTab != null)
|
||||||
return new ViewTab<PublisherView, PublisherViewModel>(
|
{
|
||||||
|
tabHostProvider.Instance.ActivateTab(replySubscriberTab);
|
||||||
|
return replySubscriber.QueueName;
|
||||||
|
}
|
||||||
|
|
||||||
|
replySubscriber = new SubscriberDecorator(connection.Subscribe(), () =>
|
||||||
|
{
|
||||||
|
replySubscriber = null;
|
||||||
|
replySubscriberTab = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
replySubscriber.Start();
|
||||||
|
|
||||||
|
replySubscriberTab = InternalCreateSubscriberTab(connection, replySubscriber, true);
|
||||||
|
return replySubscriber.QueueName!;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||||
|
{
|
||||||
|
var viewModel = new PublisherViewModel(this, connection, exampleGenerator, payloadMacroProcessor, fromReceivedMessage);
|
||||||
|
var tab = new ViewTab<PublisherView, PublisherViewModel>(
|
||||||
new PublisherView(viewModel),
|
new PublisherView(viewModel),
|
||||||
viewModel,
|
viewModel,
|
||||||
vm => vm.Title);
|
vm => vm.Title);
|
||||||
|
|
||||||
|
tabHostProvider.Instance.AddTab(tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ITab InternalCreateSubscriberTab(IConnection? connection, ISubscriber subscriber, bool isReplyTab)
|
||||||
|
{
|
||||||
|
var viewModel = new SubscriberViewModel(logger, this, connection, subscriber, exportImportFormatProvider, isReplyTab);
|
||||||
|
var tab = new ViewTab<SubscriberView, SubscriberViewModel>(
|
||||||
|
new SubscriberView(viewModel),
|
||||||
|
viewModel,
|
||||||
|
vm => vm.Title);
|
||||||
|
|
||||||
|
tabHostProvider.Instance.AddTab(tab);
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private class SubscriberDecorator : ISubscriber
|
||||||
|
{
|
||||||
|
private readonly ISubscriber decoratedSubscriber;
|
||||||
|
private readonly Action onDispose;
|
||||||
|
|
||||||
|
|
||||||
|
public string? QueueName => decoratedSubscriber.QueueName;
|
||||||
|
public string? Exchange => decoratedSubscriber.Exchange;
|
||||||
|
public string? RoutingKey => decoratedSubscriber.RoutingKey;
|
||||||
|
|
||||||
|
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
||||||
|
|
||||||
|
|
||||||
|
public SubscriberDecorator(ISubscriber decoratedSubscriber, Action onDispose)
|
||||||
|
{
|
||||||
|
this.decoratedSubscriber = decoratedSubscriber;
|
||||||
|
this.onDispose = onDispose;
|
||||||
|
|
||||||
|
decoratedSubscriber.MessageReceived += (sender, args) =>
|
||||||
|
{
|
||||||
|
MessageReceived?.Invoke(sender, args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
decoratedSubscriber.Dispose();
|
||||||
|
onDispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<ReceivedMessageInfo> GetInitialMessages()
|
||||||
|
{
|
||||||
|
return decoratedSubscriber.GetInitialMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
decoratedSubscriber.Start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user