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;
|
||||
|
||||
ISubscriber Subscribe(string exchange, string routingKey);
|
||||
ISubscriber Subscribe();
|
||||
|
||||
Task Publish(PublishMessageInfo messageInfo);
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,9 @@ namespace PettingZoo.Core.Connection
|
||||
{
|
||||
public interface ISubscriber : IAsyncDisposable
|
||||
{
|
||||
string Exchange {get; }
|
||||
string RoutingKey { get; }
|
||||
string? QueueName { get; }
|
||||
string? Exchange {get; }
|
||||
string? RoutingKey { get; }
|
||||
|
||||
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,18 +46,32 @@ namespace PettingZoo.RabbitMQ
|
||||
connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
var subscriber = new RabbitMQClientSubscriber(model, exchange, routingKey);
|
||||
if (model != null)
|
||||
if (model != null)
|
||||
return subscriber;
|
||||
|
||||
|
||||
|
||||
void ConnectSubscriber(object? sender, StatusChangedEventArgs args)
|
||||
{
|
||||
if (args.Status != ConnectionStatus.Connected)
|
||||
@ -67,20 +81,20 @@ namespace PettingZoo.RabbitMQ
|
||||
{
|
||||
if (model == null)
|
||||
return;
|
||||
|
||||
|
||||
subscriber.Connected(model);
|
||||
}
|
||||
|
||||
|
||||
StatusChanged -= ConnectSubscriber;
|
||||
}
|
||||
|
||||
|
||||
|
||||
StatusChanged += ConnectSubscriber;
|
||||
return subscriber;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Task Publish(PublishMessageInfo messageInfo)
|
||||
{
|
||||
if (model == null)
|
||||
|
@ -13,12 +13,13 @@ namespace PettingZoo.RabbitMQ
|
||||
private string? consumerTag;
|
||||
private bool started;
|
||||
|
||||
public string Exchange { get; }
|
||||
public string RoutingKey { get; }
|
||||
public string? QueueName { get; private set; }
|
||||
public string? Exchange { get; }
|
||||
public string? RoutingKey { get; }
|
||||
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
||||
|
||||
|
||||
public RabbitMQClientSubscriber(IModel? model, string exchange, string routingKey)
|
||||
public RabbitMQClientSubscriber(IModel? model, string? exchange, string? routingKey)
|
||||
{
|
||||
this.model = model;
|
||||
Exchange = exchange;
|
||||
@ -28,6 +29,8 @@ namespace PettingZoo.RabbitMQ
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
if (model != null && consumerTag != null && model.IsOpen)
|
||||
model.BasicCancelNoWait(consumerTag);
|
||||
|
||||
@ -41,13 +44,14 @@ namespace PettingZoo.RabbitMQ
|
||||
if (model == null)
|
||||
return;
|
||||
|
||||
var queueName = model.QueueDeclare().QueueName;
|
||||
model.QueueBind(queueName, Exchange, RoutingKey);
|
||||
QueueName = model.QueueDeclare().QueueName;
|
||||
if (Exchange != null && RoutingKey != null)
|
||||
model.QueueBind(QueueName, Exchange, RoutingKey);
|
||||
|
||||
var consumer = new EventingBasicConsumer(model);
|
||||
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
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PettingZoo.RabbitMQ", "PettingZoo.RabbitMQ\PettingZoo.RabbitMQ.csproj", "{220149F3-A8D6-44ED-B3B6-DFE506EB018A}"
|
||||
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
|
||||
Global
|
||||
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}.Release|Any CPU.ActiveCfg = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
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">
|
||||
<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/=WPF/@EntryIndexedValue">WPF</s:String></wpf:ResourceDictionary>
|
@ -39,9 +39,15 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PettingZoo.Core\PettingZoo.Core.csproj" />
|
||||
<ProjectReference Include="..\PettingZoo.RabbitMQ\PettingZoo.RabbitMQ.csproj" />
|
||||
<ProjectReference Include="..\PettingZoo.Settings.LiteDB\PettingZoo.Settings.LiteDB.csproj" />
|
||||
</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">
|
||||
<DependentUpon>ConnectionWindowStrings.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
@ -88,6 +94,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="UI\Connection\ConnectionDisplayNameStrings.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>ConnectionDisplayNameStrings.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="UI\Connection\ConnectionWindowStrings.resx">
|
||||
<LastGenOutput>ConnectionWindowStrings.Designer.cs</LastGenOutput>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
|
@ -1,17 +1,14 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Markup;
|
||||
using Newtonsoft.Json;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Settings;
|
||||
using PettingZoo.RabbitMQ;
|
||||
using PettingZoo.Settings;
|
||||
using PettingZoo.Settings.LiteDB;
|
||||
using PettingZoo.UI.Connection;
|
||||
using PettingZoo.UI.Main;
|
||||
using PettingZoo.UI.Subscribe;
|
||||
using PettingZoo.UI.Tab;
|
||||
using SimpleInjector;
|
||||
|
||||
namespace PettingZoo
|
||||
@ -37,11 +34,10 @@ namespace PettingZoo
|
||||
// See comments in RunApplication
|
||||
container.Options.EnableAutoVerification = false;
|
||||
|
||||
container.RegisterSingleton(() => new UserSettings(new AppDataSettingsSerializer("Settings.json")));
|
||||
|
||||
container.Register<IConnectionFactory, RabbitMQClientConnectionFactory>();
|
||||
container.Register<IConnectionDialog, WindowConnectionDialog>();
|
||||
container.Register<ISubscribeDialog, WindowSubscribeDialog>();
|
||||
container.Register<IConnectionSettingsRepository, LiteDBConnectionSettingsRepository>();
|
||||
|
||||
container.Register<MainWindow>();
|
||||
|
||||
@ -72,50 +68,9 @@ namespace PettingZoo
|
||||
var mainWindow = container.GetInstance<MainWindow>();
|
||||
_ = app.Run(mainWindow);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO Log the exception and exit
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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];
|
||||
MessageBox.Show($"Fatal exception: {e.Message}", @"PettingZoo", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -33,8 +33,12 @@
|
||||
<Style x:Key="FooterButton" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="Margin" Value="8,0,0,0" />
|
||||
</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}">
|
||||
<Setter Property="ChildMargin" Value="4"/>
|
||||
</Style>
|
||||
@ -78,4 +82,11 @@
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
</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>
|
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,
|
||||
params string[]? otherPropertiesChanged)
|
||||
DelegateCommand[]? delegateCommandsChanged = null,
|
||||
string[]? otherPropertiesChanged = null)
|
||||
{
|
||||
if ((comparer ?? EqualityComparer<T>.Default).Equals(field, value))
|
||||
return false;
|
||||
@ -29,12 +24,18 @@ namespace PettingZoo.UI
|
||||
field = value;
|
||||
RaisePropertyChanged(propertyName);
|
||||
|
||||
if (otherPropertiesChanged == null)
|
||||
return true;
|
||||
|
||||
foreach (var otherProperty in otherPropertiesChanged)
|
||||
RaisePropertyChanged(otherProperty);
|
||||
|
||||
if (otherPropertiesChanged != null)
|
||||
{
|
||||
foreach (var otherProperty in otherPropertiesChanged)
|
||||
RaisePropertyChanged(otherProperty);
|
||||
}
|
||||
|
||||
if (delegateCommandsChanged != null)
|
||||
{
|
||||
foreach (var delegateCommand in delegateCommandsChanged)
|
||||
delegateCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
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.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using PettingZoo.Core.Settings;
|
||||
|
||||
// TODO validate input
|
||||
// TODO profiles
|
||||
// TODO "save password" checkbox
|
||||
|
||||
namespace PettingZoo.UI.Connection
|
||||
{
|
||||
public class ConnectionViewModel : BaseViewModel
|
||||
{
|
||||
private string host;
|
||||
private string virtualHost;
|
||||
private readonly IConnectionSettingsRepository connectionSettingsRepository;
|
||||
private readonly ConnectionSettings defaultSettings;
|
||||
private string host = null!;
|
||||
private string virtualHost = null!;
|
||||
private int port;
|
||||
private string username;
|
||||
private string password;
|
||||
private string username = null!;
|
||||
private string password = null!;
|
||||
|
||||
private bool subscribe;
|
||||
private string exchange;
|
||||
private string routingKey;
|
||||
private string exchange = null!;
|
||||
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
|
||||
{
|
||||
get => host;
|
||||
set => SetField(ref host, value);
|
||||
set => SetField(ref host, value, delegateCommandsChanged: connectionChangedCommands);
|
||||
}
|
||||
|
||||
public string VirtualHost
|
||||
{
|
||||
get => virtualHost;
|
||||
set => SetField(ref virtualHost, value);
|
||||
set => SetField(ref virtualHost, value, delegateCommandsChanged: connectionChangedCommands);
|
||||
}
|
||||
|
||||
public int Port
|
||||
{
|
||||
get => port;
|
||||
set => SetField(ref port, value);
|
||||
set => SetField(ref port, value, delegateCommandsChanged: connectionChangedCommands);
|
||||
}
|
||||
|
||||
public string Username
|
||||
{
|
||||
get => username;
|
||||
set => SetField(ref username, value);
|
||||
set => SetField(ref username, value, delegateCommandsChanged: connectionChangedCommands);
|
||||
}
|
||||
|
||||
public string Password
|
||||
@ -53,46 +67,142 @@ namespace PettingZoo.UI.Connection
|
||||
public bool Subscribe
|
||||
{
|
||||
get => subscribe;
|
||||
set => SetField(ref subscribe, value);
|
||||
set => SetField(ref subscribe, value, delegateCommandsChanged: connectionChangedCommands);
|
||||
}
|
||||
|
||||
public string Exchange
|
||||
{
|
||||
get => exchange;
|
||||
set => SetField(ref exchange, value);
|
||||
set
|
||||
{
|
||||
if (SetField(ref exchange, value, delegateCommandsChanged: connectionChangedCommands))
|
||||
AutoToggleSubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
public string 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 ConnectionViewModel(ConnectionDialogParams model)
|
||||
public ConnectionViewModel(IConnectionSettingsRepository connectionSettingsRepository, ConnectionSettings defaultSettings)
|
||||
{
|
||||
OkCommand = new DelegateCommand(OkExecute, OkCanExecute);
|
||||
|
||||
host = model.Host;
|
||||
virtualHost = model.VirtualHost;
|
||||
port = model.Port;
|
||||
username = model.Username;
|
||||
password = model.Password;
|
||||
this.connectionSettingsRepository = connectionSettingsRepository;
|
||||
this.defaultSettings = defaultSettings;
|
||||
|
||||
subscribe = model.Subscribe;
|
||||
exchange = model.Exchange;
|
||||
routingKey = model.RoutingKey;
|
||||
okCommand = new DelegateCommand(OkExecute, OkCanExecute);
|
||||
saveCommand = new DelegateCommand(SaveExecute, SaveCanExecute);
|
||||
saveAsCommand = new DelegateCommand(SaveAsExecute, SaveAsCanExecute);
|
||||
deleteCommand = new DelegateCommand(DeleteExecute, DeleteCanExecute);
|
||||
|
||||
connectionChangedCommands = new[] { saveCommand, saveAsCommand, okCommand };
|
||||
}
|
||||
|
||||
|
||||
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 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"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance connection:DesignTimeConnectionViewModel, IsDesignTimeCreatable = True}"
|
||||
Width="500"
|
||||
Width="700"
|
||||
SizeToContent="Height"
|
||||
ResizeMode="NoResize"
|
||||
WindowStyle="ToolWindow"
|
||||
Style="{StaticResource WindowStyle}"
|
||||
Title="{x:Static connection:ConnectionWindowStrings.WindowTitle}"
|
||||
FocusManager.FocusedElement="{Binding ElementName=HostTextBox}">
|
||||
<DockPanel Margin="8">
|
||||
<UniformGrid DockPanel.Dock="Bottom" HorizontalAlignment="Right" Rows="1" Columns="2" Style="{StaticResource FooterPanel}">
|
||||
FocusManager.FocusedElement="{Binding ElementName=HostTextBox}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<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 IsCancel="True" Content="{x:Static connection:ConnectionWindowStrings.ButtonCancel}" Style="{StaticResource FooterButton}"/>
|
||||
</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>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
@ -37,28 +66,28 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<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}"/>
|
||||
<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}"/>
|
||||
<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}"/>
|
||||
<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}"/>
|
||||
<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}"/>
|
||||
|
||||
<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}"/>
|
||||
<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>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
|
@ -1,13 +1,28 @@
|
||||
using System.Windows;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using PettingZoo.Core.Settings;
|
||||
|
||||
namespace PettingZoo.UI.Connection
|
||||
{
|
||||
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)
|
||||
{
|
||||
Owner = Application.Current.MainWindow
|
||||
@ -17,10 +32,15 @@ namespace PettingZoo.UI.Connection
|
||||
{
|
||||
window.DialogResult = true;
|
||||
};
|
||||
|
||||
|
||||
return window.ShowDialog().GetValueOrDefault()
|
||||
? viewModel.ToModel()
|
||||
: null;
|
||||
if (!window.ShowDialog().GetValueOrDefault())
|
||||
return null;
|
||||
|
||||
var newSettings = viewModel.ToModel();
|
||||
await connectionSettingsRepository.StoreLastUsed(newSettings);
|
||||
|
||||
return newSettings;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,10 +49,8 @@ namespace PettingZoo.UI.Connection
|
||||
{
|
||||
public ConnectionWindow(ConnectionViewModel viewModel)
|
||||
{
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
@ -41,5 +59,14 @@ namespace PettingZoo.UI.Connection
|
||||
if (!char.IsDigit(args.Text, args.Text.Length - 1))
|
||||
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.
|
||||
// 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", "16.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class ConnectionWindowStrings {
|
||||
@ -70,7 +70,16 @@ namespace PettingZoo.UI.Connection {
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public static string ButtonOK {
|
||||
get {
|
||||
@ -79,7 +88,43 @@ namespace PettingZoo.UI.Connection {
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public static string LabelExchange {
|
||||
get {
|
||||
@ -88,7 +133,7 @@ namespace PettingZoo.UI.Connection {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Host:.
|
||||
/// Looks up a localized string similar to Host.
|
||||
/// </summary>
|
||||
public static string LabelHost {
|
||||
get {
|
||||
@ -97,7 +142,7 @@ namespace PettingZoo.UI.Connection {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Password:.
|
||||
/// Looks up a localized string similar to Password.
|
||||
/// </summary>
|
||||
public static string LabelPassword {
|
||||
get {
|
||||
@ -106,7 +151,7 @@ namespace PettingZoo.UI.Connection {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Port:.
|
||||
/// Looks up a localized string similar to Port.
|
||||
/// </summary>
|
||||
public static string LabelPort {
|
||||
get {
|
||||
@ -115,7 +160,7 @@ namespace PettingZoo.UI.Connection {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Routing key:.
|
||||
/// Looks up a localized string similar to Routing key.
|
||||
/// </summary>
|
||||
public static string LabelRoutingKey {
|
||||
get {
|
||||
@ -133,7 +178,7 @@ namespace PettingZoo.UI.Connection {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Username:.
|
||||
/// Looks up a localized string similar to Username.
|
||||
/// </summary>
|
||||
public static string LabelUsername {
|
||||
get {
|
||||
@ -142,7 +187,7 @@ namespace PettingZoo.UI.Connection {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Virtual host:.
|
||||
/// Looks up a localized string similar to Virtual host.
|
||||
/// </summary>
|
||||
public static string LabelVirtualHost {
|
||||
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>
|
||||
/// Looks up a localized string similar to Connection parameters.
|
||||
/// </summary>
|
||||
|
@ -120,32 +120,50 @@
|
||||
<data name="ButtonCancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="ButtonDelete" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
</data>
|
||||
<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 name="LabelExchange" xml:space="preserve">
|
||||
<value>Exchange:</value>
|
||||
<value>Exchange</value>
|
||||
</data>
|
||||
<data name="LabelHost" xml:space="preserve">
|
||||
<value>Host:</value>
|
||||
<value>Host</value>
|
||||
</data>
|
||||
<data name="LabelPassword" xml:space="preserve">
|
||||
<value>Password:</value>
|
||||
<value>Password</value>
|
||||
</data>
|
||||
<data name="LabelPort" xml:space="preserve">
|
||||
<value>Port:</value>
|
||||
<value>Port</value>
|
||||
</data>
|
||||
<data name="LabelRoutingKey" xml:space="preserve">
|
||||
<value>Routing key:</value>
|
||||
<value>Routing key</value>
|
||||
</data>
|
||||
<data name="LabelSubscribe" xml:space="preserve">
|
||||
<value>Subscribe</value>
|
||||
</data>
|
||||
<data name="LabelUsername" xml:space="preserve">
|
||||
<value>Username:</value>
|
||||
<value>Username</value>
|
||||
</data>
|
||||
<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 name="WindowTitle" xml:space="preserve">
|
||||
<value>Connection parameters</value>
|
||||
|
@ -1,43 +1,11 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using PettingZoo.Core.Settings;
|
||||
|
||||
namespace PettingZoo.UI.Connection
|
||||
{
|
||||
public interface IConnectionDialog
|
||||
{
|
||||
ConnectionDialogParams? Show(ConnectionDialogParams? defaultParams = null);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
Task<ConnectionSettings?> Show();
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,11 @@ using System.Windows;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.UI.Connection;
|
||||
using PettingZoo.UI.Subscribe;
|
||||
using PettingZoo.UI.Tab;
|
||||
|
||||
// TODO improve readability of the connection status (especially when connecting/disconnected)
|
||||
|
||||
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
|
||||
public partial class MainWindow
|
||||
{
|
||||
@ -20,9 +18,9 @@ namespace PettingZoo.UI.Main
|
||||
{
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
|
||||
InitializeComponent();
|
||||
viewModel = new MainWindowViewModel(connectionFactory, connectionDialog, subscribeDialog);
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
|
||||
Dispatcher.ShutdownStarted += OnDispatcherShutDownStarted;
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ namespace PettingZoo.UI.Main
|
||||
private readonly ISubscribeDialog subscribeDialog;
|
||||
private readonly ITabFactory tabFactory;
|
||||
|
||||
private ConnectionDialogParams? connectionDialogParams;
|
||||
private SubscribeDialogParams? subscribeDialogParams;
|
||||
private IConnection? connection;
|
||||
private string connectionStatus;
|
||||
@ -44,11 +43,16 @@ namespace PettingZoo.UI.Main
|
||||
public ITab? ActiveTab
|
||||
{
|
||||
get => activeTab;
|
||||
set => SetField(ref activeTab, value, otherPropertiesChanged: new []
|
||||
set
|
||||
{
|
||||
nameof(ToolbarCommands),
|
||||
nameof(ToolbarCommandsSeparatorVisibility)
|
||||
});
|
||||
var currentTab = activeTab;
|
||||
|
||||
if (!SetField(ref activeTab, value, otherPropertiesChanged: new[] { nameof(ToolbarCommands), nameof(ToolbarCommandsSeparatorVisibility) }))
|
||||
return;
|
||||
|
||||
currentTab?.Deactivate();
|
||||
activeTab?.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand ConnectCommand => connectCommand;
|
||||
@ -87,6 +91,8 @@ namespace PettingZoo.UI.Main
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
if (connection != null)
|
||||
await connection.DisposeAsync();
|
||||
}
|
||||
@ -94,28 +100,22 @@ namespace PettingZoo.UI.Main
|
||||
|
||||
private async void ConnectExecute()
|
||||
{
|
||||
var newParams = connectionDialog.Show(connectionDialogParams);
|
||||
|
||||
// TODO support command-line parameters for easier testing
|
||||
// var newParams = new ConnectionDialogParams("localhost", "/", 5672, "guest", "guest", true, "test", "#");
|
||||
|
||||
if (newParams == null)
|
||||
var connectionSettings = await connectionDialog.Show();
|
||||
if (connectionSettings == null)
|
||||
return;
|
||||
|
||||
if (connection != null)
|
||||
await connection.DisposeAsync();
|
||||
|
||||
connectionDialogParams = newParams;
|
||||
connection = connectionFactory.CreateConnection(new ConnectionParams(
|
||||
connectionDialogParams.Host, connectionDialogParams.VirtualHost, connectionDialogParams.Port,
|
||||
connectionDialogParams.Username, connectionDialogParams.Password));
|
||||
connectionSettings.Host, connectionSettings.VirtualHost, connectionSettings.Port,
|
||||
connectionSettings.Username, connectionSettings.Password!));
|
||||
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));
|
||||
|
||||
}
|
||||
|
||||
ConnectionChanged();
|
||||
@ -132,9 +132,7 @@ namespace PettingZoo.UI.Main
|
||||
connection = null;
|
||||
}
|
||||
|
||||
connectionDialogParams = null;
|
||||
ConnectionStatus = GetConnectionStatus(null);
|
||||
|
||||
ConnectionChanged();
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,8 @@ namespace PettingZoo.UI.Subscribe
|
||||
{
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
|
||||
InitializeComponent();
|
||||
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; }
|
||||
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:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:res="clr-namespace:PettingZoo.UI.Tab.Publisher"
|
||||
xmlns:ui="clr-namespace:PettingZoo.UI"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance res:DesignTimePublisherViewModel, IsDesignTimeCreatable=True}"
|
||||
Background="White">
|
||||
<Grid Margin="4">
|
||||
<ui:GridLayout Style="{StaticResource Form}" Margin="4" Grid.IsSharedSizeScope="True">
|
||||
<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="*" />
|
||||
</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.OptionMessageTypeTapeti}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeTapeti}" />
|
||||
</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}" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</ui:GridLayout>
|
||||
</UserControl>
|
||||
|
@ -9,8 +9,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
{
|
||||
public PublisherView(PublisherViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
|
||||
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
|
||||
Background = Brushes.Transparent;
|
||||
|
@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using PettingZoo.Core.Connection;
|
||||
|
||||
// TODO publish button in page instead of just in toolbar
|
||||
|
||||
namespace PettingZoo.UI.Tab.Publisher
|
||||
{
|
||||
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 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 UserControl? messageTypeControl;
|
||||
@ -29,6 +40,66 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
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
|
||||
{
|
||||
get => messageType;
|
||||
@ -70,13 +141,21 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
|
||||
|
||||
// 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";
|
||||
#pragma warning restore CA1822
|
||||
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.tabFactory = tabFactory;
|
||||
this.tabHost = tabHost;
|
||||
|
||||
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||
|
||||
@ -109,7 +188,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
switch (value)
|
||||
{
|
||||
case MessageType.Raw:
|
||||
var rawPublisherViewModel = new RawPublisherViewModel(connection);
|
||||
var rawPublisherViewModel = new RawPublisherViewModel(connection, this);
|
||||
rawPublisherView ??= new RawPublisherView(rawPublisherViewModel);
|
||||
MessageTypeControl = rawPublisherView;
|
||||
|
||||
@ -117,7 +196,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
break;
|
||||
|
||||
case MessageType.Tapeti:
|
||||
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection);
|
||||
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this);
|
||||
tapetiPublisherView ??= new TapetiPublisherView(tapetiPublisherViewModel);
|
||||
MessageTypeControl = tapetiPublisherView;
|
||||
|
||||
@ -134,28 +213,49 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
|
||||
private void SetMessageTypeControl(ReceivedMessageInfo fromReceivedMessage)
|
||||
{
|
||||
Exchange = fromReceivedMessage.Exchange;
|
||||
RoutingKey = fromReceivedMessage.RoutingKey;
|
||||
|
||||
|
||||
if (TapetiPublisherViewModel.IsTapetiMessage(fromReceivedMessage))
|
||||
{
|
||||
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, fromReceivedMessage);
|
||||
var tapetiPublisherViewModel = new TapetiPublisherViewModel(connection, this, fromReceivedMessage);
|
||||
tapetiPublisherView = new TapetiPublisherView(tapetiPublisherViewModel);
|
||||
|
||||
MessageType = MessageType.Tapeti;
|
||||
}
|
||||
else
|
||||
{
|
||||
var rawPublisherViewModel = new RawPublisherViewModel(connection, fromReceivedMessage);
|
||||
var rawPublisherViewModel = new RawPublisherViewModel(connection, this, fromReceivedMessage);
|
||||
rawPublisherView = new RawPublisherView(rawPublisherViewModel);
|
||||
|
||||
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 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>
|
||||
/// Looks up a localized string similar to Message type: .
|
||||
/// </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>
|
||||
/// Looks up a localized string similar to Raw message.
|
||||
/// </summary>
|
||||
|
@ -120,9 +120,33 @@
|
||||
<data name="CommandPublish" xml:space="preserve">
|
||||
<value>Publish</value>
|
||||
</data>
|
||||
<data name="LabelExchange" xml:space="preserve">
|
||||
<value>Exchange</value>
|
||||
</data>
|
||||
<data name="LabelMessageType" xml:space="preserve">
|
||||
<value>Message type: </value>
|
||||
</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">
|
||||
<value>Raw message</value>
|
||||
</data>
|
||||
|
@ -11,17 +11,11 @@
|
||||
Background="White">
|
||||
<ui:GridLayout Style="{StaticResource Form}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<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" />
|
||||
@ -42,31 +36,14 @@
|
||||
</ui:GridLayout.RowDefinitions>
|
||||
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="1">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<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}">
|
||||
<Label Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelDeliveryMode}" />
|
||||
<ComboBox Grid.Column="1" SelectedIndex="{Binding DeliveryModeIndex}">
|
||||
<ComboBoxItem Content="{x:Static publisher:RawPublisherViewStrings.DeliveryModeNonPersistent}" />
|
||||
<ComboBoxItem Content="{x:Static publisher:RawPublisherViewStrings.DeliveryModePersistent}" />
|
||||
</ComboBox>
|
||||
|
||||
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelHeaders}" />
|
||||
<ItemsControl Grid.Row="6" Grid.Column="1" ItemsSource="{Binding Headers}">
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelHeaders}" />
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Headers}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" />
|
||||
@ -116,43 +93,40 @@
|
||||
</ItemsControl.ItemTemplate>
|
||||
</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}" />
|
||||
<TextBox Grid.Row="8" Grid.Column="1" Text="{Binding ContentType}" />
|
||||
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelContentType}" />
|
||||
<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}" />
|
||||
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding CorrelationId}" />
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelCorrelationId}" />
|
||||
<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}" />
|
||||
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding ReplyTo}" />
|
||||
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelAppId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||
<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}" />
|
||||
<TextBox Grid.Row="11" Grid.Column="1" Text="{Binding AppId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelContentEncoding}" 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}" />
|
||||
<TextBox Grid.Row="12" Grid.Column="1" Text="{Binding ContentEncoding}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelExpiration}" 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}" />
|
||||
<TextBox Grid.Row="13" Grid.Column="1" Text="{Binding Expiration}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||
<Label Grid.Row="8" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelMessageId}" 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}" />
|
||||
<TextBox Grid.Row="14" Grid.Column="1" Text="{Binding MessageId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||
<Label Grid.Row="9" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPriority}" 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}" />
|
||||
<TextBox Grid.Row="15" Grid.Column="1" Text="{Binding Priority}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||
<Label Grid.Row="10" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelTimestamp}" 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}" />
|
||||
<TextBox Grid.Row="16" Grid.Column="1" Text="{Binding Timestamp}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||
<Label Grid.Row="11" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelType}" 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}" />
|
||||
<TextBox Grid.Row="17" Grid.Column="1" Text="{Binding TypeProperty}" 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}" />
|
||||
<Label Grid.Row="12" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelUserId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||
<TextBox Grid.Row="12" Grid.Column="1" Text="{Binding UserId, UpdateSourceTrigger=PropertyChanged}" 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>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<ContentPresenter />
|
||||
@ -160,7 +134,7 @@
|
||||
</Button.Template>
|
||||
</Button>
|
||||
|
||||
<Label Grid.Row="21" 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" />
|
||||
<Label Grid.Row="15" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPayload}" />
|
||||
<TextBox Grid.Row="15" Grid.Column="1" Text="{Binding Payload, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource Payload}" Height="150" />
|
||||
</ui:GridLayout>
|
||||
</UserControl>
|
||||
|
@ -13,16 +13,16 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
/// </summary>
|
||||
public partial class RawPublisherView
|
||||
{
|
||||
private RawPublisherViewModel viewModel;
|
||||
private DispatcherTimer checkEmptyHeaderTimer;
|
||||
private readonly RawPublisherViewModel viewModel;
|
||||
private readonly DispatcherTimer checkEmptyHeaderTimer;
|
||||
|
||||
|
||||
public RawPublisherView(RawPublisherViewModel viewModel)
|
||||
{
|
||||
this.viewModel = viewModel;
|
||||
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
|
||||
checkEmptyHeaderTimer = new DispatcherTimer();
|
||||
checkEmptyHeaderTimer.Tick += CheckEmptyHeaderTimerOnTick;
|
||||
|
@ -13,20 +13,15 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
public class RawPublisherViewModel : BaseViewModel
|
||||
{
|
||||
private readonly IConnection connection;
|
||||
private readonly IPublishDestination publishDestination;
|
||||
private readonly DelegateCommand publishCommand;
|
||||
private readonly DelegateCommand propertiesExpandCollapseCommand;
|
||||
private bool propertiesExpanded;
|
||||
|
||||
private bool sendToExchange = true;
|
||||
private string exchange = "";
|
||||
private string routingKey = "";
|
||||
private string queue = "";
|
||||
|
||||
private MessageDeliveryMode deliveryMode;
|
||||
|
||||
private string contentType = "application/json";
|
||||
private string correlationId = "";
|
||||
private string replyTo = "";
|
||||
private string appId = "";
|
||||
private string contentEncoding = "";
|
||||
private string expiration = "";
|
||||
@ -38,44 +33,6 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
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
|
||||
{
|
||||
@ -98,13 +55,6 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
}
|
||||
|
||||
|
||||
public string ReplyTo
|
||||
{
|
||||
get => replyTo;
|
||||
set => SetField(ref replyTo, value);
|
||||
}
|
||||
|
||||
|
||||
public string AppId
|
||||
{
|
||||
get => appId;
|
||||
@ -194,20 +144,17 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
protected Header LastHeader;
|
||||
|
||||
|
||||
public RawPublisherViewModel(IConnection connection, ReceivedMessageInfo? receivedMessage = null)
|
||||
public RawPublisherViewModel(IConnection connection, IPublishDestination publishDestination, ReceivedMessageInfo? receivedMessage = null)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.publishDestination = publishDestination;
|
||||
|
||||
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||
propertiesExpandCollapseCommand = new DelegateCommand(PropertiesExpandCollapseExecute);
|
||||
|
||||
if (receivedMessage != null)
|
||||
{
|
||||
Exchange = receivedMessage.Exchange;
|
||||
RoutingKey = receivedMessage.RoutingKey;
|
||||
|
||||
CorrelationId = receivedMessage.Properties.CorrelationId ?? "";
|
||||
ReplyTo = receivedMessage.Properties.ReplyTo ?? "";
|
||||
Priority = receivedMessage.Properties.Priority?.ToString() ?? "";
|
||||
AppId = receivedMessage.Properties.AppId ?? "";
|
||||
ContentEncoding = receivedMessage.Properties.ContentEncoding ?? "";
|
||||
@ -270,15 +217,14 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// TODO background worker / async
|
||||
|
||||
connection.Publish(new PublishMessageInfo(
|
||||
SendToExchange ? Exchange : "",
|
||||
SendToExchange ? RoutingKey : Queue,
|
||||
publishDestination.Exchange,
|
||||
publishDestination.RoutingKey,
|
||||
Encoding.UTF8.GetBytes(Payload),
|
||||
new MessageProperties(headers)
|
||||
{
|
||||
@ -290,7 +236,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
Expiration = NullIfEmpty(Expiration),
|
||||
MessageId = NullIfEmpty(MessageId),
|
||||
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,
|
||||
Type = NullIfEmpty(TypeProperty),
|
||||
UserId = NullIfEmpty(UserId)
|
||||
@ -341,7 +287,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
|
||||
public class DesignTimeRawPublisherViewModel : RawPublisherViewModel
|
||||
{
|
||||
public DesignTimeRawPublisherViewModel() : base(null!)
|
||||
public DesignTimeRawPublisherViewModel() : base(null!, null!)
|
||||
{
|
||||
PropertiesExpanded = true;
|
||||
|
||||
@ -349,9 +295,5 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
capturedLastHeader.Key = "Example";
|
||||
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>
|
||||
/// Looks up a localized string similar to Expiration.
|
||||
/// </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>
|
||||
/// Looks up a localized string similar to Timestamp.
|
||||
/// </summary>
|
||||
|
@ -144,9 +144,6 @@
|
||||
<data name="LabelDeliveryMode" xml:space="preserve">
|
||||
<value>Delivery mode</value>
|
||||
</data>
|
||||
<data name="LabelExchange" xml:space="preserve">
|
||||
<value>Exchange</value>
|
||||
</data>
|
||||
<data name="LabelExpiration" xml:space="preserve">
|
||||
<value>Expiration</value>
|
||||
</data>
|
||||
@ -165,21 +162,6 @@
|
||||
<data name="LabelProperties" xml:space="preserve">
|
||||
<value>Properties</value>
|
||||
</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">
|
||||
<value>Timestamp</value>
|
||||
</data>
|
||||
|
@ -11,17 +11,11 @@
|
||||
Background="White">
|
||||
<ui:GridLayout Style="{StaticResource Form}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<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" />
|
||||
@ -32,47 +26,28 @@
|
||||
</ui:GridLayout.RowDefinitions>
|
||||
|
||||
|
||||
<Label Grid.Row="0" Grid.Column="1">
|
||||
<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.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelProperties}" Style="{StaticResource SectionLabel}"/>
|
||||
|
||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelExchange}" Visibility="{Binding ExchangeVisibility}" />
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Exchange}" 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 CorrelationId, UpdateSourceTrigger=PropertyChanged}" />
|
||||
|
||||
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelRoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding RoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
||||
<Label Grid.Row="4" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelAssemblyName}" />
|
||||
<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}" />
|
||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Queue}" Visibility="{Binding QueueVisibility}" />
|
||||
|
||||
<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">
|
||||
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelClassName}" />
|
||||
<Grid Grid.Row="5" Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</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}" />
|
||||
-->
|
||||
</Grid>
|
||||
|
||||
<Label Grid.Row="12" 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" />
|
||||
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:TapetiPublisherViewStrings.LabelPayload}" />
|
||||
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding Payload, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource Payload}" Height="150" />
|
||||
</ui:GridLayout>
|
||||
</UserControl>
|
||||
|
@ -10,8 +10,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
{
|
||||
public TapetiPublisherView(TapetiPublisherViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
if (sender is not TextBox textBox)
|
||||
return;
|
||||
|
||||
textBox.CaretIndex = textBox.Text?.Length ?? 0;
|
||||
textBox.CaretIndex = textBox.Text.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using PettingZoo.Core.Connection;
|
||||
using IConnection = PettingZoo.Core.Connection.IConnection;
|
||||
@ -10,68 +9,15 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
public class TapetiPublisherViewModel : BaseViewModel
|
||||
{
|
||||
private readonly IConnection connection;
|
||||
private readonly IPublishDestination publishDestination;
|
||||
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 replyTo = "";
|
||||
private string payload = "";
|
||||
private string className = "";
|
||||
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
|
||||
{
|
||||
get => correlationId;
|
||||
@ -79,13 +25,6 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
}
|
||||
|
||||
|
||||
public string ReplyTo
|
||||
{
|
||||
get => replyTo;
|
||||
set => SetField(ref replyTo, value);
|
||||
}
|
||||
|
||||
|
||||
public string 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.publishDestination = publishDestination;
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
Exchange = receivedMessage.Exchange;
|
||||
RoutingKey = receivedMessage.RoutingKey;
|
||||
|
||||
|
||||
AssemblyName = receivedAssemblyName;
|
||||
ClassName = receivedClassName;
|
||||
CorrelationId = receivedMessage.Properties.CorrelationId ?? "";
|
||||
ReplyTo = receivedMessage.Properties.ReplyTo ?? "";
|
||||
Payload = Encoding.UTF8.GetString(receivedMessage.Body);
|
||||
}
|
||||
|
||||
@ -171,12 +106,11 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
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
|
||||
|
||||
connection.Publish(new PublishMessageInfo(
|
||||
SendToExchange ? Exchange : "",
|
||||
SendToExchange ? RoutingKey : Queue,
|
||||
publishDestination.Exchange,
|
||||
publishDestination.RoutingKey,
|
||||
Encoding.UTF8.GetBytes(Payload),
|
||||
new MessageProperties(new Dictionary<string, string>
|
||||
{
|
||||
@ -185,8 +119,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
{
|
||||
ContentType = @"application/json",
|
||||
CorrelationId = NullIfEmpty(CorrelationId),
|
||||
DeliveryMode = deliveryMode,
|
||||
ReplyTo = NullIfEmpty(ReplyTo)
|
||||
DeliveryMode = MessageDeliveryMode.Persistent,
|
||||
ReplyTo = publishDestination.GetReplyTo()
|
||||
}));
|
||||
}
|
||||
|
||||
@ -201,12 +135,12 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
|
||||
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>
|
||||
/// Looks up a localized string similar to Payload.
|
||||
/// </summary>
|
||||
@ -149,50 +140,5 @@ namespace PettingZoo.UI.Tab.Publisher {
|
||||
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">
|
||||
<value>Delivery mode</value>
|
||||
</data>
|
||||
<data name="LabelExchange" xml:space="preserve">
|
||||
<value>Exchange</value>
|
||||
</data>
|
||||
<data name="LabelPayload" xml:space="preserve">
|
||||
<value>Payload</value>
|
||||
</data>
|
||||
<data name="LabelProperties" xml:space="preserve">
|
||||
<value>Properties</value>
|
||||
</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>
|
@ -10,8 +10,8 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
{
|
||||
public SubscriberView(SubscriberViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
|
||||
|
||||
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
|
||||
|
@ -7,12 +7,11 @@ using System.Windows.Input;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Rendering;
|
||||
|
||||
// TODO update title with unread message count if tab is not active
|
||||
// TODO export option (to Tapeti.Cmd compatible format / command-line of course)
|
||||
// TODO visual hint of where the last read message was when activating the tab again
|
||||
|
||||
namespace PettingZoo.UI.Tab.Subscriber
|
||||
{
|
||||
public class SubscriberViewModel : BaseViewModel, ITabToolbarCommands
|
||||
public class SubscriberViewModel : BaseViewModel, ITabToolbarCommands, ITabActivate
|
||||
{
|
||||
private readonly ITabHost tabHost;
|
||||
private readonly ITabFactory tabFactory;
|
||||
@ -26,8 +25,13 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
|
||||
private readonly DelegateCommand createPublisherCommand;
|
||||
|
||||
private bool tabActive;
|
||||
private int unreadCount;
|
||||
|
||||
|
||||
public ICommand ClearCommand => clearCommand;
|
||||
|
||||
// ReSharper disable once UnusedMember.Global - it is, but via a proxy
|
||||
public ICommand CreatePublisherCommand => createPublisherCommand;
|
||||
|
||||
public ObservableCollection<ReceivedMessageInfo> Messages { get; }
|
||||
@ -53,7 +57,9 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
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;
|
||||
|
||||
|
||||
@ -111,6 +117,12 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
{
|
||||
RunFromUiScheduler(() =>
|
||||
{
|
||||
if (!tabActive)
|
||||
{
|
||||
unreadCount++;
|
||||
RaisePropertyChanged(nameof(Title));
|
||||
}
|
||||
|
||||
Messages.Add(args.MessageInfo);
|
||||
clearCommand.RaiseCanExecuteChanged();
|
||||
});
|
||||
@ -131,6 +143,20 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
{
|
||||
_ = 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 RoutingKey => "dummy";
|
||||
|
||||
|
@ -47,5 +47,17 @@ namespace PettingZoo.UI.Tab
|
||||
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)
|
||||
{
|
||||
var viewModel = new PublisherViewModel(connection, fromReceivedMessage);
|
||||
var viewModel = new PublisherViewModel(tabHost, this, connection, fromReceivedMessage);
|
||||
return new ViewTab<PublisherView, PublisherViewModel>(
|
||||
closeTabCommand,
|
||||
new PublisherView(viewModel),
|
||||
|
Loading…
Reference in New Issue
Block a user