Implemented connection profiles
Added unread messages counter to deactivated subscriber tabs Added feature to reply to a new subscriber tab
This commit is contained in:
parent
4817b1806a
commit
2e6524f3b9
@ -8,6 +8,8 @@ namespace PettingZoo.Core.Connection
|
|||||||
event EventHandler<StatusChangedEventArgs> StatusChanged;
|
event EventHandler<StatusChangedEventArgs> StatusChanged;
|
||||||
|
|
||||||
ISubscriber Subscribe(string exchange, string routingKey);
|
ISubscriber Subscribe(string exchange, string routingKey);
|
||||||
|
ISubscriber Subscribe();
|
||||||
|
|
||||||
Task Publish(PublishMessageInfo messageInfo);
|
Task Publish(PublishMessageInfo messageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,9 @@ namespace PettingZoo.Core.Connection
|
|||||||
{
|
{
|
||||||
public interface ISubscriber : IAsyncDisposable
|
public interface ISubscriber : IAsyncDisposable
|
||||||
{
|
{
|
||||||
string Exchange {get; }
|
string? QueueName { get; }
|
||||||
string RoutingKey { get; }
|
string? Exchange {get; }
|
||||||
|
string? RoutingKey { get; }
|
||||||
|
|
||||||
event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
||||||
|
|
||||||
|
86
PettingZoo.Core/Settings/IConnectionSettingsRepository.cs
Normal file
86
PettingZoo.Core/Settings/IConnectionSettingsRepository.cs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PettingZoo.Core.Settings
|
||||||
|
{
|
||||||
|
public interface IConnectionSettingsRepository
|
||||||
|
{
|
||||||
|
Task<ConnectionSettings> GetLastUsed();
|
||||||
|
Task StoreLastUsed(ConnectionSettings connectionSettings);
|
||||||
|
|
||||||
|
Task<IEnumerable<StoredConnectionSettings>> GetStored();
|
||||||
|
Task<StoredConnectionSettings> Add(string displayName, ConnectionSettings connectionSettings);
|
||||||
|
Task<StoredConnectionSettings> Update(Guid id, string displayName, ConnectionSettings connectionSettings);
|
||||||
|
Task Delete(Guid id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class ConnectionSettings
|
||||||
|
{
|
||||||
|
public string Host { get; }
|
||||||
|
public string VirtualHost { get; }
|
||||||
|
public int Port { get; }
|
||||||
|
public string Username { get; }
|
||||||
|
public string? Password { get; }
|
||||||
|
|
||||||
|
public bool Subscribe { get; }
|
||||||
|
public string Exchange { get; }
|
||||||
|
public string RoutingKey { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly ConnectionSettings Default = new("localhost", "/", 5672, "guest", "guest", false, "", "#");
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectionSettings(string host, string virtualHost, int port, string username, string? password,
|
||||||
|
bool subscribe, string exchange, string routingKey)
|
||||||
|
{
|
||||||
|
Host = host;
|
||||||
|
VirtualHost = virtualHost;
|
||||||
|
Port = port;
|
||||||
|
Username = username;
|
||||||
|
Password = password;
|
||||||
|
|
||||||
|
Subscribe = subscribe;
|
||||||
|
Exchange = exchange;
|
||||||
|
RoutingKey = routingKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool SameParameters(ConnectionSettings value, bool comparePassword = true)
|
||||||
|
{
|
||||||
|
return Host == value.Host &&
|
||||||
|
VirtualHost == value.VirtualHost &&
|
||||||
|
Port == value.Port &&
|
||||||
|
Username == value.Username &&
|
||||||
|
(!comparePassword || Password == value.Password) &&
|
||||||
|
Subscribe == value.Subscribe &&
|
||||||
|
Exchange == value.Exchange &&
|
||||||
|
RoutingKey == value.RoutingKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class StoredConnectionSettings : ConnectionSettings
|
||||||
|
{
|
||||||
|
public Guid Id { get; }
|
||||||
|
public string DisplayName { get; }
|
||||||
|
|
||||||
|
public StoredConnectionSettings(Guid id, string displayName, string host, string virtualHost, int port, string username,
|
||||||
|
string? password, bool subscribe, string exchange, string routingKey)
|
||||||
|
: base(host, virtualHost, port, username, password, subscribe, exchange, routingKey)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
DisplayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public StoredConnectionSettings(Guid id, string displayName, ConnectionSettings connectionSettings)
|
||||||
|
: base(connectionSettings.Host, connectionSettings.VirtualHost, connectionSettings.Port, connectionSettings.Username, connectionSettings.Password,
|
||||||
|
connectionSettings.Subscribe, connectionSettings.Exchange, connectionSettings.RoutingKey)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
DisplayName = displayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -46,10 +46,24 @@ namespace PettingZoo.RabbitMQ
|
|||||||
connection = null;
|
connection = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ISubscriber Subscribe(string exchange, string routingKey)
|
public ISubscriber Subscribe(string exchange, string routingKey)
|
||||||
|
{
|
||||||
|
return CreateSubscriber(exchange, routingKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ISubscriber Subscribe()
|
||||||
|
{
|
||||||
|
return CreateSubscriber(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ISubscriber CreateSubscriber(string? exchange, string? routingKey)
|
||||||
{
|
{
|
||||||
lock (connectionLock)
|
lock (connectionLock)
|
||||||
{
|
{
|
||||||
|
@ -13,12 +13,13 @@ namespace PettingZoo.RabbitMQ
|
|||||||
private string? consumerTag;
|
private string? consumerTag;
|
||||||
private bool started;
|
private bool started;
|
||||||
|
|
||||||
public string Exchange { get; }
|
public string? QueueName { get; private set; }
|
||||||
public string RoutingKey { get; }
|
public string? Exchange { get; }
|
||||||
|
public string? RoutingKey { get; }
|
||||||
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
||||||
|
|
||||||
|
|
||||||
public RabbitMQClientSubscriber(IModel? model, string exchange, string routingKey)
|
public RabbitMQClientSubscriber(IModel? model, string? exchange, string? routingKey)
|
||||||
{
|
{
|
||||||
this.model = model;
|
this.model = model;
|
||||||
Exchange = exchange;
|
Exchange = exchange;
|
||||||
@ -28,6 +29,8 @@ namespace PettingZoo.RabbitMQ
|
|||||||
|
|
||||||
public ValueTask DisposeAsync()
|
public ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
if (model != null && consumerTag != null && model.IsOpen)
|
if (model != null && consumerTag != null && model.IsOpen)
|
||||||
model.BasicCancelNoWait(consumerTag);
|
model.BasicCancelNoWait(consumerTag);
|
||||||
|
|
||||||
@ -41,13 +44,14 @@ namespace PettingZoo.RabbitMQ
|
|||||||
if (model == null)
|
if (model == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var queueName = model.QueueDeclare().QueueName;
|
QueueName = model.QueueDeclare().QueueName;
|
||||||
model.QueueBind(queueName, Exchange, RoutingKey);
|
if (Exchange != null && RoutingKey != null)
|
||||||
|
model.QueueBind(QueueName, Exchange, RoutingKey);
|
||||||
|
|
||||||
var consumer = new EventingBasicConsumer(model);
|
var consumer = new EventingBasicConsumer(model);
|
||||||
consumer.Received += ClientReceived;
|
consumer.Received += ClientReceived;
|
||||||
|
|
||||||
consumerTag = model.BasicConsume(queueName, true, consumer);
|
consumerTag = model.BasicConsume(QueueName, true, consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
30
PettingZoo.Settings.LiteDB/BaseLiteDBRepository.cs
Normal file
30
PettingZoo.Settings.LiteDB/BaseLiteDBRepository.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using LiteDB;
|
||||||
|
using LiteDB.Async;
|
||||||
|
|
||||||
|
namespace PettingZoo.Settings.LiteDB
|
||||||
|
{
|
||||||
|
public class BaseLiteDBRepository
|
||||||
|
{
|
||||||
|
private readonly string databaseFilename;
|
||||||
|
|
||||||
|
|
||||||
|
public BaseLiteDBRepository(string databaseName)
|
||||||
|
{
|
||||||
|
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||||
|
if (appDataPath == null)
|
||||||
|
throw new IOException("Could not resolve application data path");
|
||||||
|
|
||||||
|
var databasePath = Path.Combine(appDataPath, @"PettingZoo");
|
||||||
|
if (!Directory.CreateDirectory(databasePath).Exists)
|
||||||
|
throw new IOException($"Failed to create directory: {databasePath}");
|
||||||
|
|
||||||
|
databaseFilename = Path.Combine(databasePath, $"{databaseName}.litedb");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected ILiteDatabaseAsync GetDatabase()
|
||||||
|
{
|
||||||
|
return new LiteDatabaseAsync(databaseFilename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
130
PettingZoo.Settings.LiteDB/LiteDBConnectionSettingsRepository.cs
Normal file
130
PettingZoo.Settings.LiteDB/LiteDBConnectionSettingsRepository.cs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
using PettingZoo.Core.Settings;
|
||||||
|
|
||||||
|
namespace PettingZoo.Settings.LiteDB
|
||||||
|
{
|
||||||
|
public class LiteDBConnectionSettingsRepository : BaseLiteDBRepository, IConnectionSettingsRepository
|
||||||
|
{
|
||||||
|
private static readonly Guid LastUsedId = new("1624147f-76b2-4b5e-8e6f-2ef1730a0a99");
|
||||||
|
|
||||||
|
private const string CollectionLastUsed = "lastUsed";
|
||||||
|
private const string CollectionStored = "stored";
|
||||||
|
|
||||||
|
|
||||||
|
public LiteDBConnectionSettingsRepository() : base(@"connectionSettings")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<ConnectionSettings> GetLastUsed()
|
||||||
|
{
|
||||||
|
using var database = GetDatabase();
|
||||||
|
var collection = database.GetCollection<ConnectionSettingsRecord>(CollectionLastUsed);
|
||||||
|
|
||||||
|
var lastUsed = await collection.FindOneAsync(r => true);
|
||||||
|
if (lastUsed == null)
|
||||||
|
return ConnectionSettings.Default;
|
||||||
|
|
||||||
|
return new ConnectionSettings(
|
||||||
|
lastUsed.Host,
|
||||||
|
lastUsed.VirtualHost,
|
||||||
|
lastUsed.Port,
|
||||||
|
lastUsed.Username,
|
||||||
|
lastUsed.Password,
|
||||||
|
lastUsed.Subscribe,
|
||||||
|
lastUsed.Exchange,
|
||||||
|
lastUsed.RoutingKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task StoreLastUsed(ConnectionSettings connectionSettings)
|
||||||
|
{
|
||||||
|
using var database = GetDatabase();
|
||||||
|
var collection = database.GetCollection<ConnectionSettingsRecord>(CollectionLastUsed);
|
||||||
|
|
||||||
|
await collection.UpsertAsync(ConnectionSettingsRecord.FromConnectionSettings(LastUsedId, connectionSettings, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<IEnumerable<StoredConnectionSettings>> GetStored()
|
||||||
|
{
|
||||||
|
using var database = GetDatabase();
|
||||||
|
var collection = database.GetCollection<ConnectionSettingsRecord>(CollectionStored);
|
||||||
|
|
||||||
|
return (await collection.FindAllAsync())
|
||||||
|
.Select(r => new StoredConnectionSettings(r.Id, r.DisplayName, r.Host, r.VirtualHost, r.Port, r.Username, r.Password, r.Subscribe, r.Exchange, r.RoutingKey))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<StoredConnectionSettings> Add(string displayName, ConnectionSettings connectionSettings)
|
||||||
|
{
|
||||||
|
using var database = GetDatabase();
|
||||||
|
var collection = database.GetCollection<ConnectionSettingsRecord>(CollectionStored);
|
||||||
|
|
||||||
|
var id = Guid.NewGuid();
|
||||||
|
await collection.InsertAsync(ConnectionSettingsRecord.FromConnectionSettings(id, connectionSettings, displayName));
|
||||||
|
|
||||||
|
return new StoredConnectionSettings(id, displayName, connectionSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<StoredConnectionSettings> Update(Guid id, string displayName, ConnectionSettings connectionSettings)
|
||||||
|
{
|
||||||
|
using var database = GetDatabase();
|
||||||
|
var collection = database.GetCollection<ConnectionSettingsRecord>(CollectionStored);
|
||||||
|
|
||||||
|
await collection.UpdateAsync(ConnectionSettingsRecord.FromConnectionSettings(id, connectionSettings, displayName));
|
||||||
|
return new StoredConnectionSettings(id, displayName, connectionSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task Delete(Guid id)
|
||||||
|
{
|
||||||
|
using var database = GetDatabase();
|
||||||
|
var collection = database.GetCollection<ConnectionSettingsRecord>(CollectionStored);
|
||||||
|
|
||||||
|
await collection.DeleteAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ReSharper disable MemberCanBePrivate.Local - for LiteDB
|
||||||
|
// ReSharper disable PropertyCanBeMadeInitOnly.Local
|
||||||
|
private class ConnectionSettingsRecord
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public string DisplayName { get; set; } = null!;
|
||||||
|
public string Host { get; set; } = null!;
|
||||||
|
public string VirtualHost { get; set; } = null!;
|
||||||
|
public int Port { get; set; }
|
||||||
|
public string Username { get; set; } = null!;
|
||||||
|
public string? Password { get; set; }
|
||||||
|
|
||||||
|
public bool Subscribe { get; set; }
|
||||||
|
public string Exchange { get; set; } = null!;
|
||||||
|
public string RoutingKey { get; set; } = null!;
|
||||||
|
|
||||||
|
|
||||||
|
public static ConnectionSettingsRecord FromConnectionSettings(Guid id, ConnectionSettings connectionSettings, string displayName)
|
||||||
|
{
|
||||||
|
return new ConnectionSettingsRecord
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
DisplayName = displayName,
|
||||||
|
|
||||||
|
Host = connectionSettings.Host,
|
||||||
|
VirtualHost = connectionSettings.VirtualHost,
|
||||||
|
Port = connectionSettings.Port,
|
||||||
|
Username = connectionSettings.Username,
|
||||||
|
Password = connectionSettings.Password,
|
||||||
|
|
||||||
|
Subscribe = connectionSettings.Subscribe,
|
||||||
|
Exchange = connectionSettings.Exchange,
|
||||||
|
RoutingKey = connectionSettings.RoutingKey
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ReSharper restore PropertyCanBeMadeInitOnly.Local
|
||||||
|
// ReSharper restore MemberCanBePrivate.Local
|
||||||
|
}
|
||||||
|
}
|
18
PettingZoo.Settings.LiteDB/PettingZoo.Settings.LiteDB.csproj
Normal file
18
PettingZoo.Settings.LiteDB/PettingZoo.Settings.LiteDB.csproj
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="LiteDB" Version="5.0.11" />
|
||||||
|
<PackageReference Include="LiteDB.Async" Version="0.0.11" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PettingZoo.Core\PettingZoo.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -14,7 +14,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PettingZoo.Core", "PettingZ
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PettingZoo.RabbitMQ", "PettingZoo.RabbitMQ\PettingZoo.RabbitMQ.csproj", "{220149F3-A8D6-44ED-B3B6-DFE506EB018A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PettingZoo.RabbitMQ", "PettingZoo.RabbitMQ\PettingZoo.RabbitMQ.csproj", "{220149F3-A8D6-44ED-B3B6-DFE506EB018A}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PettingZoo.Tapeti", "PettingZoo.Tapeti\PettingZoo.Tapeti.csproj", "{1763AB04-59D9-4663-B207-D6302FFAACD5}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PettingZoo.Tapeti", "PettingZoo.Tapeti\PettingZoo.Tapeti.csproj", "{1763AB04-59D9-4663-B207-D6302FFAACD5}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PettingZoo.Settings.LiteDB", "PettingZoo.Settings.LiteDB\PettingZoo.Settings.LiteDB.csproj", "{7157B09C-FDD9-4928-B14D-C25B784CA865}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -38,6 +40,10 @@ Global
|
|||||||
{1763AB04-59D9-4663-B207-D6302FFAACD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{1763AB04-59D9-4663-B207-D6302FFAACD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{1763AB04-59D9-4663-B207-D6302FFAACD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{1763AB04-59D9-4663-B207-D6302FFAACD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{1763AB04-59D9-4663-B207-D6302FFAACD5}.Release|Any CPU.Build.0 = Release|Any CPU
|
{1763AB04-59D9-4663-B207-D6302FFAACD5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7157B09C-FDD9-4928-B14D-C25B784CA865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7157B09C-FDD9-4928-B14D-C25B784CA865}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7157B09C-FDD9-4928-B14D-C25B784CA865}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7157B09C-FDD9-4928-B14D-C25B784CA865}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=PettingZoo_002EAnnotations/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=PettingZoo_002EAnnotations/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MQ/@EntryIndexedValue">MQ</s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MQ/@EntryIndexedValue">MQ</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WPF/@EntryIndexedValue">WPF</s:String></wpf:ResourceDictionary>
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WPF/@EntryIndexedValue">WPF</s:String></wpf:ResourceDictionary>
|
@ -39,9 +39,15 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\PettingZoo.Core\PettingZoo.Core.csproj" />
|
<ProjectReference Include="..\PettingZoo.Core\PettingZoo.Core.csproj" />
|
||||||
<ProjectReference Include="..\PettingZoo.RabbitMQ\PettingZoo.RabbitMQ.csproj" />
|
<ProjectReference Include="..\PettingZoo.RabbitMQ\PettingZoo.RabbitMQ.csproj" />
|
||||||
|
<ProjectReference Include="..\PettingZoo.Settings.LiteDB\PettingZoo.Settings.LiteDB.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Update="UI\Connection\ConnectionDisplayNameStrings.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>ConnectionDisplayNameStrings.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Update="UI\Connection\ConnectionWindowStrings.Designer.cs">
|
<Compile Update="UI\Connection\ConnectionWindowStrings.Designer.cs">
|
||||||
<DependentUpon>ConnectionWindowStrings.resx</DependentUpon>
|
<DependentUpon>ConnectionWindowStrings.resx</DependentUpon>
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
@ -88,6 +94,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="UI\Connection\ConnectionDisplayNameStrings.resx">
|
||||||
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>ConnectionDisplayNameStrings.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Update="UI\Connection\ConnectionWindowStrings.resx">
|
<EmbeddedResource Update="UI\Connection\ConnectionWindowStrings.resx">
|
||||||
<LastGenOutput>ConnectionWindowStrings.Designer.cs</LastGenOutput>
|
<LastGenOutput>ConnectionWindowStrings.Designer.cs</LastGenOutput>
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Markup;
|
using System.Windows.Markup;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
|
using PettingZoo.Core.Settings;
|
||||||
using PettingZoo.RabbitMQ;
|
using PettingZoo.RabbitMQ;
|
||||||
using PettingZoo.Settings;
|
using PettingZoo.Settings.LiteDB;
|
||||||
using PettingZoo.UI.Connection;
|
using PettingZoo.UI.Connection;
|
||||||
using PettingZoo.UI.Main;
|
using PettingZoo.UI.Main;
|
||||||
using PettingZoo.UI.Subscribe;
|
using PettingZoo.UI.Subscribe;
|
||||||
using PettingZoo.UI.Tab;
|
|
||||||
using SimpleInjector;
|
using SimpleInjector;
|
||||||
|
|
||||||
namespace PettingZoo
|
namespace PettingZoo
|
||||||
@ -37,11 +34,10 @@ namespace PettingZoo
|
|||||||
// See comments in RunApplication
|
// See comments in RunApplication
|
||||||
container.Options.EnableAutoVerification = false;
|
container.Options.EnableAutoVerification = false;
|
||||||
|
|
||||||
container.RegisterSingleton(() => new UserSettings(new AppDataSettingsSerializer("Settings.json")));
|
|
||||||
|
|
||||||
container.Register<IConnectionFactory, RabbitMQClientConnectionFactory>();
|
container.Register<IConnectionFactory, RabbitMQClientConnectionFactory>();
|
||||||
container.Register<IConnectionDialog, WindowConnectionDialog>();
|
container.Register<IConnectionDialog, WindowConnectionDialog>();
|
||||||
container.Register<ISubscribeDialog, WindowSubscribeDialog>();
|
container.Register<ISubscribeDialog, WindowSubscribeDialog>();
|
||||||
|
container.Register<IConnectionSettingsRepository, LiteDBConnectionSettingsRepository>();
|
||||||
|
|
||||||
container.Register<MainWindow>();
|
container.Register<MainWindow>();
|
||||||
|
|
||||||
@ -72,50 +68,9 @@ namespace PettingZoo
|
|||||||
var mainWindow = container.GetInstance<MainWindow>();
|
var mainWindow = container.GetInstance<MainWindow>();
|
||||||
_ = app.Run(mainWindow);
|
_ = app.Run(mainWindow);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// TODO Log the exception and exit
|
MessageBox.Show($"Fatal exception: {e.Message}", @"PettingZoo", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private class AppDataSettingsSerializer : IUserSettingsSerializer
|
|
||||||
{
|
|
||||||
private readonly string path;
|
|
||||||
private readonly string fullPath;
|
|
||||||
|
|
||||||
|
|
||||||
public AppDataSettingsSerializer(string filename)
|
|
||||||
{
|
|
||||||
var companyName = GetProductInfo<AssemblyCompanyAttribute>().Company;
|
|
||||||
var productName = GetProductInfo<AssemblyProductAttribute>().Product;
|
|
||||||
|
|
||||||
path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
|
||||||
companyName, productName);
|
|
||||||
fullPath = Path.Combine(path, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Read(UserSettings settings)
|
|
||||||
{
|
|
||||||
if (File.Exists(fullPath))
|
|
||||||
JsonConvert.PopulateObject(File.ReadAllText(fullPath), settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Write(UserSettings settings)
|
|
||||||
{
|
|
||||||
_ = Directory.CreateDirectory(path);
|
|
||||||
File.WriteAllText(fullPath, JsonConvert.SerializeObject(settings, Formatting.Indented));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private T GetProductInfo<T>()
|
|
||||||
{
|
|
||||||
var attributes = GetType().Assembly.GetCustomAttributes(typeof(T), true);
|
|
||||||
return attributes.Length == 0
|
|
||||||
? throw new Exception("Missing product information in assembly")
|
|
||||||
: (T) attributes[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
namespace PettingZoo.Settings
|
|
||||||
{
|
|
||||||
public interface IUserSettingsSerializer
|
|
||||||
{
|
|
||||||
void Read(UserSettings settings);
|
|
||||||
void Write(UserSettings settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class ConnectionWindowSettings
|
|
||||||
{
|
|
||||||
public string LastHost { get; set; }
|
|
||||||
public string LastVirtualHost { get; set; }
|
|
||||||
public int LastPort { get; set; }
|
|
||||||
public string LastUsername { get; set; }
|
|
||||||
public string LastPassword { get; set; }
|
|
||||||
|
|
||||||
//public bool LastSubscribe { get; set; }
|
|
||||||
public string LastExchange { get; set; }
|
|
||||||
public string LastRoutingKey { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public ConnectionWindowSettings()
|
|
||||||
{
|
|
||||||
LastHost = "localhost";
|
|
||||||
LastPort = 5672;
|
|
||||||
LastVirtualHost = "/";
|
|
||||||
LastUsername = "guest";
|
|
||||||
LastPassword = "guest";
|
|
||||||
|
|
||||||
LastExchange = "";
|
|
||||||
LastRoutingKey = "#";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class UserSettings
|
|
||||||
{
|
|
||||||
public ConnectionWindowSettings ConnectionWindow { get; }
|
|
||||||
|
|
||||||
|
|
||||||
private readonly IUserSettingsSerializer serializer;
|
|
||||||
|
|
||||||
|
|
||||||
public UserSettings(IUserSettingsSerializer serializer)
|
|
||||||
{
|
|
||||||
ConnectionWindow = new ConnectionWindowSettings();
|
|
||||||
|
|
||||||
this.serializer = serializer;
|
|
||||||
serializer.Read(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Save()
|
|
||||||
{
|
|
||||||
serializer.Write(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -34,6 +34,10 @@
|
|||||||
<Setter Property="Margin" Value="8,0,0,0" />
|
<Setter Property="Margin" Value="8,0,0,0" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Key="FooterButtonLeft" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
|
||||||
|
<Setter Property="Margin" Value="0,0,8,0" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
<Style x:Key="Form" TargetType="{x:Type ui:GridLayout}">
|
<Style x:Key="Form" TargetType="{x:Type ui:GridLayout}">
|
||||||
<Setter Property="ChildMargin" Value="4"/>
|
<Setter Property="ChildMargin" Value="4"/>
|
||||||
@ -78,4 +82,11 @@
|
|||||||
<Setter Property="FontWeight" Value="Bold"/>
|
<Setter Property="FontWeight" Value="Bold"/>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
|
<Style x:Key="Payload" TargetType="{x:Type TextBox}">
|
||||||
|
<Setter Property="AcceptsReturn" Value="True" />
|
||||||
|
<Setter Property="AcceptsTab" Value="True" />
|
||||||
|
<Setter Property="VerticalScrollBarVisibility" Value="Visible" />
|
||||||
|
<Setter Property="FontFamily" Value="Consolas,Courier New" />
|
||||||
|
</Style>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
16
PettingZoo/TODO.md
Normal file
16
PettingZoo/TODO.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Must-have
|
||||||
|
---------
|
||||||
|
|
||||||
|
|
||||||
|
Should-have
|
||||||
|
-----------
|
||||||
|
- Support undocking tabs (and redocking afterwards)
|
||||||
|
- Allow tab reordering
|
||||||
|
- Save / load publisher messages (either as templates or to disk)
|
||||||
|
- Export received messages to Tapeti JSON file / Tapeti.Cmd command-line
|
||||||
|
|
||||||
|
|
||||||
|
Nice-to-have
|
||||||
|
------------
|
||||||
|
- JSON validation
|
||||||
|
- JSON syntax highlighting
|
@ -14,14 +14,9 @@ namespace PettingZoo.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected virtual void RaiseOtherPropertyChanged(string propertyName)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected bool SetField<T>(ref T field, T value, IEqualityComparer<T>? comparer = null, [CallerMemberName] string? propertyName = null,
|
protected bool SetField<T>(ref T field, T value, IEqualityComparer<T>? comparer = null, [CallerMemberName] string? propertyName = null,
|
||||||
params string[]? otherPropertiesChanged)
|
DelegateCommand[]? delegateCommandsChanged = null,
|
||||||
|
string[]? otherPropertiesChanged = null)
|
||||||
{
|
{
|
||||||
if ((comparer ?? EqualityComparer<T>.Default).Equals(field, value))
|
if ((comparer ?? EqualityComparer<T>.Default).Equals(field, value))
|
||||||
return false;
|
return false;
|
||||||
@ -29,11 +24,17 @@ namespace PettingZoo.UI
|
|||||||
field = value;
|
field = value;
|
||||||
RaisePropertyChanged(propertyName);
|
RaisePropertyChanged(propertyName);
|
||||||
|
|
||||||
if (otherPropertiesChanged == null)
|
if (otherPropertiesChanged != null)
|
||||||
return true;
|
{
|
||||||
|
foreach (var otherProperty in otherPropertiesChanged)
|
||||||
|
RaisePropertyChanged(otherProperty);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var otherProperty in otherPropertiesChanged)
|
if (delegateCommandsChanged != null)
|
||||||
RaisePropertyChanged(otherProperty);
|
{
|
||||||
|
foreach (var delegateCommand in delegateCommandsChanged)
|
||||||
|
delegateCommand.RaiseCanExecuteChanged();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
25
PettingZoo/UI/Connection/ConnectionDisplayNameDialog.xaml
Normal file
25
PettingZoo/UI/Connection/ConnectionDisplayNameDialog.xaml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<Window x:Class="PettingZoo.UI.Connection.ConnectionDisplayNameDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:PettingZoo.UI.Connection"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Width="400"
|
||||||
|
SizeToContent="Height"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
WindowStyle="ToolWindow"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
Style="{StaticResource WindowStyle}"
|
||||||
|
Title="{x:Static local:ConnectionDisplayNameStrings.WindowTitle}"
|
||||||
|
FocusManager.FocusedElement="{Binding ElementName=DisplayNameTextBox}"
|
||||||
|
d:DataContext="{d:DesignInstance local:ConnectionDisplayNameViewModel}">
|
||||||
|
<StackPanel Margin="8">
|
||||||
|
<TextBox Name="DisplayNameTextBox" Text="{Binding DisplayName, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
|
<UniformGrid HorizontalAlignment="Right" Rows="1" Columns="2" Style="{StaticResource FooterPanel}">
|
||||||
|
<Button IsDefault="True" Content="{x:Static local:ConnectionDisplayNameStrings.ButtonOK}" Style="{StaticResource FooterButton}" Command="{Binding OkCommand}"/>
|
||||||
|
<Button IsCancel="True" Content="{x:Static local:ConnectionDisplayNameStrings.ButtonCancel}" Style="{StaticResource FooterButton}"/>
|
||||||
|
</UniformGrid>
|
||||||
|
</StackPanel>
|
||||||
|
</Window>
|
49
PettingZoo/UI/Connection/ConnectionDisplayNameDialog.xaml.cs
Normal file
49
PettingZoo/UI/Connection/ConnectionDisplayNameDialog.xaml.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Connection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for ConnectionDisplayNameDialog.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class ConnectionDisplayNameDialog
|
||||||
|
{
|
||||||
|
public static bool Execute(ref string displayName)
|
||||||
|
{
|
||||||
|
var viewModel = new ConnectionDisplayNameViewModel
|
||||||
|
{
|
||||||
|
DisplayName = displayName
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var activeWindow = Application.Current.Windows
|
||||||
|
.Cast<Window>()
|
||||||
|
.FirstOrDefault(applicationWindow => applicationWindow.IsActive);
|
||||||
|
|
||||||
|
var window = new ConnectionDisplayNameDialog(viewModel)
|
||||||
|
{
|
||||||
|
Owner = activeWindow ?? Application.Current.MainWindow
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.ShowDialog().GetValueOrDefault())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
displayName = viewModel.DisplayName;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectionDisplayNameDialog(ConnectionDisplayNameViewModel viewModel)
|
||||||
|
{
|
||||||
|
viewModel.OkClick += (_, _) =>
|
||||||
|
{
|
||||||
|
DialogResult = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
DisplayNameTextBox.CaretIndex = DisplayNameTextBox.Text.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
90
PettingZoo/UI/Connection/ConnectionDisplayNameStrings.Designer.cs
generated
Normal file
90
PettingZoo/UI/Connection/ConnectionDisplayNameStrings.Designer.cs
generated
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Connection {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
public class ConnectionDisplayNameStrings {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal ConnectionDisplayNameStrings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
public static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.UI.Connection.ConnectionDisplayNameStrings", typeof(ConnectionDisplayNameStrings).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
public static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Cancel.
|
||||||
|
/// </summary>
|
||||||
|
public static string ButtonCancel {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ButtonCancel", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to OK.
|
||||||
|
/// </summary>
|
||||||
|
public static string ButtonOK {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ButtonOK", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Profile name.
|
||||||
|
/// </summary>
|
||||||
|
public static string WindowTitle {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("WindowTitle", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
129
PettingZoo/UI/Connection/ConnectionDisplayNameStrings.resx
Normal file
129
PettingZoo/UI/Connection/ConnectionDisplayNameStrings.resx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="ButtonCancel" xml:space="preserve">
|
||||||
|
<value>Cancel</value>
|
||||||
|
</data>
|
||||||
|
<data name="ButtonOK" xml:space="preserve">
|
||||||
|
<value>OK</value>
|
||||||
|
</data>
|
||||||
|
<data name="WindowTitle" xml:space="preserve">
|
||||||
|
<value>Profile name</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
41
PettingZoo/UI/Connection/ConnectionDisplayNameViewModel.cs
Normal file
41
PettingZoo/UI/Connection/ConnectionDisplayNameViewModel.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Connection
|
||||||
|
{
|
||||||
|
public class ConnectionDisplayNameViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private string displayName = "";
|
||||||
|
|
||||||
|
private readonly DelegateCommand okCommand;
|
||||||
|
|
||||||
|
|
||||||
|
public string DisplayName
|
||||||
|
{
|
||||||
|
get => displayName;
|
||||||
|
set => SetField(ref displayName, value, delegateCommandsChanged: new [] { okCommand });
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommand OkCommand => okCommand;
|
||||||
|
|
||||||
|
public event EventHandler? OkClick;
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectionDisplayNameViewModel()
|
||||||
|
{
|
||||||
|
okCommand = new DelegateCommand(OkExecute, OkCanExecute);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OkExecute()
|
||||||
|
{
|
||||||
|
OkClick?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool OkCanExecute()
|
||||||
|
{
|
||||||
|
return !string.IsNullOrWhiteSpace(DisplayName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,46 +1,60 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using PettingZoo.Core.Settings;
|
||||||
|
|
||||||
// TODO validate input
|
// TODO "save password" checkbox
|
||||||
// TODO profiles
|
|
||||||
|
|
||||||
namespace PettingZoo.UI.Connection
|
namespace PettingZoo.UI.Connection
|
||||||
{
|
{
|
||||||
public class ConnectionViewModel : BaseViewModel
|
public class ConnectionViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
private string host;
|
private readonly IConnectionSettingsRepository connectionSettingsRepository;
|
||||||
private string virtualHost;
|
private readonly ConnectionSettings defaultSettings;
|
||||||
|
private string host = null!;
|
||||||
|
private string virtualHost = null!;
|
||||||
private int port;
|
private int port;
|
||||||
private string username;
|
private string username = null!;
|
||||||
private string password;
|
private string password = null!;
|
||||||
|
|
||||||
private bool subscribe;
|
private bool subscribe;
|
||||||
private string exchange;
|
private string exchange = null!;
|
||||||
private string routingKey;
|
private string routingKey = null!;
|
||||||
|
|
||||||
|
private StoredConnectionSettings? selectedStoredConnection;
|
||||||
|
|
||||||
|
private readonly DelegateCommand okCommand;
|
||||||
|
private readonly DelegateCommand saveCommand;
|
||||||
|
private readonly DelegateCommand saveAsCommand;
|
||||||
|
private readonly DelegateCommand deleteCommand;
|
||||||
|
|
||||||
|
private readonly DelegateCommand[] connectionChangedCommands;
|
||||||
|
|
||||||
|
|
||||||
public string Host
|
public string Host
|
||||||
{
|
{
|
||||||
get => host;
|
get => host;
|
||||||
set => SetField(ref host, value);
|
set => SetField(ref host, value, delegateCommandsChanged: connectionChangedCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string VirtualHost
|
public string VirtualHost
|
||||||
{
|
{
|
||||||
get => virtualHost;
|
get => virtualHost;
|
||||||
set => SetField(ref virtualHost, value);
|
set => SetField(ref virtualHost, value, delegateCommandsChanged: connectionChangedCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Port
|
public int Port
|
||||||
{
|
{
|
||||||
get => port;
|
get => port;
|
||||||
set => SetField(ref port, value);
|
set => SetField(ref port, value, delegateCommandsChanged: connectionChangedCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Username
|
public string Username
|
||||||
{
|
{
|
||||||
get => username;
|
get => username;
|
||||||
set => SetField(ref username, value);
|
set => SetField(ref username, value, delegateCommandsChanged: connectionChangedCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Password
|
public string Password
|
||||||
@ -53,46 +67,142 @@ namespace PettingZoo.UI.Connection
|
|||||||
public bool Subscribe
|
public bool Subscribe
|
||||||
{
|
{
|
||||||
get => subscribe;
|
get => subscribe;
|
||||||
set => SetField(ref subscribe, value);
|
set => SetField(ref subscribe, value, delegateCommandsChanged: connectionChangedCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Exchange
|
public string Exchange
|
||||||
{
|
{
|
||||||
get => exchange;
|
get => exchange;
|
||||||
set => SetField(ref exchange, value);
|
set
|
||||||
|
{
|
||||||
|
if (SetField(ref exchange, value, delegateCommandsChanged: connectionChangedCommands))
|
||||||
|
AutoToggleSubscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string RoutingKey
|
public string RoutingKey
|
||||||
{
|
{
|
||||||
get => routingKey;
|
get => routingKey;
|
||||||
set => SetField(ref routingKey, value);
|
set
|
||||||
|
{
|
||||||
|
if (SetField(ref routingKey, value, delegateCommandsChanged: connectionChangedCommands))
|
||||||
|
AutoToggleSubscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ICommand OkCommand { get; }
|
public ObservableCollection<StoredConnectionSettings> StoredConnections { get; } = new();
|
||||||
|
|
||||||
|
public StoredConnectionSettings? SelectedStoredConnection
|
||||||
|
{
|
||||||
|
get => selectedStoredConnection;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!SetField(ref selectedStoredConnection, value, delegateCommandsChanged: new [] { deleteCommand }))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Host = value.Host;
|
||||||
|
VirtualHost = value.VirtualHost;
|
||||||
|
Port = value.Port;
|
||||||
|
Username = value.Username;
|
||||||
|
Password = value.Password ?? "";
|
||||||
|
|
||||||
|
Exchange = value.Exchange;
|
||||||
|
RoutingKey = value.RoutingKey;
|
||||||
|
Subscribe = value.Subscribe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ICommand OkCommand => okCommand;
|
||||||
|
public ICommand SaveCommand => saveCommand;
|
||||||
|
public ICommand SaveAsCommand => saveAsCommand;
|
||||||
|
public ICommand DeleteCommand => deleteCommand;
|
||||||
|
|
||||||
public event EventHandler? OkClick;
|
public event EventHandler? OkClick;
|
||||||
|
|
||||||
|
|
||||||
public ConnectionViewModel(ConnectionDialogParams model)
|
public ConnectionViewModel(IConnectionSettingsRepository connectionSettingsRepository, ConnectionSettings defaultSettings)
|
||||||
{
|
{
|
||||||
OkCommand = new DelegateCommand(OkExecute, OkCanExecute);
|
this.connectionSettingsRepository = connectionSettingsRepository;
|
||||||
|
this.defaultSettings = defaultSettings;
|
||||||
|
|
||||||
host = model.Host;
|
okCommand = new DelegateCommand(OkExecute, OkCanExecute);
|
||||||
virtualHost = model.VirtualHost;
|
saveCommand = new DelegateCommand(SaveExecute, SaveCanExecute);
|
||||||
port = model.Port;
|
saveAsCommand = new DelegateCommand(SaveAsExecute, SaveAsCanExecute);
|
||||||
username = model.Username;
|
deleteCommand = new DelegateCommand(DeleteExecute, DeleteCanExecute);
|
||||||
password = model.Password;
|
|
||||||
|
|
||||||
subscribe = model.Subscribe;
|
connectionChangedCommands = new[] { saveCommand, saveAsCommand, okCommand };
|
||||||
exchange = model.Exchange;
|
|
||||||
routingKey = model.RoutingKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ConnectionDialogParams ToModel()
|
public async Task Initialize()
|
||||||
{
|
{
|
||||||
return new(Host, VirtualHost, Port, Username, Password, Subscribe, Exchange, RoutingKey);
|
var defaultConnection = new StoredConnectionSettings(
|
||||||
|
Guid.Empty,
|
||||||
|
ConnectionWindowStrings.LastUsedDisplayName,
|
||||||
|
defaultSettings.Host,
|
||||||
|
defaultSettings.VirtualHost,
|
||||||
|
defaultSettings.Port,
|
||||||
|
defaultSettings.Username,
|
||||||
|
defaultSettings.Password,
|
||||||
|
defaultSettings.Subscribe,
|
||||||
|
defaultSettings.Exchange,
|
||||||
|
defaultSettings.RoutingKey);
|
||||||
|
|
||||||
|
var isStored = false;
|
||||||
|
|
||||||
|
foreach (var storedConnectionSettings in await connectionSettingsRepository.GetStored())
|
||||||
|
{
|
||||||
|
if (!isStored && storedConnectionSettings.SameParameters(defaultConnection))
|
||||||
|
{
|
||||||
|
SelectedStoredConnection = storedConnectionSettings;
|
||||||
|
isStored = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
StoredConnections.Add(storedConnectionSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStored)
|
||||||
|
{
|
||||||
|
// The last used parameters match a stored connection, insert the "New connection" item with default parameters
|
||||||
|
StoredConnections.Insert(0, new StoredConnectionSettings(Guid.Empty, ConnectionWindowStrings.LastUsedDisplayName, ConnectionSettings.Default));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No match, use the passed parameters
|
||||||
|
StoredConnections.Insert(0, defaultConnection);
|
||||||
|
SelectedStoredConnection = defaultConnection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectionSettings ToModel()
|
||||||
|
{
|
||||||
|
return new ConnectionSettings(Host, VirtualHost, Port, Username, Password, Subscribe, Exchange, RoutingKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool ValidConnection(bool requirePassword)
|
||||||
|
{
|
||||||
|
return !string.IsNullOrWhiteSpace(Host) &&
|
||||||
|
!string.IsNullOrWhiteSpace(VirtualHost) &&
|
||||||
|
Port > 0 &&
|
||||||
|
!string.IsNullOrWhiteSpace(Username) &&
|
||||||
|
(!requirePassword || !string.IsNullOrWhiteSpace(Password)) &&
|
||||||
|
(!Subscribe || (
|
||||||
|
!string.IsNullOrWhiteSpace(Exchange) &&
|
||||||
|
!string.IsNullOrWhiteSpace(RoutingKey)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void AutoToggleSubscribe()
|
||||||
|
{
|
||||||
|
Subscribe = !string.IsNullOrWhiteSpace(Exchange) && !string.IsNullOrWhiteSpace(RoutingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -102,17 +212,94 @@ namespace PettingZoo.UI.Connection
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static bool OkCanExecute()
|
private bool OkCanExecute()
|
||||||
{
|
{
|
||||||
return true;
|
return ValidConnection(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async void SaveExecute()
|
||||||
|
{
|
||||||
|
if (SelectedStoredConnection == null || SelectedStoredConnection.Id == Guid.Empty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var selectedIndex = StoredConnections.IndexOf(SelectedStoredConnection);
|
||||||
|
|
||||||
|
var updatedStoredConnection = await connectionSettingsRepository.Update(SelectedStoredConnection.Id, SelectedStoredConnection.DisplayName, ToModel());
|
||||||
|
|
||||||
|
|
||||||
|
StoredConnections[selectedIndex] = updatedStoredConnection;
|
||||||
|
SelectedStoredConnection = updatedStoredConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool SaveCanExecute()
|
||||||
|
{
|
||||||
|
// TODO check changes in parameters (excluding password)
|
||||||
|
return SelectedStoredConnection != null &&
|
||||||
|
SelectedStoredConnection.Id != Guid.Empty &&
|
||||||
|
ValidConnection(false) &&
|
||||||
|
!ToModel().SameParameters(SelectedStoredConnection, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async void SaveAsExecute()
|
||||||
|
{
|
||||||
|
// TODO create and enforce unique name?
|
||||||
|
var displayName = SelectedStoredConnection != null && SelectedStoredConnection.Id != Guid.Empty ? SelectedStoredConnection.DisplayName : "";
|
||||||
|
|
||||||
|
if (!ConnectionDisplayNameDialog.Execute(ref displayName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var storedConnectionSettings = await connectionSettingsRepository.Add(displayName, ToModel());
|
||||||
|
|
||||||
|
StoredConnections.Add(storedConnectionSettings);
|
||||||
|
SelectedStoredConnection = storedConnectionSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool SaveAsCanExecute()
|
||||||
|
{
|
||||||
|
return ValidConnection(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async void DeleteExecute()
|
||||||
|
{
|
||||||
|
if (SelectedStoredConnection == null || SelectedStoredConnection.Id == Guid.Empty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var selectedIndex = StoredConnections.IndexOf(SelectedStoredConnection);
|
||||||
|
|
||||||
|
if (MessageBox.Show(
|
||||||
|
string.Format(ConnectionWindowStrings.DeleteConfirm, SelectedStoredConnection.DisplayName),
|
||||||
|
ConnectionWindowStrings.DeleteConfirmTitle,
|
||||||
|
MessageBoxButton.YesNo,
|
||||||
|
MessageBoxImage.Question) != MessageBoxResult.Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await connectionSettingsRepository.Delete(SelectedStoredConnection.Id);
|
||||||
|
|
||||||
|
StoredConnections.Remove(SelectedStoredConnection);
|
||||||
|
if (selectedIndex >= StoredConnections.Count)
|
||||||
|
selectedIndex--;
|
||||||
|
|
||||||
|
SelectedStoredConnection = StoredConnections[selectedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool DeleteCanExecute()
|
||||||
|
{
|
||||||
|
return SelectedStoredConnection != null && SelectedStoredConnection.Id != Guid.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class DesignTimeConnectionViewModel : ConnectionViewModel
|
public class DesignTimeConnectionViewModel : ConnectionViewModel
|
||||||
{
|
{
|
||||||
public DesignTimeConnectionViewModel() : base(ConnectionDialogParams.Default)
|
public DesignTimeConnectionViewModel() : base(null!, null!)
|
||||||
{
|
{
|
||||||
|
StoredConnections.Add(new StoredConnectionSettings(Guid.Empty, "Dummy", ConnectionSettings.Default));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,20 +7,49 @@
|
|||||||
xmlns:connection="clr-namespace:PettingZoo.UI.Connection"
|
xmlns:connection="clr-namespace:PettingZoo.UI.Connection"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DataContext="{d:DesignInstance connection:DesignTimeConnectionViewModel, IsDesignTimeCreatable = True}"
|
d:DataContext="{d:DesignInstance connection:DesignTimeConnectionViewModel, IsDesignTimeCreatable = True}"
|
||||||
Width="500"
|
Width="700"
|
||||||
SizeToContent="Height"
|
SizeToContent="Height"
|
||||||
ResizeMode="NoResize"
|
ResizeMode="NoResize"
|
||||||
WindowStyle="ToolWindow"
|
WindowStyle="ToolWindow"
|
||||||
Style="{StaticResource WindowStyle}"
|
Style="{StaticResource WindowStyle}"
|
||||||
Title="{x:Static connection:ConnectionWindowStrings.WindowTitle}"
|
Title="{x:Static connection:ConnectionWindowStrings.WindowTitle}"
|
||||||
FocusManager.FocusedElement="{Binding ElementName=HostTextBox}">
|
FocusManager.FocusedElement="{Binding ElementName=HostTextBox}"
|
||||||
<DockPanel Margin="8">
|
WindowStartupLocation="CenterOwner">
|
||||||
<UniformGrid DockPanel.Dock="Bottom" HorizontalAlignment="Right" Rows="1" Columns="2" Style="{StaticResource FooterPanel}">
|
<Grid Margin="8">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<UniformGrid Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" Rows="1" Columns="1" Style="{StaticResource FooterPanel}">
|
||||||
|
<Button Content="{x:Static connection:ConnectionWindowStrings.ButtonDelete}" Style="{StaticResource FooterButtonLeft}" Command="{Binding DeleteCommand}"/>
|
||||||
|
</UniformGrid>
|
||||||
|
|
||||||
|
<UniformGrid Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Rows="1" Columns="3" Style="{StaticResource FooterPanel}">
|
||||||
|
<Button Content="{x:Static connection:ConnectionWindowStrings.ButtonSave}" Style="{StaticResource FooterButtonLeft}" Command="{Binding SaveCommand}"/>
|
||||||
|
<Button Content="{x:Static connection:ConnectionWindowStrings.ButtonSaveAs}" Style="{StaticResource FooterButtonLeft}" Command="{Binding SaveAsCommand}"/>
|
||||||
|
</UniformGrid>
|
||||||
|
|
||||||
|
<UniformGrid Grid.Row="1" Grid.Column="2" HorizontalAlignment="Right" Rows="1" Columns="2" Style="{StaticResource FooterPanel}">
|
||||||
<Button IsDefault="True" Content="{x:Static connection:ConnectionWindowStrings.ButtonOK}" Style="{StaticResource FooterButton}" Command="{Binding OkCommand}"/>
|
<Button IsDefault="True" Content="{x:Static connection:ConnectionWindowStrings.ButtonOK}" Style="{StaticResource FooterButton}" Command="{Binding OkCommand}"/>
|
||||||
<Button IsCancel="True" Content="{x:Static connection:ConnectionWindowStrings.ButtonCancel}" Style="{StaticResource FooterButton}"/>
|
<Button IsCancel="True" Content="{x:Static connection:ConnectionWindowStrings.ButtonCancel}" Style="{StaticResource FooterButton}"/>
|
||||||
</UniformGrid>
|
</UniformGrid>
|
||||||
|
|
||||||
<ui:GridLayout Style="{StaticResource Form}">
|
<ListBox Grid.Row="0" Grid.Column="0" Margin="0 0 8 0" Width="250" ItemsSource="{Binding StoredConnections}" SelectedValue="{Binding SelectedStoredConnection}">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding DisplayName}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
|
||||||
|
<ui:GridLayout Style="{StaticResource Form}" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
@ -37,28 +66,28 @@
|
|||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static connection:ConnectionWindowStrings.LabelHost}"/>
|
<Label Grid.Column="0" Grid.Row="0" Content="{x:Static connection:ConnectionWindowStrings.LabelHost}"/>
|
||||||
<TextBox Grid.Column="1" Grid.Row="0" Text="{Binding Host}" Name="HostTextBox" />
|
<TextBox Grid.Column="1" Grid.Row="0" Text="{Binding Host, UpdateSourceTrigger=PropertyChanged}" Name="HostTextBox" GotFocus="CaretToEnd" />
|
||||||
|
|
||||||
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static connection:ConnectionWindowStrings.LabelPort}"/>
|
<Label Grid.Column="0" Grid.Row="1" Content="{x:Static connection:ConnectionWindowStrings.LabelPort}"/>
|
||||||
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Port}" Width="100" HorizontalAlignment="Left" PreviewTextInput="NumericPreviewTextInput" />
|
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Port, UpdateSourceTrigger=PropertyChanged}" Width="100" HorizontalAlignment="Left" PreviewTextInput="NumericPreviewTextInput" GotFocus="CaretToEnd" />
|
||||||
|
|
||||||
<Label Grid.Column="0" Grid.Row="2" Content="{x:Static connection:ConnectionWindowStrings.LabelVirtualHost}"/>
|
<Label Grid.Column="0" Grid.Row="2" Content="{x:Static connection:ConnectionWindowStrings.LabelVirtualHost}"/>
|
||||||
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding VirtualHost}"/>
|
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding VirtualHost, UpdateSourceTrigger=PropertyChanged}" GotFocus="CaretToEnd"/>
|
||||||
|
|
||||||
<Label Grid.Column="0" Grid.Row="3" Content="{x:Static connection:ConnectionWindowStrings.LabelUsername}"/>
|
<Label Grid.Column="0" Grid.Row="3" Content="{x:Static connection:ConnectionWindowStrings.LabelUsername}"/>
|
||||||
<TextBox Grid.Column="1" Grid.Row="3" Text="{Binding Username}"/>
|
<TextBox Grid.Column="1" Grid.Row="3" Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}" GotFocus="CaretToEnd"/>
|
||||||
|
|
||||||
<Label Grid.Column="0" Grid.Row="4" Content="{x:Static connection:ConnectionWindowStrings.LabelPassword}"/>
|
<Label Grid.Column="0" Grid.Row="4" Content="{x:Static connection:ConnectionWindowStrings.LabelPassword}"/>
|
||||||
<PasswordBox Grid.Column="1" Grid.Row="4" ui:PasswordBoxAssistant.BindPassword="true" ui:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
|
<PasswordBox Grid.Column="1" Grid.Row="4" ui:PasswordBoxAssistant.BindPassword="true" ui:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" GotFocus="CaretToEnd"/>
|
||||||
|
|
||||||
<CheckBox Grid.Column="1" Grid.Row="6" Content="{x:Static connection:ConnectionWindowStrings.LabelSubscribe}" IsChecked="{Binding Subscribe}"/>
|
<CheckBox Grid.Column="1" Grid.Row="6" Content="{x:Static connection:ConnectionWindowStrings.LabelSubscribe}" IsChecked="{Binding Subscribe}"/>
|
||||||
|
|
||||||
<Label Grid.Column="0" Grid.Row="7" Content="{x:Static connection:ConnectionWindowStrings.LabelExchange}"/>
|
<Label Grid.Column="0" Grid.Row="7" Content="{x:Static connection:ConnectionWindowStrings.LabelExchange}"/>
|
||||||
<TextBox Grid.Column="1" Grid.Row="7" Text="{Binding Exchange}"/>
|
<TextBox Grid.Column="1" Grid.Row="7" Text="{Binding Exchange, UpdateSourceTrigger=PropertyChanged}" GotFocus="CaretToEnd"/>
|
||||||
|
|
||||||
<Label Grid.Column="0" Grid.Row="8" Content="{x:Static connection:ConnectionWindowStrings.LabelRoutingKey}"/>
|
<Label Grid.Column="0" Grid.Row="8" Content="{x:Static connection:ConnectionWindowStrings.LabelRoutingKey}"/>
|
||||||
<TextBox Grid.Column="1" Grid.Row="8" Text="{Binding RoutingKey}"/>
|
<TextBox Grid.Column="1" Grid.Row="8" Text="{Binding RoutingKey, UpdateSourceTrigger=PropertyChanged}" GotFocus="CaretToEnd"/>
|
||||||
</ui:GridLayout>
|
</ui:GridLayout>
|
||||||
</DockPanel>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|
||||||
|
@ -1,13 +1,28 @@
|
|||||||
using System.Windows;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using PettingZoo.Core.Settings;
|
||||||
|
|
||||||
namespace PettingZoo.UI.Connection
|
namespace PettingZoo.UI.Connection
|
||||||
{
|
{
|
||||||
public class WindowConnectionDialog : IConnectionDialog
|
public class WindowConnectionDialog : IConnectionDialog
|
||||||
{
|
{
|
||||||
public ConnectionDialogParams? Show(ConnectionDialogParams? defaultParams = null)
|
private readonly IConnectionSettingsRepository connectionSettingsRepository;
|
||||||
|
|
||||||
|
public WindowConnectionDialog(IConnectionSettingsRepository connectionSettingsRepository)
|
||||||
{
|
{
|
||||||
var viewModel = new ConnectionViewModel(defaultParams ?? ConnectionDialogParams.Default);
|
this.connectionSettingsRepository = connectionSettingsRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<ConnectionSettings?> Show()
|
||||||
|
{
|
||||||
|
var lastUsed = await connectionSettingsRepository.GetLastUsed();
|
||||||
|
|
||||||
|
var viewModel = new ConnectionViewModel(connectionSettingsRepository, lastUsed);
|
||||||
|
await viewModel.Initialize();
|
||||||
|
|
||||||
var window = new ConnectionWindow(viewModel)
|
var window = new ConnectionWindow(viewModel)
|
||||||
{
|
{
|
||||||
Owner = Application.Current.MainWindow
|
Owner = Application.Current.MainWindow
|
||||||
@ -18,9 +33,14 @@ namespace PettingZoo.UI.Connection
|
|||||||
window.DialogResult = true;
|
window.DialogResult = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
return window.ShowDialog().GetValueOrDefault()
|
|
||||||
? viewModel.ToModel()
|
if (!window.ShowDialog().GetValueOrDefault())
|
||||||
: null;
|
return null;
|
||||||
|
|
||||||
|
var newSettings = viewModel.ToModel();
|
||||||
|
await connectionSettingsRepository.StoreLastUsed(newSettings);
|
||||||
|
|
||||||
|
return newSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,10 +49,8 @@ namespace PettingZoo.UI.Connection
|
|||||||
{
|
{
|
||||||
public ConnectionWindow(ConnectionViewModel viewModel)
|
public ConnectionWindow(ConnectionViewModel viewModel)
|
||||||
{
|
{
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
|
||||||
|
|
||||||
InitializeComponent();
|
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -41,5 +59,14 @@ namespace PettingZoo.UI.Connection
|
|||||||
if (!char.IsDigit(args.Text, args.Text.Length - 1))
|
if (!char.IsDigit(args.Text, args.Text.Length - 1))
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void CaretToEnd(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is not TextBox textBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
textBox.CaretIndex = textBox.Text.Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace PettingZoo.UI.Connection {
|
|||||||
// class via a tool like ResGen or Visual Studio.
|
// class via a tool like ResGen or Visual Studio.
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
// with the /str option, or rebuild your VS project.
|
// with the /str option, or rebuild your VS project.
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.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()]
|
||||||
public class ConnectionWindowStrings {
|
public class ConnectionWindowStrings {
|
||||||
@ -70,7 +70,16 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to OK.
|
/// Looks up a localized string similar to Delete.
|
||||||
|
/// </summary>
|
||||||
|
public static string ButtonDelete {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ButtonDelete", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Connect.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string ButtonOK {
|
public static string ButtonOK {
|
||||||
get {
|
get {
|
||||||
@ -79,7 +88,43 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Exchange:.
|
/// Looks up a localized string similar to Save.
|
||||||
|
/// </summary>
|
||||||
|
public static string ButtonSave {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ButtonSave", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Save as....
|
||||||
|
/// </summary>
|
||||||
|
public static string ButtonSaveAs {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ButtonSaveAs", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Do you want to delete the connection settings "{0}"?.
|
||||||
|
/// </summary>
|
||||||
|
public static string DeleteConfirm {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeleteConfirm", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Delete connection.
|
||||||
|
/// </summary>
|
||||||
|
public static string DeleteConfirmTitle {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeleteConfirmTitle", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Exchange.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LabelExchange {
|
public static string LabelExchange {
|
||||||
get {
|
get {
|
||||||
@ -88,7 +133,7 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Host:.
|
/// Looks up a localized string similar to Host.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LabelHost {
|
public static string LabelHost {
|
||||||
get {
|
get {
|
||||||
@ -97,7 +142,7 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Password:.
|
/// Looks up a localized string similar to Password.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LabelPassword {
|
public static string LabelPassword {
|
||||||
get {
|
get {
|
||||||
@ -106,7 +151,7 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Port:.
|
/// Looks up a localized string similar to Port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LabelPort {
|
public static string LabelPort {
|
||||||
get {
|
get {
|
||||||
@ -115,7 +160,7 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Routing key:.
|
/// Looks up a localized string similar to Routing key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LabelRoutingKey {
|
public static string LabelRoutingKey {
|
||||||
get {
|
get {
|
||||||
@ -133,7 +178,7 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Username:.
|
/// Looks up a localized string similar to Username.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LabelUsername {
|
public static string LabelUsername {
|
||||||
get {
|
get {
|
||||||
@ -142,7 +187,7 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Virtual host:.
|
/// Looks up a localized string similar to Virtual host.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LabelVirtualHost {
|
public static string LabelVirtualHost {
|
||||||
get {
|
get {
|
||||||
@ -150,6 +195,15 @@ namespace PettingZoo.UI.Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to <New connection>.
|
||||||
|
/// </summary>
|
||||||
|
public static string LastUsedDisplayName {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LastUsedDisplayName", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Connection parameters.
|
/// Looks up a localized string similar to Connection parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -120,32 +120,50 @@
|
|||||||
<data name="ButtonCancel" xml:space="preserve">
|
<data name="ButtonCancel" xml:space="preserve">
|
||||||
<value>Cancel</value>
|
<value>Cancel</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ButtonDelete" xml:space="preserve">
|
||||||
|
<value>Delete</value>
|
||||||
|
</data>
|
||||||
<data name="ButtonOK" xml:space="preserve">
|
<data name="ButtonOK" xml:space="preserve">
|
||||||
<value>OK</value>
|
<value>Connect</value>
|
||||||
|
</data>
|
||||||
|
<data name="ButtonSave" xml:space="preserve">
|
||||||
|
<value>Save</value>
|
||||||
|
</data>
|
||||||
|
<data name="ButtonSaveAs" xml:space="preserve">
|
||||||
|
<value>Save as...</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeleteConfirm" xml:space="preserve">
|
||||||
|
<value>Do you want to delete the connection settings "{0}"?</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeleteConfirmTitle" xml:space="preserve">
|
||||||
|
<value>Delete connection</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelExchange" xml:space="preserve">
|
<data name="LabelExchange" xml:space="preserve">
|
||||||
<value>Exchange:</value>
|
<value>Exchange</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelHost" xml:space="preserve">
|
<data name="LabelHost" xml:space="preserve">
|
||||||
<value>Host:</value>
|
<value>Host</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelPassword" xml:space="preserve">
|
<data name="LabelPassword" xml:space="preserve">
|
||||||
<value>Password:</value>
|
<value>Password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelPort" xml:space="preserve">
|
<data name="LabelPort" xml:space="preserve">
|
||||||
<value>Port:</value>
|
<value>Port</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelRoutingKey" xml:space="preserve">
|
<data name="LabelRoutingKey" xml:space="preserve">
|
||||||
<value>Routing key:</value>
|
<value>Routing key</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelSubscribe" xml:space="preserve">
|
<data name="LabelSubscribe" xml:space="preserve">
|
||||||
<value>Subscribe</value>
|
<value>Subscribe</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelUsername" xml:space="preserve">
|
<data name="LabelUsername" xml:space="preserve">
|
||||||
<value>Username:</value>
|
<value>Username</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelVirtualHost" xml:space="preserve">
|
<data name="LabelVirtualHost" xml:space="preserve">
|
||||||
<value>Virtual host:</value>
|
<value>Virtual host</value>
|
||||||
|
</data>
|
||||||
|
<data name="LastUsedDisplayName" xml:space="preserve">
|
||||||
|
<value><New connection></value>
|
||||||
</data>
|
</data>
|
||||||
<data name="WindowTitle" xml:space="preserve">
|
<data name="WindowTitle" xml:space="preserve">
|
||||||
<value>Connection parameters</value>
|
<value>Connection parameters</value>
|
||||||
|
@ -1,43 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PettingZoo.Core.Settings;
|
||||||
|
|
||||||
namespace PettingZoo.UI.Connection
|
namespace PettingZoo.UI.Connection
|
||||||
{
|
{
|
||||||
public interface IConnectionDialog
|
public interface IConnectionDialog
|
||||||
{
|
{
|
||||||
ConnectionDialogParams? Show(ConnectionDialogParams? defaultParams = null);
|
Task<ConnectionSettings?> Show();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class ConnectionDialogParams
|
|
||||||
{
|
|
||||||
public string Host { get; }
|
|
||||||
public string VirtualHost { get; }
|
|
||||||
public int Port { get; }
|
|
||||||
public string Username { get; }
|
|
||||||
public string Password { get; }
|
|
||||||
|
|
||||||
public bool Subscribe { get; }
|
|
||||||
public string Exchange { get; }
|
|
||||||
public string RoutingKey { get; }
|
|
||||||
|
|
||||||
|
|
||||||
public static ConnectionDialogParams Default { get; } = new("localhost", "/", 5672, "guest", "guest", false, "", "#");
|
|
||||||
|
|
||||||
|
|
||||||
public ConnectionDialogParams(string host, string virtualHost, int port, string username, string password, bool subscribe, string exchange, string routingKey)
|
|
||||||
{
|
|
||||||
if (subscribe && (string.IsNullOrEmpty(exchange) || string.IsNullOrEmpty(routingKey)))
|
|
||||||
throw new ArgumentException(@"Exchange and RoutingKey must be provided when Subscribe is true", nameof(subscribe));
|
|
||||||
|
|
||||||
Host = host;
|
|
||||||
VirtualHost = virtualHost;
|
|
||||||
Port = port;
|
|
||||||
Username = username;
|
|
||||||
Password = password;
|
|
||||||
|
|
||||||
Subscribe = subscribe;
|
|
||||||
Exchange = exchange;
|
|
||||||
RoutingKey = routingKey;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,11 @@ using System.Windows;
|
|||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using PettingZoo.UI.Connection;
|
using PettingZoo.UI.Connection;
|
||||||
using PettingZoo.UI.Subscribe;
|
using PettingZoo.UI.Subscribe;
|
||||||
using PettingZoo.UI.Tab;
|
|
||||||
|
// TODO improve readability of the connection status (especially when connecting/disconnected)
|
||||||
|
|
||||||
namespace PettingZoo.UI.Main
|
namespace PettingZoo.UI.Main
|
||||||
{
|
{
|
||||||
// TODO support undocking tabs (and redocking afterwards)
|
|
||||||
// TODO allow tab reordering
|
|
||||||
|
|
||||||
#pragma warning disable CA1001 // MainWindow can't be IDisposable, handled instead in OnDispatcherShutDownStarted
|
#pragma warning disable CA1001 // MainWindow can't be IDisposable, handled instead in OnDispatcherShutDownStarted
|
||||||
public partial class MainWindow
|
public partial class MainWindow
|
||||||
{
|
{
|
||||||
@ -20,9 +18,9 @@ namespace PettingZoo.UI.Main
|
|||||||
{
|
{
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||||
|
|
||||||
InitializeComponent();
|
|
||||||
viewModel = new MainWindowViewModel(connectionFactory, connectionDialog, subscribeDialog);
|
viewModel = new MainWindowViewModel(connectionFactory, connectionDialog, subscribeDialog);
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
Dispatcher.ShutdownStarted += OnDispatcherShutDownStarted;
|
Dispatcher.ShutdownStarted += OnDispatcherShutDownStarted;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ namespace PettingZoo.UI.Main
|
|||||||
private readonly ISubscribeDialog subscribeDialog;
|
private readonly ISubscribeDialog subscribeDialog;
|
||||||
private readonly ITabFactory tabFactory;
|
private readonly ITabFactory tabFactory;
|
||||||
|
|
||||||
private ConnectionDialogParams? connectionDialogParams;
|
|
||||||
private SubscribeDialogParams? subscribeDialogParams;
|
private SubscribeDialogParams? subscribeDialogParams;
|
||||||
private IConnection? connection;
|
private IConnection? connection;
|
||||||
private string connectionStatus;
|
private string connectionStatus;
|
||||||
@ -44,11 +43,16 @@ namespace PettingZoo.UI.Main
|
|||||||
public ITab? ActiveTab
|
public ITab? ActiveTab
|
||||||
{
|
{
|
||||||
get => activeTab;
|
get => activeTab;
|
||||||
set => SetField(ref activeTab, value, otherPropertiesChanged: new []
|
set
|
||||||
{
|
{
|
||||||
nameof(ToolbarCommands),
|
var currentTab = activeTab;
|
||||||
nameof(ToolbarCommandsSeparatorVisibility)
|
|
||||||
});
|
if (!SetField(ref activeTab, value, otherPropertiesChanged: new[] { nameof(ToolbarCommands), nameof(ToolbarCommandsSeparatorVisibility) }))
|
||||||
|
return;
|
||||||
|
|
||||||
|
currentTab?.Deactivate();
|
||||||
|
activeTab?.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommand ConnectCommand => connectCommand;
|
public ICommand ConnectCommand => connectCommand;
|
||||||
@ -87,6 +91,8 @@ namespace PettingZoo.UI.Main
|
|||||||
|
|
||||||
public async ValueTask DisposeAsync()
|
public async ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
await connection.DisposeAsync();
|
await connection.DisposeAsync();
|
||||||
}
|
}
|
||||||
@ -94,28 +100,22 @@ namespace PettingZoo.UI.Main
|
|||||||
|
|
||||||
private async void ConnectExecute()
|
private async void ConnectExecute()
|
||||||
{
|
{
|
||||||
var newParams = connectionDialog.Show(connectionDialogParams);
|
var connectionSettings = await connectionDialog.Show();
|
||||||
|
if (connectionSettings == null)
|
||||||
// TODO support command-line parameters for easier testing
|
|
||||||
// var newParams = new ConnectionDialogParams("localhost", "/", 5672, "guest", "guest", true, "test", "#");
|
|
||||||
|
|
||||||
if (newParams == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
await connection.DisposeAsync();
|
await connection.DisposeAsync();
|
||||||
|
|
||||||
connectionDialogParams = newParams;
|
|
||||||
connection = connectionFactory.CreateConnection(new ConnectionParams(
|
connection = connectionFactory.CreateConnection(new ConnectionParams(
|
||||||
connectionDialogParams.Host, connectionDialogParams.VirtualHost, connectionDialogParams.Port,
|
connectionSettings.Host, connectionSettings.VirtualHost, connectionSettings.Port,
|
||||||
connectionDialogParams.Username, connectionDialogParams.Password));
|
connectionSettings.Username, connectionSettings.Password!));
|
||||||
connection.StatusChanged += ConnectionStatusChanged;
|
connection.StatusChanged += ConnectionStatusChanged;
|
||||||
|
|
||||||
if (connectionDialogParams.Subscribe)
|
if (connectionSettings.Subscribe)
|
||||||
{
|
{
|
||||||
var subscriber = connection.Subscribe(connectionDialogParams.Exchange, connectionDialogParams.RoutingKey);
|
var subscriber = connection.Subscribe(connectionSettings.Exchange, connectionSettings.RoutingKey);
|
||||||
AddTab(tabFactory.CreateSubscriberTab(connection, subscriber));
|
AddTab(tabFactory.CreateSubscriberTab(connection, subscriber));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionChanged();
|
ConnectionChanged();
|
||||||
@ -132,9 +132,7 @@ namespace PettingZoo.UI.Main
|
|||||||
connection = null;
|
connection = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionDialogParams = null;
|
|
||||||
ConnectionStatus = GetConnectionStatus(null);
|
ConnectionStatus = GetConnectionStatus(null);
|
||||||
|
|
||||||
ConnectionChanged();
|
ConnectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ namespace PettingZoo.UI.Subscribe
|
|||||||
{
|
{
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||||
|
|
||||||
InitializeComponent();
|
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,14 @@ namespace PettingZoo.UI.Tab
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface ITab : ITabToolbarCommands
|
public interface ITabActivate
|
||||||
|
{
|
||||||
|
void Activate();
|
||||||
|
void Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface ITab : ITabToolbarCommands, ITabActivate
|
||||||
{
|
{
|
||||||
string Title { get; }
|
string Title { get; }
|
||||||
ContentControl Content { get; }
|
ContentControl Content { get; }
|
||||||
|
10
PettingZoo/UI/Tab/Publisher/IPublishDestination.cs
Normal file
10
PettingZoo/UI/Tab/Publisher/IPublishDestination.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
|
{
|
||||||
|
public interface IPublishDestination
|
||||||
|
{
|
||||||
|
string Exchange { get; }
|
||||||
|
string RoutingKey { get; }
|
||||||
|
|
||||||
|
string? GetReplyTo();
|
||||||
|
}
|
||||||
|
}
|
@ -4,24 +4,60 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
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:ui="clr-namespace:PettingZoo.UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance res:DesignTimePublisherViewModel, IsDesignTimeCreatable=True}"
|
d:DataContext="{d:DesignInstance res:DesignTimePublisherViewModel, IsDesignTimeCreatable=True}"
|
||||||
Background="White">
|
Background="White">
|
||||||
<Grid Margin="4">
|
<ui:GridLayout Style="{StaticResource Form}" Margin="4" Grid.IsSharedSizeScope="True">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="16"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="16"/>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" Grid.Row="0" HorizontalAlignment="Center">
|
<Label Grid.Row="0" Grid.Column="1">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<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}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelExchange}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Exchange}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelRoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding RoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelQueue}" Visibility="{Binding QueueVisibility}" />
|
||||||
|
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Queue}" Visibility="{Binding QueueVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelReplyTo}" />
|
||||||
|
<StackPanel Orientation="Horizontal" Grid.Row="5" Grid.Column="1">
|
||||||
|
<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}" />
|
||||||
|
</StackPanel>
|
||||||
|
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding ReplyTo}" IsEnabled="{Binding ReplyToSpecified}" />
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center">
|
||||||
<ToggleButton Content="{x:Static res:PublisherViewStrings.OptionMessageTypeRaw}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeRaw}" />
|
<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}" />
|
<ToggleButton Content="{x:Static res:PublisherViewStrings.OptionMessageTypeTapeti}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeTapeti}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Auto">
|
||||||
<ContentControl Margin="0 8 0 0" Content="{Binding MessageTypeControl}" />
|
<ContentControl Margin="0 8 0 0" Content="{Binding MessageTypeControl}" />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Grid>
|
</ui:GridLayout>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -9,8 +9,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
{
|
{
|
||||||
public PublisherView(PublisherViewModel viewModel)
|
public PublisherView(PublisherViewModel viewModel)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
|
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
|
||||||
Background = Brushes.Transparent;
|
Background = Brushes.Transparent;
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
|
|
||||||
|
// TODO publish button in page instead of just in toolbar
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Publisher
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
{
|
{
|
||||||
public enum MessageType
|
public enum MessageType
|
||||||
@ -14,9 +16,18 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class PublisherViewModel : BaseViewModel, ITabToolbarCommands
|
public class PublisherViewModel : BaseViewModel, ITabToolbarCommands, IPublishDestination
|
||||||
{
|
{
|
||||||
private readonly IConnection connection;
|
private readonly IConnection connection;
|
||||||
|
private readonly ITabFactory tabFactory;
|
||||||
|
private readonly ITabHost tabHost;
|
||||||
|
|
||||||
|
private bool sendToExchange = true;
|
||||||
|
private string exchange = "";
|
||||||
|
private string routingKey = "";
|
||||||
|
private string queue = "";
|
||||||
|
private string replyTo = "";
|
||||||
|
private bool replyToSpecified = true;
|
||||||
|
|
||||||
private MessageType messageType;
|
private MessageType messageType;
|
||||||
private UserControl? messageTypeControl;
|
private UserControl? messageTypeControl;
|
||||||
@ -29,6 +40,66 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
private readonly TabToolbarCommand[] toolbarCommands;
|
private readonly TabToolbarCommand[] toolbarCommands;
|
||||||
|
|
||||||
|
|
||||||
|
public bool SendToExchange
|
||||||
|
{
|
||||||
|
get => sendToExchange;
|
||||||
|
set => SetField(ref sendToExchange, value, otherPropertiesChanged: new[] { nameof(SendToQueue), nameof(ExchangeVisibility), nameof(QueueVisibility) });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool SendToQueue
|
||||||
|
{
|
||||||
|
get => !SendToExchange;
|
||||||
|
set => SendToExchange = !value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Exchange
|
||||||
|
{
|
||||||
|
get => exchange;
|
||||||
|
set => SetField(ref exchange, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string RoutingKey
|
||||||
|
{
|
||||||
|
get => routingKey;
|
||||||
|
set => SetField(ref routingKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Queue
|
||||||
|
{
|
||||||
|
get => queue;
|
||||||
|
set => SetField(ref queue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string ReplyTo
|
||||||
|
{
|
||||||
|
get => replyTo;
|
||||||
|
set => SetField(ref replyTo, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool ReplyToSpecified
|
||||||
|
{
|
||||||
|
get => replyToSpecified;
|
||||||
|
set => SetField(ref replyToSpecified, value, otherPropertiesChanged: new[] { nameof(ReplyToNewSubscriber) });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool ReplyToNewSubscriber
|
||||||
|
{
|
||||||
|
get => !ReplyToSpecified;
|
||||||
|
set => ReplyToSpecified = !value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual Visibility ExchangeVisibility => SendToExchange ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
public virtual Visibility QueueVisibility => SendToQueue ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
|
||||||
public MessageType MessageType
|
public MessageType MessageType
|
||||||
{
|
{
|
||||||
get => messageType;
|
get => messageType;
|
||||||
@ -70,13 +141,21 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
|
|
||||||
// TODO make more dynamic, include entered routing key for example
|
// TODO make more dynamic, include entered routing key for example
|
||||||
|
#pragma warning disable CA1822 // Mark members as static - can't, it's part of the interface you silly, that would break the build
|
||||||
public string Title => "Publish";
|
public string Title => "Publish";
|
||||||
|
#pragma warning restore CA1822
|
||||||
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
||||||
|
|
||||||
|
|
||||||
public PublisherViewModel(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
string IPublishDestination.Exchange => SendToExchange ? Exchange : "";
|
||||||
|
string IPublishDestination.RoutingKey => SendToExchange ? RoutingKey : Queue;
|
||||||
|
|
||||||
|
|
||||||
|
public PublisherViewModel(ITabHost tabHost, ITabFactory tabFactory, IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||||
{
|
{
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
this.tabFactory = tabFactory;
|
||||||
|
this.tabHost = tabHost;
|
||||||
|
|
||||||
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||||
|
|
||||||
@ -109,7 +188,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
switch (value)
|
switch (value)
|
||||||
{
|
{
|
||||||
case MessageType.Raw:
|
case MessageType.Raw:
|
||||||
var rawPublisherViewModel = new RawPublisherViewModel(connection);
|
var rawPublisherViewModel = new RawPublisherViewModel(connection, this);
|
||||||
rawPublisherView ??= new RawPublisherView(rawPublisherViewModel);
|
rawPublisherView ??= new RawPublisherView(rawPublisherViewModel);
|
||||||
MessageTypeControl = rawPublisherView;
|
MessageTypeControl = rawPublisherView;
|
||||||
|
|
||||||
@ -117,7 +196,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType.Tapeti:
|
case MessageType.Tapeti:
|
||||||
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection);
|
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this);
|
||||||
tapetiPublisherView ??= new TapetiPublisherView(tapetiPublisherViewModel);
|
tapetiPublisherView ??= new TapetiPublisherView(tapetiPublisherViewModel);
|
||||||
MessageTypeControl = tapetiPublisherView;
|
MessageTypeControl = tapetiPublisherView;
|
||||||
|
|
||||||
@ -134,28 +213,49 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
private void SetMessageTypeControl(ReceivedMessageInfo fromReceivedMessage)
|
private void SetMessageTypeControl(ReceivedMessageInfo fromReceivedMessage)
|
||||||
{
|
{
|
||||||
|
Exchange = fromReceivedMessage.Exchange;
|
||||||
|
RoutingKey = fromReceivedMessage.RoutingKey;
|
||||||
|
|
||||||
|
|
||||||
if (TapetiPublisherViewModel.IsTapetiMessage(fromReceivedMessage))
|
if (TapetiPublisherViewModel.IsTapetiMessage(fromReceivedMessage))
|
||||||
{
|
{
|
||||||
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, fromReceivedMessage);
|
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, fromReceivedMessage);
|
||||||
tapetiPublisherView = new TapetiPublisherView(tapetiPublisherViewModel);
|
tapetiPublisherView = new TapetiPublisherView(tapetiPublisherViewModel);
|
||||||
|
|
||||||
MessageType = MessageType.Tapeti;
|
MessageType = MessageType.Tapeti;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var rawPublisherViewModel = new RawPublisherViewModel(connection, fromReceivedMessage);
|
var rawPublisherViewModel = new RawPublisherViewModel(connection, this, fromReceivedMessage);
|
||||||
rawPublisherView = new RawPublisherView(rawPublisherViewModel);
|
rawPublisherView = new RawPublisherView(rawPublisherViewModel);
|
||||||
|
|
||||||
MessageType = MessageType.Raw;
|
MessageType = MessageType.Raw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string? GetReplyTo()
|
||||||
|
{
|
||||||
|
if (ReplyToSpecified)
|
||||||
|
return string.IsNullOrEmpty(ReplyTo) ? null : ReplyTo;
|
||||||
|
|
||||||
|
var subscriber = connection.Subscribe();
|
||||||
|
var tab = tabFactory.CreateSubscriberTab(connection, subscriber);
|
||||||
|
tabHost.AddTab(tab);
|
||||||
|
|
||||||
|
subscriber.Start();
|
||||||
|
return subscriber.QueueName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class DesignTimePublisherViewModel : PublisherViewModel
|
public class DesignTimePublisherViewModel : PublisherViewModel
|
||||||
{
|
{
|
||||||
public DesignTimePublisherViewModel() : base(null!)
|
public DesignTimePublisherViewModel() : base(null!, null!, null!)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Visibility ExchangeVisibility => Visibility.Visible;
|
||||||
|
public override Visibility QueueVisibility => Visibility.Visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,15 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Exchange.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelExchange {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelExchange", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Message type: .
|
/// Looks up a localized string similar to Message type: .
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -78,6 +87,69 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Queue.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelQueue {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelQueue", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Reply To.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelReplyTo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelReplyTo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to New subscriber tab.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelReplyToNewSubscriber {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelReplyToNewSubscriber", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Specified queue.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelReplyToSpecified {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelReplyToSpecified", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Routing key.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelRoutingKey {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelRoutingKey", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Publish to exchange (topic).
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelSendToExchange {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelSendToExchange", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Publish to queue (direct).
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelSendToQueue {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelSendToQueue", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Raw message.
|
/// Looks up a localized string similar to Raw message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -120,9 +120,33 @@
|
|||||||
<data name="CommandPublish" xml:space="preserve">
|
<data name="CommandPublish" xml:space="preserve">
|
||||||
<value>Publish</value>
|
<value>Publish</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LabelExchange" xml:space="preserve">
|
||||||
|
<value>Exchange</value>
|
||||||
|
</data>
|
||||||
<data name="LabelMessageType" xml:space="preserve">
|
<data name="LabelMessageType" xml:space="preserve">
|
||||||
<value>Message type: </value>
|
<value>Message type: </value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LabelQueue" xml:space="preserve">
|
||||||
|
<value>Queue</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelReplyTo" xml:space="preserve">
|
||||||
|
<value>Reply To</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelReplyToNewSubscriber" xml:space="preserve">
|
||||||
|
<value>New subscriber tab</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelReplyToSpecified" xml:space="preserve">
|
||||||
|
<value>Specified queue</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelRoutingKey" xml:space="preserve">
|
||||||
|
<value>Routing key</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelSendToExchange" xml:space="preserve">
|
||||||
|
<value>Publish to exchange (topic)</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelSendToQueue" xml:space="preserve">
|
||||||
|
<value>Publish to queue (direct)</value>
|
||||||
|
</data>
|
||||||
<data name="OptionMessageTypeRaw" xml:space="preserve">
|
<data name="OptionMessageTypeRaw" xml:space="preserve">
|
||||||
<value>Raw message</value>
|
<value>Raw message</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -11,17 +11,11 @@
|
|||||||
Background="White">
|
Background="White">
|
||||||
<ui:GridLayout Style="{StaticResource Form}">
|
<ui:GridLayout Style="{StaticResource Form}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<ui:GridLayout.RowDefinitions>
|
<ui:GridLayout.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="16"/>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
@ -42,31 +36,14 @@
|
|||||||
</ui:GridLayout.RowDefinitions>
|
</ui:GridLayout.RowDefinitions>
|
||||||
|
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="1">
|
<Label Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelDeliveryMode}" />
|
||||||
<StackPanel Orientation="Horizontal">
|
<ComboBox Grid.Column="1" SelectedIndex="{Binding DeliveryModeIndex}">
|
||||||
<RadioButton Content="{x:Static publisher:RawPublisherViewStrings.LabelSendToExchange}" IsChecked="{Binding SendToExchange}" Style="{StaticResource TypeSelection}" />
|
|
||||||
<RadioButton Content="{x:Static publisher:RawPublisherViewStrings.LabelSendToQueue}" IsChecked="{Binding SendToQueue}" Style="{StaticResource TypeSelection}" />
|
|
||||||
</StackPanel>
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelExchange}" Visibility="{Binding ExchangeVisibility}" />
|
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Exchange}" Visibility="{Binding ExchangeVisibility}" />
|
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelRoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
|
||||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding RoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
|
||||||
|
|
||||||
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelQueue}" Visibility="{Binding QueueVisibility}" />
|
|
||||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Queue}" Visibility="{Binding QueueVisibility}" />
|
|
||||||
|
|
||||||
|
|
||||||
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelDeliveryMode}" />
|
|
||||||
<ComboBox Grid.Row="5" Grid.Column="1" SelectedIndex="{Binding DeliveryModeIndex}">
|
|
||||||
<ComboBoxItem Content="{x:Static publisher:RawPublisherViewStrings.DeliveryModeNonPersistent}" />
|
<ComboBoxItem Content="{x:Static publisher:RawPublisherViewStrings.DeliveryModeNonPersistent}" />
|
||||||
<ComboBoxItem Content="{x:Static publisher:RawPublisherViewStrings.DeliveryModePersistent}" />
|
<ComboBoxItem Content="{x:Static publisher:RawPublisherViewStrings.DeliveryModePersistent}" />
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
|
|
||||||
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelHeaders}" />
|
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelHeaders}" />
|
||||||
<ItemsControl Grid.Row="6" Grid.Column="1" ItemsSource="{Binding Headers}">
|
<ItemsControl Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Headers}">
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<StackPanel Orientation="Vertical" />
|
<StackPanel Orientation="Vertical" />
|
||||||
@ -116,43 +93,40 @@
|
|||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
|
|
||||||
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelProperties}" Style="{StaticResource SectionLabel}"/>
|
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelProperties}" Style="{StaticResource SectionLabel}"/>
|
||||||
|
|
||||||
<Label Grid.Row="8" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelContentType}" />
|
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelContentType}" />
|
||||||
<TextBox Grid.Row="8" Grid.Column="1" Text="{Binding ContentType}" />
|
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding ContentType, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
<Label Grid.Row="9" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelCorrelationId}" />
|
<Label Grid.Row="4" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelCorrelationId}" />
|
||||||
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding CorrelationId}" />
|
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding CorrelationId, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
<Label Grid.Row="10" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelReplyTo}" />
|
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelAppId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding ReplyTo}" />
|
<TextBox Grid.Row="5" Grid.Column="1" Text="{Binding AppId, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="11" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelAppId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelContentEncoding}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
<TextBox Grid.Row="11" Grid.Column="1" Text="{Binding AppId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding ContentEncoding, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="12" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelContentEncoding}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelExpiration}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
<TextBox Grid.Row="12" Grid.Column="1" Text="{Binding ContentEncoding}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding Expiration, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="13" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelExpiration}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<Label Grid.Row="8" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelMessageId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
<TextBox Grid.Row="13" Grid.Column="1" Text="{Binding Expiration}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<TextBox Grid.Row="8" Grid.Column="1" Text="{Binding MessageId, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="14" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelMessageId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<Label Grid.Row="9" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPriority}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
<TextBox Grid.Row="14" Grid.Column="1" Text="{Binding MessageId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding Priority, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="15" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPriority}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<Label Grid.Row="10" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelTimestamp}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
<TextBox Grid.Row="15" Grid.Column="1" Text="{Binding Priority}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding Timestamp, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="16" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelTimestamp}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<Label Grid.Row="11" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelType}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
<TextBox Grid.Row="16" Grid.Column="1" Text="{Binding Timestamp}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<TextBox Grid.Row="11" Grid.Column="1" Text="{Binding TypeProperty, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="17" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelType}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<Label Grid.Row="12" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelUserId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
<TextBox Grid.Row="17" Grid.Column="1" Text="{Binding TypeProperty}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
<TextBox Grid.Row="12" Grid.Column="1" Text="{Binding UserId, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
<Label Grid.Row="18" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelUserId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
|
||||||
<TextBox Grid.Row="18" Grid.Column="1" Text="{Binding UserId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
|
||||||
|
|
||||||
|
|
||||||
<Button Grid.Row="19" Grid.Column="1" Content="{Binding PropertiesExpandedCollapsedText}" Command="{Binding PropertiesExpandCollapseCommand}" Cursor="Hand">
|
<Button Grid.Row="13" Grid.Column="1" Content="{Binding PropertiesExpandedCollapsedText}" Command="{Binding PropertiesExpandCollapseCommand}" Cursor="Hand">
|
||||||
<Button.Template>
|
<Button.Template>
|
||||||
<ControlTemplate TargetType="{x:Type Button}">
|
<ControlTemplate TargetType="{x:Type Button}">
|
||||||
<ContentPresenter />
|
<ContentPresenter />
|
||||||
@ -160,7 +134,7 @@
|
|||||||
</Button.Template>
|
</Button.Template>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Label Grid.Row="21" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPayload}" />
|
<Label Grid.Row="15" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPayload}" />
|
||||||
<TextBox Grid.Row="21" Grid.Column="1" Text="{Binding Payload}" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" Height="150" />
|
<TextBox Grid.Row="15" Grid.Column="1" Text="{Binding Payload, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource Payload}" Height="150" />
|
||||||
</ui:GridLayout>
|
</ui:GridLayout>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -13,16 +13,16 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class RawPublisherView
|
public partial class RawPublisherView
|
||||||
{
|
{
|
||||||
private RawPublisherViewModel viewModel;
|
private readonly RawPublisherViewModel viewModel;
|
||||||
private DispatcherTimer checkEmptyHeaderTimer;
|
private readonly DispatcherTimer checkEmptyHeaderTimer;
|
||||||
|
|
||||||
|
|
||||||
public RawPublisherView(RawPublisherViewModel viewModel)
|
public RawPublisherView(RawPublisherViewModel viewModel)
|
||||||
{
|
{
|
||||||
this.viewModel = viewModel;
|
this.viewModel = viewModel;
|
||||||
|
|
||||||
InitializeComponent();
|
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
checkEmptyHeaderTimer = new DispatcherTimer();
|
checkEmptyHeaderTimer = new DispatcherTimer();
|
||||||
checkEmptyHeaderTimer.Tick += CheckEmptyHeaderTimerOnTick;
|
checkEmptyHeaderTimer.Tick += CheckEmptyHeaderTimerOnTick;
|
||||||
|
@ -13,20 +13,15 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
public class RawPublisherViewModel : BaseViewModel
|
public class RawPublisherViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
private readonly IConnection connection;
|
private readonly IConnection connection;
|
||||||
|
private readonly IPublishDestination publishDestination;
|
||||||
private readonly DelegateCommand publishCommand;
|
private readonly DelegateCommand publishCommand;
|
||||||
private readonly DelegateCommand propertiesExpandCollapseCommand;
|
private readonly DelegateCommand propertiesExpandCollapseCommand;
|
||||||
private bool propertiesExpanded;
|
private bool propertiesExpanded;
|
||||||
|
|
||||||
private bool sendToExchange = true;
|
|
||||||
private string exchange = "";
|
|
||||||
private string routingKey = "";
|
|
||||||
private string queue = "";
|
|
||||||
|
|
||||||
private MessageDeliveryMode deliveryMode;
|
private MessageDeliveryMode deliveryMode;
|
||||||
|
|
||||||
private string contentType = "application/json";
|
private string contentType = "application/json";
|
||||||
private string correlationId = "";
|
private string correlationId = "";
|
||||||
private string replyTo = "";
|
|
||||||
private string appId = "";
|
private string appId = "";
|
||||||
private string contentEncoding = "";
|
private string contentEncoding = "";
|
||||||
private string expiration = "";
|
private string expiration = "";
|
||||||
@ -38,44 +33,6 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
private string payload = "";
|
private string payload = "";
|
||||||
|
|
||||||
|
|
||||||
public bool SendToExchange
|
|
||||||
{
|
|
||||||
get => sendToExchange;
|
|
||||||
set => SetField(ref sendToExchange, value, otherPropertiesChanged: new[] { nameof(SendToQueue), nameof(ExchangeVisibility), nameof(QueueVisibility) });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public bool SendToQueue
|
|
||||||
{
|
|
||||||
get => !SendToExchange;
|
|
||||||
set => SendToExchange = !value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string Exchange
|
|
||||||
{
|
|
||||||
get => exchange;
|
|
||||||
set => SetField(ref exchange, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string RoutingKey
|
|
||||||
{
|
|
||||||
get => routingKey;
|
|
||||||
set => SetField(ref routingKey, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string Queue
|
|
||||||
{
|
|
||||||
get => queue;
|
|
||||||
set => SetField(ref queue, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public virtual Visibility ExchangeVisibility => SendToExchange ? Visibility.Visible : Visibility.Collapsed;
|
|
||||||
public virtual Visibility QueueVisibility => SendToQueue ? Visibility.Visible : Visibility.Collapsed;
|
|
||||||
|
|
||||||
|
|
||||||
public int DeliveryModeIndex
|
public int DeliveryModeIndex
|
||||||
{
|
{
|
||||||
@ -98,13 +55,6 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public string ReplyTo
|
|
||||||
{
|
|
||||||
get => replyTo;
|
|
||||||
set => SetField(ref replyTo, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string AppId
|
public string AppId
|
||||||
{
|
{
|
||||||
get => appId;
|
get => appId;
|
||||||
@ -194,20 +144,17 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
protected Header LastHeader;
|
protected Header LastHeader;
|
||||||
|
|
||||||
|
|
||||||
public RawPublisherViewModel(IConnection connection, ReceivedMessageInfo? receivedMessage = null)
|
public RawPublisherViewModel(IConnection connection, IPublishDestination publishDestination, ReceivedMessageInfo? receivedMessage = null)
|
||||||
{
|
{
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
this.publishDestination = publishDestination;
|
||||||
|
|
||||||
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||||
propertiesExpandCollapseCommand = new DelegateCommand(PropertiesExpandCollapseExecute);
|
propertiesExpandCollapseCommand = new DelegateCommand(PropertiesExpandCollapseExecute);
|
||||||
|
|
||||||
if (receivedMessage != null)
|
if (receivedMessage != null)
|
||||||
{
|
{
|
||||||
Exchange = receivedMessage.Exchange;
|
|
||||||
RoutingKey = receivedMessage.RoutingKey;
|
|
||||||
|
|
||||||
CorrelationId = receivedMessage.Properties.CorrelationId ?? "";
|
CorrelationId = receivedMessage.Properties.CorrelationId ?? "";
|
||||||
ReplyTo = receivedMessage.Properties.ReplyTo ?? "";
|
|
||||||
Priority = receivedMessage.Properties.Priority?.ToString() ?? "";
|
Priority = receivedMessage.Properties.Priority?.ToString() ?? "";
|
||||||
AppId = receivedMessage.Properties.AppId ?? "";
|
AppId = receivedMessage.Properties.AppId ?? "";
|
||||||
ContentEncoding = receivedMessage.Properties.ContentEncoding ?? "";
|
ContentEncoding = receivedMessage.Properties.ContentEncoding ?? "";
|
||||||
@ -270,15 +217,14 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO check parsing of priority and timestamp
|
// TODO check parsing of priority and timestamp
|
||||||
// TODO support for Reply To to dynamic queue which waits for a message (or opens a new subscriber tab?)
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
// TODO background worker / async
|
// TODO background worker / async
|
||||||
|
|
||||||
connection.Publish(new PublishMessageInfo(
|
connection.Publish(new PublishMessageInfo(
|
||||||
SendToExchange ? Exchange : "",
|
publishDestination.Exchange,
|
||||||
SendToExchange ? RoutingKey : Queue,
|
publishDestination.RoutingKey,
|
||||||
Encoding.UTF8.GetBytes(Payload),
|
Encoding.UTF8.GetBytes(Payload),
|
||||||
new MessageProperties(headers)
|
new MessageProperties(headers)
|
||||||
{
|
{
|
||||||
@ -290,7 +236,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
Expiration = NullIfEmpty(Expiration),
|
Expiration = NullIfEmpty(Expiration),
|
||||||
MessageId = NullIfEmpty(MessageId),
|
MessageId = NullIfEmpty(MessageId),
|
||||||
Priority = !string.IsNullOrEmpty(Priority) && byte.TryParse(Priority, out var priorityValue) ? priorityValue : null,
|
Priority = !string.IsNullOrEmpty(Priority) && byte.TryParse(Priority, out var priorityValue) ? priorityValue : null,
|
||||||
ReplyTo = NullIfEmpty(ReplyTo),
|
ReplyTo = publishDestination.GetReplyTo(),
|
||||||
Timestamp = !string.IsNullOrEmpty(Timestamp) && DateTime.TryParse(Timestamp, out var timestampValue) ? timestampValue : null,
|
Timestamp = !string.IsNullOrEmpty(Timestamp) && DateTime.TryParse(Timestamp, out var timestampValue) ? timestampValue : null,
|
||||||
Type = NullIfEmpty(TypeProperty),
|
Type = NullIfEmpty(TypeProperty),
|
||||||
UserId = NullIfEmpty(UserId)
|
UserId = NullIfEmpty(UserId)
|
||||||
@ -341,7 +287,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
public class DesignTimeRawPublisherViewModel : RawPublisherViewModel
|
public class DesignTimeRawPublisherViewModel : RawPublisherViewModel
|
||||||
{
|
{
|
||||||
public DesignTimeRawPublisherViewModel() : base(null!)
|
public DesignTimeRawPublisherViewModel() : base(null!, null!)
|
||||||
{
|
{
|
||||||
PropertiesExpanded = true;
|
PropertiesExpanded = true;
|
||||||
|
|
||||||
@ -349,9 +295,5 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
capturedLastHeader.Key = "Example";
|
capturedLastHeader.Key = "Example";
|
||||||
capturedLastHeader.Value = "header";
|
capturedLastHeader.Value = "header";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override Visibility ExchangeVisibility => Visibility.Visible;
|
|
||||||
public override Visibility QueueVisibility => Visibility.Visible;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,15 +141,6 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Exchange.
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelExchange {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelExchange", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Expiration.
|
/// Looks up a localized string similar to Expiration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -204,51 +195,6 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Queue.
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelQueue {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelQueue", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Reply To.
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelReplyTo {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelReplyTo", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Routing key.
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelRoutingKey {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelRoutingKey", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Publish to exchange (topic).
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelSendToExchange {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelSendToExchange", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Publish to queue (direct).
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelSendToQueue {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelSendToQueue", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Timestamp.
|
/// Looks up a localized string similar to Timestamp.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -144,9 +144,6 @@
|
|||||||
<data name="LabelDeliveryMode" xml:space="preserve">
|
<data name="LabelDeliveryMode" xml:space="preserve">
|
||||||
<value>Delivery mode</value>
|
<value>Delivery mode</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelExchange" xml:space="preserve">
|
|
||||||
<value>Exchange</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelExpiration" xml:space="preserve">
|
<data name="LabelExpiration" xml:space="preserve">
|
||||||
<value>Expiration</value>
|
<value>Expiration</value>
|
||||||
</data>
|
</data>
|
||||||
@ -165,21 +162,6 @@
|
|||||||
<data name="LabelProperties" xml:space="preserve">
|
<data name="LabelProperties" xml:space="preserve">
|
||||||
<value>Properties</value>
|
<value>Properties</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelQueue" xml:space="preserve">
|
|
||||||
<value>Queue</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelReplyTo" xml:space="preserve">
|
|
||||||
<value>Reply To</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelRoutingKey" xml:space="preserve">
|
|
||||||
<value>Routing key</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelSendToExchange" xml:space="preserve">
|
|
||||||
<value>Publish to exchange (topic)</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelSendToQueue" xml:space="preserve">
|
|
||||||
<value>Publish to queue (direct)</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelTimestamp" xml:space="preserve">
|
<data name="LabelTimestamp" xml:space="preserve">
|
||||||
<value>Timestamp</value>
|
<value>Timestamp</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -11,17 +11,11 @@
|
|||||||
Background="White">
|
Background="White">
|
||||||
<ui:GridLayout Style="{StaticResource Form}">
|
<ui:GridLayout Style="{StaticResource Form}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<ui:GridLayout.RowDefinitions>
|
<ui:GridLayout.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="16"/>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
@ -32,47 +26,28 @@
|
|||||||
</ui:GridLayout.RowDefinitions>
|
</ui:GridLayout.RowDefinitions>
|
||||||
|
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="1">
|
<Label Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelProperties}" Style="{StaticResource SectionLabel}"/>
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<RadioButton Content="{x:Static publisher:TapetiPublisherViewStrings.LabelSendToExchange}" IsChecked="{Binding SendToExchange}" Style="{StaticResource TypeSelection}" />
|
|
||||||
<RadioButton Content="{x:Static publisher:TapetiPublisherViewStrings.LabelSendToQueue}" IsChecked="{Binding SendToQueue}" Style="{StaticResource TypeSelection}" />
|
|
||||||
</StackPanel>
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelExchange}" Visibility="{Binding ExchangeVisibility}" />
|
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelCorrelationId}" />
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Exchange}" Visibility="{Binding ExchangeVisibility}" />
|
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding CorrelationId, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelRoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
<Label Grid.Row="4" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelAssemblyName}" />
|
||||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding RoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding AssemblyName, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelQueue}" Visibility="{Binding QueueVisibility}" />
|
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelClassName}" />
|
||||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Queue}" Visibility="{Binding QueueVisibility}" />
|
<Grid Grid.Row="5" Grid.Column="1">
|
||||||
|
|
||||||
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelProperties}" Style="{StaticResource SectionLabel}"/>
|
|
||||||
|
|
||||||
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelCorrelationId}" />
|
|
||||||
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding CorrelationId}" />
|
|
||||||
|
|
||||||
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelReplyTo}" />
|
|
||||||
<TextBox Grid.Row="7" Grid.Column="1" Text="{Binding ReplyTo}" />
|
|
||||||
|
|
||||||
<Label Grid.Row="10" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelAssemblyName}" />
|
|
||||||
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding AssemblyName, UpdateSourceTrigger=PropertyChanged}" />
|
|
||||||
|
|
||||||
<Label Grid.Row="11" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelClassName}" />
|
|
||||||
<Grid Grid.Row="11" Grid.Column="1">
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBox Grid.Column="0" Text="{Binding ClassName}" GotFocus="CaretToEnd" />
|
<TextBox Grid.Column="0" Text="{Binding ClassName, UpdateSourceTrigger=PropertyChanged}" GotFocus="CaretToEnd" />
|
||||||
<!--
|
<!--
|
||||||
<Button Grid.Column="1" Content="{x:Static publisher:TapetiPublisherViewStrings.ButtonBrowseClass}" />
|
<Button Grid.Column="1" Content="{x:Static publisher:TapetiPublisherViewStrings.ButtonBrowseClass}" />
|
||||||
-->
|
-->
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="12" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelPayload}" />
|
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelPayload}" />
|
||||||
<TextBox Grid.Row="12" Grid.Column="1" Text="{Binding Payload}" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" Height="150" />
|
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding Payload, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource Payload}" Height="150" />
|
||||||
</ui:GridLayout>
|
</ui:GridLayout>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -10,8 +10,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
{
|
{
|
||||||
public TapetiPublisherView(TapetiPublisherViewModel viewModel)
|
public TapetiPublisherView(TapetiPublisherViewModel viewModel)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
if (sender is not TextBox textBox)
|
if (sender is not TextBox textBox)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
textBox.CaretIndex = textBox.Text?.Length ?? 0;
|
textBox.CaretIndex = textBox.Text.Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using IConnection = PettingZoo.Core.Connection.IConnection;
|
using IConnection = PettingZoo.Core.Connection.IConnection;
|
||||||
@ -10,68 +9,15 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
public class TapetiPublisherViewModel : BaseViewModel
|
public class TapetiPublisherViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
private readonly IConnection connection;
|
private readonly IConnection connection;
|
||||||
|
private readonly IPublishDestination publishDestination;
|
||||||
private readonly DelegateCommand publishCommand;
|
private readonly DelegateCommand publishCommand;
|
||||||
|
|
||||||
private bool sendToExchange = true;
|
|
||||||
private string exchange = "";
|
|
||||||
private string routingKey = "";
|
|
||||||
private string queue = "";
|
|
||||||
|
|
||||||
private MessageDeliveryMode deliveryMode;
|
|
||||||
|
|
||||||
private string correlationId = "";
|
private string correlationId = "";
|
||||||
private string replyTo = "";
|
|
||||||
private string payload = "";
|
private string payload = "";
|
||||||
private string className = "";
|
private string className = "";
|
||||||
private string assemblyName = "";
|
private string assemblyName = "";
|
||||||
|
|
||||||
|
|
||||||
public bool SendToExchange
|
|
||||||
{
|
|
||||||
get => sendToExchange;
|
|
||||||
set => SetField(ref sendToExchange, value, otherPropertiesChanged: new[] { nameof(SendToQueue), nameof(ExchangeVisibility), nameof(QueueVisibility) });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public bool SendToQueue
|
|
||||||
{
|
|
||||||
get => !SendToExchange;
|
|
||||||
set => SendToExchange = !value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string Exchange
|
|
||||||
{
|
|
||||||
get => exchange;
|
|
||||||
set => SetField(ref exchange, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string RoutingKey
|
|
||||||
{
|
|
||||||
get => routingKey;
|
|
||||||
set => SetField(ref routingKey, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string Queue
|
|
||||||
{
|
|
||||||
get => queue;
|
|
||||||
set => SetField(ref queue, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public virtual Visibility ExchangeVisibility => SendToExchange ? Visibility.Visible : Visibility.Collapsed;
|
|
||||||
public virtual Visibility QueueVisibility => SendToQueue ? Visibility.Visible : Visibility.Collapsed;
|
|
||||||
|
|
||||||
|
|
||||||
public int DeliveryModeIndex
|
|
||||||
{
|
|
||||||
get => deliveryMode == MessageDeliveryMode.Persistent ? 1 : 0;
|
|
||||||
set => SetField(ref deliveryMode, value == 1 ? MessageDeliveryMode.Persistent : MessageDeliveryMode.NonPersistent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string CorrelationId
|
public string CorrelationId
|
||||||
{
|
{
|
||||||
get => correlationId;
|
get => correlationId;
|
||||||
@ -79,13 +25,6 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public string ReplyTo
|
|
||||||
{
|
|
||||||
get => replyTo;
|
|
||||||
set => SetField(ref replyTo, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string ClassName
|
public string ClassName
|
||||||
{
|
{
|
||||||
get => string.IsNullOrEmpty(className) ? AssemblyName + "." : className;
|
get => string.IsNullOrEmpty(className) ? AssemblyName + "." : className;
|
||||||
@ -142,9 +81,10 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public TapetiPublisherViewModel(IConnection connection, ReceivedMessageInfo? receivedMessage = null)
|
public TapetiPublisherViewModel(IConnection connection, IPublishDestination publishDestination, ReceivedMessageInfo? receivedMessage = null)
|
||||||
{
|
{
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
this.publishDestination = publishDestination;
|
||||||
|
|
||||||
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||||
|
|
||||||
@ -152,14 +92,9 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
if (receivedMessage == null || !IsTapetiMessage(receivedMessage, out var receivedAssemblyName, out var receivedClassName))
|
if (receivedMessage == null || !IsTapetiMessage(receivedMessage, out var receivedAssemblyName, out var receivedClassName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Exchange = receivedMessage.Exchange;
|
|
||||||
RoutingKey = receivedMessage.RoutingKey;
|
|
||||||
|
|
||||||
|
|
||||||
AssemblyName = receivedAssemblyName;
|
AssemblyName = receivedAssemblyName;
|
||||||
ClassName = receivedClassName;
|
ClassName = receivedClassName;
|
||||||
CorrelationId = receivedMessage.Properties.CorrelationId ?? "";
|
CorrelationId = receivedMessage.Properties.CorrelationId ?? "";
|
||||||
ReplyTo = receivedMessage.Properties.ReplyTo ?? "";
|
|
||||||
Payload = Encoding.UTF8.GetString(receivedMessage.Body);
|
Payload = Encoding.UTF8.GetString(receivedMessage.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,12 +106,11 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
return string.IsNullOrEmpty(value) ? null : value;
|
return string.IsNullOrEmpty(value) ? null : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO support for Reply To to dynamic queue which waits for a message (or opens a new subscriber tab?)
|
|
||||||
// TODO background worker / async
|
// TODO background worker / async
|
||||||
|
|
||||||
connection.Publish(new PublishMessageInfo(
|
connection.Publish(new PublishMessageInfo(
|
||||||
SendToExchange ? Exchange : "",
|
publishDestination.Exchange,
|
||||||
SendToExchange ? RoutingKey : Queue,
|
publishDestination.RoutingKey,
|
||||||
Encoding.UTF8.GetBytes(Payload),
|
Encoding.UTF8.GetBytes(Payload),
|
||||||
new MessageProperties(new Dictionary<string, string>
|
new MessageProperties(new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
@ -185,8 +119,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
{
|
{
|
||||||
ContentType = @"application/json",
|
ContentType = @"application/json",
|
||||||
CorrelationId = NullIfEmpty(CorrelationId),
|
CorrelationId = NullIfEmpty(CorrelationId),
|
||||||
DeliveryMode = deliveryMode,
|
DeliveryMode = MessageDeliveryMode.Persistent,
|
||||||
ReplyTo = NullIfEmpty(ReplyTo)
|
ReplyTo = publishDestination.GetReplyTo()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,12 +135,12 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
|
|
||||||
public class DesignTimeTapetiPublisherViewModel : TapetiPublisherViewModel
|
public class DesignTimeTapetiPublisherViewModel : TapetiPublisherViewModel
|
||||||
{
|
{
|
||||||
public DesignTimeTapetiPublisherViewModel() : base(null!)
|
public DesignTimeTapetiPublisherViewModel() : base(null!, null!)
|
||||||
{
|
{
|
||||||
|
AssemblyName = "Messaging.Example";
|
||||||
|
ClassName = "Messaging.Example.ExampleMessage";
|
||||||
|
CorrelationId = "2c702859-bbbc-454e-87e2-4220c8c595d7";
|
||||||
|
Payload = "{\r\n \"Hello\": \"world!\"\r\n}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override Visibility ExchangeVisibility => Visibility.Visible;
|
|
||||||
public override Visibility QueueVisibility => Visibility.Visible;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,15 +123,6 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Exchange.
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelExchange {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelExchange", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Payload.
|
/// Looks up a localized string similar to Payload.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -149,50 +140,5 @@ namespace PettingZoo.UI.Tab.Publisher {
|
|||||||
return ResourceManager.GetString("LabelProperties", resourceCulture);
|
return ResourceManager.GetString("LabelProperties", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Queue.
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelQueue {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelQueue", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Reply To.
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelReplyTo {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelReplyTo", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Routing key.
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelRoutingKey {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelRoutingKey", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Publish to exchange (topic).
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelSendToExchange {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelSendToExchange", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to Publish to queue (direct).
|
|
||||||
/// </summary>
|
|
||||||
public static string LabelSendToQueue {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LabelSendToQueue", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,28 +138,10 @@
|
|||||||
<data name="LabelDeliveryMode" xml:space="preserve">
|
<data name="LabelDeliveryMode" xml:space="preserve">
|
||||||
<value>Delivery mode</value>
|
<value>Delivery mode</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelExchange" xml:space="preserve">
|
|
||||||
<value>Exchange</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelPayload" xml:space="preserve">
|
<data name="LabelPayload" xml:space="preserve">
|
||||||
<value>Payload</value>
|
<value>Payload</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelProperties" xml:space="preserve">
|
<data name="LabelProperties" xml:space="preserve">
|
||||||
<value>Properties</value>
|
<value>Properties</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LabelQueue" xml:space="preserve">
|
|
||||||
<value>Queue</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelReplyTo" xml:space="preserve">
|
|
||||||
<value>Reply To</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelRoutingKey" xml:space="preserve">
|
|
||||||
<value>Routing key</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelSendToExchange" xml:space="preserve">
|
|
||||||
<value>Publish to exchange (topic)</value>
|
|
||||||
</data>
|
|
||||||
<data name="LabelSendToQueue" xml:space="preserve">
|
|
||||||
<value>Publish to queue (direct)</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
@ -10,8 +10,8 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
{
|
{
|
||||||
public SubscriberView(SubscriberViewModel viewModel)
|
public SubscriberView(SubscriberViewModel viewModel)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
|
||||||
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
|
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
|
||||||
|
@ -7,12 +7,11 @@ using System.Windows.Input;
|
|||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using PettingZoo.Core.Rendering;
|
using PettingZoo.Core.Rendering;
|
||||||
|
|
||||||
// TODO update title with unread message count if tab is not active
|
// TODO visual hint of where the last read message was when activating the tab again
|
||||||
// TODO export option (to Tapeti.Cmd compatible format / command-line of course)
|
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Subscriber
|
namespace PettingZoo.UI.Tab.Subscriber
|
||||||
{
|
{
|
||||||
public class SubscriberViewModel : BaseViewModel, ITabToolbarCommands
|
public class SubscriberViewModel : BaseViewModel, ITabToolbarCommands, ITabActivate
|
||||||
{
|
{
|
||||||
private readonly ITabHost tabHost;
|
private readonly ITabHost tabHost;
|
||||||
private readonly ITabFactory tabFactory;
|
private readonly ITabFactory tabFactory;
|
||||||
@ -26,8 +25,13 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
|
|
||||||
private readonly DelegateCommand createPublisherCommand;
|
private readonly DelegateCommand createPublisherCommand;
|
||||||
|
|
||||||
|
private bool tabActive;
|
||||||
|
private int unreadCount;
|
||||||
|
|
||||||
|
|
||||||
public ICommand ClearCommand => clearCommand;
|
public ICommand ClearCommand => clearCommand;
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedMember.Global - it is, but via a proxy
|
||||||
public ICommand CreatePublisherCommand => createPublisherCommand;
|
public ICommand CreatePublisherCommand => createPublisherCommand;
|
||||||
|
|
||||||
public ObservableCollection<ReceivedMessageInfo> Messages { get; }
|
public ObservableCollection<ReceivedMessageInfo> Messages { get; }
|
||||||
@ -53,7 +57,9 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
set => SetField(ref selectedMessageProperties, value);
|
set => SetField(ref selectedMessageProperties, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Title => $"{subscriber.Exchange} - {subscriber.RoutingKey}";
|
public string Title =>
|
||||||
|
(subscriber.Exchange != null ? $"{subscriber.Exchange} - {subscriber.RoutingKey}" : $"{subscriber.QueueName}") +
|
||||||
|
(tabActive || unreadCount == 0 ? "" : $" ({unreadCount})");
|
||||||
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
||||||
|
|
||||||
|
|
||||||
@ -111,6 +117,12 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
{
|
{
|
||||||
RunFromUiScheduler(() =>
|
RunFromUiScheduler(() =>
|
||||||
{
|
{
|
||||||
|
if (!tabActive)
|
||||||
|
{
|
||||||
|
unreadCount++;
|
||||||
|
RaisePropertyChanged(nameof(Title));
|
||||||
|
}
|
||||||
|
|
||||||
Messages.Add(args.MessageInfo);
|
Messages.Add(args.MessageInfo);
|
||||||
clearCommand.RaiseCanExecuteChanged();
|
clearCommand.RaiseCanExecuteChanged();
|
||||||
});
|
});
|
||||||
@ -131,6 +143,20 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
{
|
{
|
||||||
_ = Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
|
_ = Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Activate()
|
||||||
|
{
|
||||||
|
tabActive = true;
|
||||||
|
unreadCount = 0;
|
||||||
|
|
||||||
|
RaisePropertyChanged(nameof(Title));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Deactivate()
|
||||||
|
{
|
||||||
|
tabActive = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -149,6 +175,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string QueueName => "dummy";
|
||||||
public string Exchange => "dummy";
|
public string Exchange => "dummy";
|
||||||
public string RoutingKey => "dummy";
|
public string RoutingKey => "dummy";
|
||||||
|
|
||||||
|
@ -47,5 +47,17 @@ namespace PettingZoo.UI.Tab
|
|||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ToolbarCommands)));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ToolbarCommands)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Activate()
|
||||||
|
{
|
||||||
|
(viewModel as ITabActivate)?.Activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Deactivate()
|
||||||
|
{
|
||||||
|
(viewModel as ITabActivate)?.Deactivate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace PettingZoo.UI.Tab
|
|||||||
|
|
||||||
public ITab CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
public ITab CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||||
{
|
{
|
||||||
var viewModel = new PublisherViewModel(connection, fromReceivedMessage);
|
var viewModel = new PublisherViewModel(tabHost, this, connection, fromReceivedMessage);
|
||||||
return new ViewTab<PublisherView, PublisherViewModel>(
|
return new ViewTab<PublisherView, PublisherViewModel>(
|
||||||
closeTabCommand,
|
closeTabCommand,
|
||||||
new PublisherView(viewModel),
|
new PublisherView(viewModel),
|
||||||
|
Loading…
Reference in New Issue
Block a user