Implemented tab reordering
Implemented tab undocking / docking
This commit is contained in:
parent
2e6524f3b9
commit
c9636aff04
50
PettingZoo/Images/Dock.svg
Normal file
50
PettingZoo/Images/Dock.svg
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<rect y="16" style="fill:#ECF0F1;" width="50" height="35"/>
|
||||||
|
<rect y="2" style="fill:#546A79;" width="50" height="14"/>
|
||||||
|
<circle style="fill:#ED7161;" cx="7" cy="9" r="3"/>
|
||||||
|
<circle style="fill:#EFC41A;" cx="16" cy="9" r="3"/>
|
||||||
|
<circle style="fill:#4FBA6E;" cx="25" cy="9" r="3"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect x="36" y="34" style="fill:#48A0DC;" width="22" height="22"/>
|
||||||
|
<rect x="46" y="40" style="fill:#FFFFFF;" width="2" height="16"/>
|
||||||
|
<polygon style="fill:#FFFFFF;" points="52.293,46.707 47,41.414 41.707,46.707 40.293,45.293 47,38.586 53.707,45.293 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
50
PettingZoo/Images/Undock.svg
Normal file
50
PettingZoo/Images/Undock.svg
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 58 58" style="enable-background:new 0 0 58 58;" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<rect y="16" style="fill:#ECF0F1;" width="50" height="35"/>
|
||||||
|
<rect y="2" style="fill:#546A79;" width="50" height="14"/>
|
||||||
|
<circle style="fill:#ED7161;" cx="7" cy="9" r="3"/>
|
||||||
|
<circle style="fill:#EFC41A;" cx="16" cy="9" r="3"/>
|
||||||
|
<circle style="fill:#4FBA6E;" cx="25" cy="9" r="3"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<rect x="36" y="34" style="fill:#21AE5E;" width="22" height="22"/>
|
||||||
|
<rect x="46" y="35.586" style="fill:#FFFFFF;" width="2" height="16"/>
|
||||||
|
<polygon style="fill:#FFFFFF;" points="47,53 40,46.293 41.476,44.879 47,50.172 52.524,44.879 54,46.293 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -18,13 +18,16 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Remove="Images\Dock.svg" />
|
||||||
<None Remove="Images\PublishSend.svg" />
|
<None Remove="Images\PublishSend.svg" />
|
||||||
|
<None Remove="Images\Undock.svg" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Resource Include="Images\Clear.svg" />
|
<Resource Include="Images\Clear.svg" />
|
||||||
<Resource Include="Images\Connect.svg" />
|
<Resource Include="Images\Connect.svg" />
|
||||||
<Resource Include="Images\Disconnect.svg" />
|
<Resource Include="Images\Disconnect.svg" />
|
||||||
|
<Resource Include="Images\Dock.svg" />
|
||||||
<Resource Include="Images\Publish.svg" />
|
<Resource Include="Images\Publish.svg" />
|
||||||
<Resource Include="Images\PublishSend.svg" />
|
<Resource Include="Images\PublishSend.svg" />
|
||||||
<Resource Include="Images\Subscribe.svg" />
|
<Resource Include="Images\Subscribe.svg" />
|
||||||
@ -42,6 +45,10 @@
|
|||||||
<ProjectReference Include="..\PettingZoo.Settings.LiteDB\PettingZoo.Settings.LiteDB.csproj" />
|
<ProjectReference Include="..\PettingZoo.Settings.LiteDB\PettingZoo.Settings.LiteDB.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Images\Undock.svg" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="UI\Connection\ConnectionDisplayNameStrings.Designer.cs">
|
<Compile Update="UI\Connection\ConnectionDisplayNameStrings.Designer.cs">
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
@ -91,6 +98,11 @@
|
|||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="UI\Tab\Undocked\UndockedTabHostStrings.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>UndockedTabHostStrings.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -130,6 +142,10 @@
|
|||||||
<LastGenOutput>SubscriberViewStrings.Designer.cs</LastGenOutput>
|
<LastGenOutput>SubscriberViewStrings.Designer.cs</LastGenOutput>
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Update="UI\Tab\Undocked\UndockedTabHostStrings.resx">
|
||||||
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>UndockedTabHostStrings.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
Must-have
|
Must-have
|
||||||
---------
|
---------
|
||||||
|
- Option to not save password in profiles
|
||||||
|
|
||||||
|
|
||||||
Should-have
|
Should-have
|
||||||
-----------
|
-----------
|
||||||
- Support undocking tabs (and redocking afterwards)
|
|
||||||
- Allow tab reordering
|
|
||||||
- Save / load publisher messages (either as templates or to disk)
|
- Save / load publisher messages (either as templates or to disk)
|
||||||
- Export received messages to Tapeti JSON file / Tapeti.Cmd command-line
|
- Export received messages to Tapeti JSON file / Tapeti.Cmd command-line
|
||||||
|
|
||||||
|
@ -235,7 +235,6 @@ namespace PettingZoo.UI.Connection
|
|||||||
|
|
||||||
private bool SaveCanExecute()
|
private bool SaveCanExecute()
|
||||||
{
|
{
|
||||||
// TODO check changes in parameters (excluding password)
|
|
||||||
return SelectedStoredConnection != null &&
|
return SelectedStoredConnection != null &&
|
||||||
SelectedStoredConnection.Id != Guid.Empty &&
|
SelectedStoredConnection.Id != Guid.Empty &&
|
||||||
ValidConnection(false) &&
|
ValidConnection(false) &&
|
||||||
|
8
PettingZoo/UI/Main/ITabContainer.cs
Normal file
8
PettingZoo/UI/Main/ITabContainer.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace PettingZoo.UI.Main
|
||||||
|
{
|
||||||
|
public interface ITabContainer
|
||||||
|
{
|
||||||
|
public double TabWidth { get; }
|
||||||
|
public double TabHeight { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@
|
|||||||
xmlns:main="clr-namespace:PettingZoo.UI.Main"
|
xmlns:main="clr-namespace:PettingZoo.UI.Main"
|
||||||
xmlns:tab="clr-namespace:PettingZoo.UI.Tab"
|
xmlns:tab="clr-namespace:PettingZoo.UI.Tab"
|
||||||
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
|
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
|
||||||
|
xmlns:ui="clr-namespace:PettingZoo.UI"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DataContext="{d:DesignInstance main:DesignTimeMainWindowViewModel, IsDesignTimeCreatable=True}"
|
d:DataContext="{d:DesignInstance main:DesignTimeMainWindowViewModel, IsDesignTimeCreatable=True}"
|
||||||
Width="800"
|
Width="800"
|
||||||
@ -17,7 +18,11 @@
|
|||||||
Closed="MainWindow_OnClosed">
|
Closed="MainWindow_OnClosed">
|
||||||
<Window.InputBindings>
|
<Window.InputBindings>
|
||||||
<KeyBinding Modifiers="Control" Key="W" Command="{Binding CloseTabCommand}" />
|
<KeyBinding Modifiers="Control" Key="W" Command="{Binding CloseTabCommand}" />
|
||||||
|
<KeyBinding Modifiers="Control" Key="U" Command="{Binding UndockTabCommand}" />
|
||||||
</Window.InputBindings>
|
</Window.InputBindings>
|
||||||
|
<Window.Resources>
|
||||||
|
<ui:BindingProxy x:Key="ContextMenuProxy" Data="{Binding}" />
|
||||||
|
</Window.Resources>
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<ToolBar DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
|
<ToolBar DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
|
||||||
<Button Command="{Binding ConnectCommand}">
|
<Button Command="{Binding ConnectCommand}">
|
||||||
@ -45,6 +50,12 @@
|
|||||||
<TextBlock Margin="3,0,0,0" Text="{x:Static main:MainWindowStrings.CommandPublish}" />
|
<TextBlock Margin="3,0,0,0" Text="{x:Static main:MainWindowStrings.CommandPublish}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button Command="{Binding UndockTabCommand}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="{svgc:SvgImage Source=/Images/Undock.svg, AppName=PettingZoo}" Width="16" Height="16" Style="{StaticResource ToolbarIcon}"/>
|
||||||
|
<TextBlock Margin="3,0,0,0" Text="{x:Static main:MainWindowStrings.CommandUndock}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Visibility="{Binding ToolbarCommandsSeparatorVisibility}" />
|
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Visibility="{Binding ToolbarCommandsSeparatorVisibility}" />
|
||||||
<ItemsControl ItemsSource="{Binding ToolbarCommands}">
|
<ItemsControl ItemsSource="{Binding ToolbarCommands}">
|
||||||
@ -70,28 +81,39 @@
|
|||||||
<TextBlock Text="{Binding ConnectionStatus}"/>
|
<TextBlock Text="{Binding ConnectionStatus}"/>
|
||||||
</StatusBarItem>
|
</StatusBarItem>
|
||||||
</StatusBar>
|
</StatusBar>
|
||||||
<TabControl
|
<Grid>
|
||||||
|
<TabControl
|
||||||
Name="SubscriberTabs"
|
Name="SubscriberTabs"
|
||||||
ItemsSource="{Binding Tabs}"
|
ItemsSource="{Binding Tabs}"
|
||||||
SelectedValue="{Binding ActiveTab}">
|
SelectedValue="{Binding ActiveTab}">
|
||||||
<TabControl.ItemContainerStyle>
|
<TabControl.ItemContainerStyle>
|
||||||
<Style TargetType="{x:Type TabItem}">
|
<Style TargetType="{x:Type TabItem}">
|
||||||
<Setter Property="Header" Value="{Binding Title}" />
|
<!-- ReSharper disable once Xaml.BindingWithContextNotResolved - valid property for ITab, not sure how to specify the DataContext here so just ignore the warning for now -->
|
||||||
<Setter Property="ContextMenu">
|
<Setter Property="Header" Value="{Binding Title}" />
|
||||||
<Setter.Value>
|
<Setter Property="AllowDrop" Value="True" />
|
||||||
<ContextMenu>
|
<Setter Property="ContextMenu">
|
||||||
<MenuItem Header="{x:Static main:MainWindowStrings.ContextMenuCloseTab}" Command="{Binding CloseTabCommand}" InputGestureText="Ctrl+W" />
|
<Setter.Value>
|
||||||
</ContextMenu>
|
<ContextMenu>
|
||||||
</Setter.Value>
|
<!-- ReSharper disable Xaml.BindingWithContextNotResolved - binding is correct, just weird because of the required proxy -->
|
||||||
</Setter>
|
<MenuItem Header="{x:Static main:MainWindowStrings.ContextMenuUndockTab}" Command="{Binding Data.UndockTabCommand, Source={StaticResource ContextMenuProxy}}" InputGestureText="Ctrl+U" />
|
||||||
</Style>
|
<MenuItem Header="{x:Static main:MainWindowStrings.ContextMenuCloseTab}" Command="{Binding Data.CloseTabCommand, Source={StaticResource ContextMenuProxy}}" InputGestureText="Ctrl+W" />
|
||||||
</TabControl.ItemContainerStyle>
|
<!-- ReSharper restore Xaml.BindingWithContextNotResolved -->
|
||||||
<TabControl.ContentTemplate>
|
</ContextMenu>
|
||||||
<DataTemplate DataType="{x:Type tab:ITab}">
|
</Setter.Value>
|
||||||
<ContentControl Content="{Binding Content}" />
|
</Setter>
|
||||||
</DataTemplate>
|
<EventSetter Event="PreviewMouseRightButtonDown" Handler="TabItem_PreviewRightMouseDown" />
|
||||||
|
<EventSetter Event="PreviewMouseMove" Handler="TabItem_PreviewMouseMove" />
|
||||||
|
<EventSetter Event="Drop" Handler="TabItem_Drop" />
|
||||||
|
</Style>
|
||||||
|
</TabControl.ItemContainerStyle>
|
||||||
|
<TabControl.ContentTemplate>
|
||||||
|
<DataTemplate DataType="{x:Type tab:ITab}">
|
||||||
|
<ContentControl Content="{Binding Content}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</TabControl.ContentTemplate>
|
||||||
|
</TabControl>
|
||||||
|
|
||||||
</TabControl.ContentTemplate>
|
<TextBlock Text="{x:Static main:MainWindowStrings.TabsEmptyText}" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding NoTabsVisibility}" />
|
||||||
</TabControl>
|
</Grid>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Window>
|
</Window>
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using PettingZoo.UI.Connection;
|
using PettingZoo.UI.Connection;
|
||||||
using PettingZoo.UI.Subscribe;
|
using PettingZoo.UI.Subscribe;
|
||||||
|
using PettingZoo.UI.Tab;
|
||||||
|
|
||||||
// TODO improve readability of the connection status (especially when connecting/disconnected)
|
// TODO improve readability of the connection status (especially when connecting/disconnected)
|
||||||
|
|
||||||
namespace PettingZoo.UI.Main
|
namespace PettingZoo.UI.Main
|
||||||
{
|
{
|
||||||
#pragma warning disable CA1001 // MainWindow can't be IDisposable, handled instead in OnDispatcherShutDownStarted
|
#pragma warning disable CA1001 // MainWindow can't be IDisposable, handled instead in OnDispatcherShutDownStarted
|
||||||
public partial class MainWindow
|
public partial class MainWindow : ITabContainer
|
||||||
{
|
{
|
||||||
private readonly MainWindowViewModel viewModel;
|
private readonly MainWindowViewModel viewModel;
|
||||||
|
|
||||||
@ -18,7 +23,7 @@ namespace PettingZoo.UI.Main
|
|||||||
{
|
{
|
||||||
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||||
|
|
||||||
viewModel = new MainWindowViewModel(connectionFactory, connectionDialog, subscribeDialog);
|
viewModel = new MainWindowViewModel(connectionFactory, connectionDialog, subscribeDialog, this);
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
@ -43,6 +48,74 @@ namespace PettingZoo.UI.Main
|
|||||||
{
|
{
|
||||||
var _ = Application.Current.Windows;
|
var _ = Application.Current.Windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void TabItem_PreviewRightMouseDown(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
var tabItem = GetParent<TabItem>(e.OriginalSource);
|
||||||
|
if (tabItem == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var tabControl = GetParent<TabControl>(tabItem);
|
||||||
|
if (tabControl == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tabControl.SelectedItem = tabItem.DataContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void TabItem_PreviewMouseMove(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Source is not TabItem tabItem)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Mouse.PrimaryDevice.LeftButton == MouseButtonState.Pressed)
|
||||||
|
DragDrop.DoDragDrop(tabItem, tabItem, DragDropEffects.All);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void TabItem_Drop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
var targetTab = GetParent<TabItem>(e.OriginalSource);
|
||||||
|
if (targetTab == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sourceTab = (TabItem?)e.Data.GetData(typeof(TabItem));
|
||||||
|
if (sourceTab == null || sourceTab == targetTab)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var tabControl = GetParent<TabControl>(targetTab);
|
||||||
|
if (tabControl?.ItemsSource is not ObservableCollection<ITab> dataCollection)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sourceTab.DataContext is not ITab sourceData || targetTab.DataContext is not ITab targetData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sourceIndex = dataCollection.IndexOf(sourceData);
|
||||||
|
var targetIndex = dataCollection.IndexOf(targetData);
|
||||||
|
|
||||||
|
dataCollection.Move(sourceIndex, targetIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static T? GetParent<T>(object originalSource) where T : DependencyObject
|
||||||
|
{
|
||||||
|
var current = originalSource as DependencyObject;
|
||||||
|
|
||||||
|
while (current != null)
|
||||||
|
{
|
||||||
|
if (current is T targetType)
|
||||||
|
return targetType;
|
||||||
|
|
||||||
|
current = VisualTreeHelper.GetParent(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public double TabWidth => SubscriberTabs.ActualWidth;
|
||||||
|
public double TabHeight => SubscriberTabs.ActualHeight;
|
||||||
}
|
}
|
||||||
#pragma warning restore CA1001
|
#pragma warning restore CA1001
|
||||||
}
|
}
|
||||||
|
29
PettingZoo/UI/Main/MainWindowStrings.Designer.cs
generated
29
PettingZoo/UI/Main/MainWindowStrings.Designer.cs
generated
@ -19,7 +19,7 @@ namespace PettingZoo.UI.Main {
|
|||||||
// class via a tool like ResGen or Visual Studio.
|
// class via a tool like ResGen or Visual Studio.
|
||||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
// with the /str option, or rebuild your VS project.
|
// with the /str option, or rebuild your VS project.
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
public class MainWindowStrings {
|
public class MainWindowStrings {
|
||||||
@ -96,6 +96,15 @@ namespace PettingZoo.UI.Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Undock tab.
|
||||||
|
/// </summary>
|
||||||
|
public static string CommandUndock {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("CommandUndock", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Close tab.
|
/// Looks up a localized string similar to Close tab.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -105,6 +114,15 @@ namespace PettingZoo.UI.Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Undock.
|
||||||
|
/// </summary>
|
||||||
|
public static string ContextMenuUndockTab {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContextMenuUndockTab", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Non-persistent.
|
/// Looks up a localized string similar to Non-persistent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -159,6 +177,15 @@ namespace PettingZoo.UI.Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to No open tabs. Click on New Publisher or New Subscriber to open a new tab..
|
||||||
|
/// </summary>
|
||||||
|
public static string TabsEmptyText {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TabsEmptyText", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Petting Zoo - a RabbitMQ live message viewer.
|
/// Looks up a localized string similar to Petting Zoo - a RabbitMQ live message viewer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -129,9 +129,15 @@
|
|||||||
<data name="CommandSubscribe" xml:space="preserve">
|
<data name="CommandSubscribe" xml:space="preserve">
|
||||||
<value>New Subscriber...</value>
|
<value>New Subscriber...</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="CommandUndock" xml:space="preserve">
|
||||||
|
<value>Undock tab</value>
|
||||||
|
</data>
|
||||||
<data name="ContextMenuCloseTab" xml:space="preserve">
|
<data name="ContextMenuCloseTab" xml:space="preserve">
|
||||||
<value>Close tab</value>
|
<value>Close tab</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ContextMenuUndockTab" xml:space="preserve">
|
||||||
|
<value>Undock</value>
|
||||||
|
</data>
|
||||||
<data name="DeliveryModeNonPersistent" xml:space="preserve">
|
<data name="DeliveryModeNonPersistent" xml:space="preserve">
|
||||||
<value>Non-persistent</value>
|
<value>Non-persistent</value>
|
||||||
</data>
|
</data>
|
||||||
@ -150,6 +156,9 @@
|
|||||||
<data name="StatusError" xml:space="preserve">
|
<data name="StatusError" xml:space="preserve">
|
||||||
<value>Error: {0}</value>
|
<value>Error: {0}</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TabsEmptyText" xml:space="preserve">
|
||||||
|
<value>No open tabs. Click on New Publisher or New Subscriber to open a new tab.</value>
|
||||||
|
</data>
|
||||||
<data name="WindowTitle" xml:space="preserve">
|
<data name="WindowTitle" xml:space="preserve">
|
||||||
<value>Petting Zoo - a RabbitMQ live message viewer</value>
|
<value>Petting Zoo - a RabbitMQ live message viewer</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -9,6 +9,7 @@ using PettingZoo.Core.Connection;
|
|||||||
using PettingZoo.UI.Connection;
|
using PettingZoo.UI.Connection;
|
||||||
using PettingZoo.UI.Subscribe;
|
using PettingZoo.UI.Subscribe;
|
||||||
using PettingZoo.UI.Tab;
|
using PettingZoo.UI.Tab;
|
||||||
|
using PettingZoo.UI.Tab.Undocked;
|
||||||
|
|
||||||
namespace PettingZoo.UI.Main
|
namespace PettingZoo.UI.Main
|
||||||
{
|
{
|
||||||
@ -17,18 +18,21 @@ namespace PettingZoo.UI.Main
|
|||||||
private readonly IConnectionFactory connectionFactory;
|
private readonly IConnectionFactory connectionFactory;
|
||||||
private readonly IConnectionDialog connectionDialog;
|
private readonly IConnectionDialog connectionDialog;
|
||||||
private readonly ISubscribeDialog subscribeDialog;
|
private readonly ISubscribeDialog subscribeDialog;
|
||||||
|
private readonly ITabContainer tabContainer;
|
||||||
private readonly ITabFactory tabFactory;
|
private readonly ITabFactory tabFactory;
|
||||||
|
|
||||||
private SubscribeDialogParams? subscribeDialogParams;
|
private SubscribeDialogParams? subscribeDialogParams;
|
||||||
private IConnection? connection;
|
private IConnection? connection;
|
||||||
private string connectionStatus;
|
private string connectionStatus;
|
||||||
private ITab? activeTab;
|
private ITab? activeTab;
|
||||||
|
private readonly Dictionary<ITab, Window> undockedTabs = new();
|
||||||
|
|
||||||
private readonly DelegateCommand connectCommand;
|
private readonly DelegateCommand connectCommand;
|
||||||
private readonly DelegateCommand disconnectCommand;
|
private readonly DelegateCommand disconnectCommand;
|
||||||
private readonly DelegateCommand publishCommand;
|
private readonly DelegateCommand publishCommand;
|
||||||
private readonly DelegateCommand subscribeCommand;
|
private readonly DelegateCommand subscribeCommand;
|
||||||
private readonly DelegateCommand closeTabCommand;
|
private readonly DelegateCommand closeTabCommand;
|
||||||
|
private readonly DelegateCommand undockTabCommand;
|
||||||
|
|
||||||
|
|
||||||
public string ConnectionStatus
|
public string ConnectionStatus
|
||||||
@ -60,6 +64,7 @@ namespace PettingZoo.UI.Main
|
|||||||
public ICommand PublishCommand => publishCommand;
|
public ICommand PublishCommand => publishCommand;
|
||||||
public ICommand SubscribeCommand => subscribeCommand;
|
public ICommand SubscribeCommand => subscribeCommand;
|
||||||
public ICommand CloseTabCommand => closeTabCommand;
|
public ICommand CloseTabCommand => closeTabCommand;
|
||||||
|
public ICommand UndockTabCommand => undockTabCommand;
|
||||||
|
|
||||||
public IEnumerable<TabToolbarCommand> ToolbarCommands => ActiveTab is ITabToolbarCommands tabToolbarCommands
|
public IEnumerable<TabToolbarCommand> ToolbarCommands => ActiveTab is ITabToolbarCommands tabToolbarCommands
|
||||||
? tabToolbarCommands.ToolbarCommands
|
? tabToolbarCommands.ToolbarCommands
|
||||||
@ -68,13 +73,17 @@ namespace PettingZoo.UI.Main
|
|||||||
public Visibility ToolbarCommandsSeparatorVisibility =>
|
public Visibility ToolbarCommandsSeparatorVisibility =>
|
||||||
ToolbarCommands.Any() ? Visibility.Visible : Visibility.Collapsed;
|
ToolbarCommands.Any() ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
public Visibility NoTabsVisibility =>
|
||||||
|
Tabs.Count > 0 ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
|
||||||
|
|
||||||
public MainWindowViewModel(IConnectionFactory connectionFactory, IConnectionDialog connectionDialog,
|
public MainWindowViewModel(IConnectionFactory connectionFactory, IConnectionDialog connectionDialog,
|
||||||
ISubscribeDialog subscribeDialog)
|
ISubscribeDialog subscribeDialog, ITabContainer tabContainer)
|
||||||
{
|
{
|
||||||
this.connectionFactory = connectionFactory;
|
this.connectionFactory = connectionFactory;
|
||||||
this.connectionDialog = connectionDialog;
|
this.connectionDialog = connectionDialog;
|
||||||
this.subscribeDialog = subscribeDialog;
|
this.subscribeDialog = subscribeDialog;
|
||||||
|
this.tabContainer = tabContainer;
|
||||||
|
|
||||||
connectionStatus = GetConnectionStatus(null);
|
connectionStatus = GetConnectionStatus(null);
|
||||||
|
|
||||||
@ -83,9 +92,10 @@ namespace PettingZoo.UI.Main
|
|||||||
disconnectCommand = new DelegateCommand(DisconnectExecute, IsConnectedCanExecute);
|
disconnectCommand = new DelegateCommand(DisconnectExecute, IsConnectedCanExecute);
|
||||||
publishCommand = new DelegateCommand(PublishExecute, IsConnectedCanExecute);
|
publishCommand = new DelegateCommand(PublishExecute, IsConnectedCanExecute);
|
||||||
subscribeCommand = new DelegateCommand(SubscribeExecute, IsConnectedCanExecute);
|
subscribeCommand = new DelegateCommand(SubscribeExecute, IsConnectedCanExecute);
|
||||||
closeTabCommand = new DelegateCommand(CloseTabExecute, CloseTabCanExecute);
|
closeTabCommand = new DelegateCommand(CloseTabExecute, HasActiveTabCanExecute);
|
||||||
|
undockTabCommand = new DelegateCommand(UndockTabExecute, HasActiveTabCanExecute);
|
||||||
|
|
||||||
tabFactory = new ViewTabFactory(this, closeTabCommand);
|
tabFactory = new ViewTabFactory(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -126,6 +136,15 @@ namespace PettingZoo.UI.Main
|
|||||||
{
|
{
|
||||||
Tabs.Clear();
|
Tabs.Clear();
|
||||||
|
|
||||||
|
var capturedUndockedTabs = undockedTabs.ToList();
|
||||||
|
undockedTabs.Clear();
|
||||||
|
|
||||||
|
foreach (var undockedTab in capturedUndockedTabs)
|
||||||
|
undockedTab.Value.Close();
|
||||||
|
|
||||||
|
RaisePropertyChanged(nameof(NoTabsVisibility));
|
||||||
|
undockTabCommand.RaiseCanExecuteChanged();
|
||||||
|
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
{
|
{
|
||||||
await connection.DisposeAsync();
|
await connection.DisposeAsync();
|
||||||
@ -170,13 +189,33 @@ namespace PettingZoo.UI.Main
|
|||||||
|
|
||||||
private void CloseTabExecute()
|
private void CloseTabExecute()
|
||||||
{
|
{
|
||||||
if (ActiveTab == null)
|
RemoveActiveTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void UndockTabExecute()
|
||||||
|
{
|
||||||
|
var tab = RemoveActiveTab();
|
||||||
|
if (tab == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var tabHostWindow = UndockedTabHostWindow.Create(this, tab, tabContainer.TabWidth, tabContainer.TabHeight);
|
||||||
|
undockedTabs.Add(tab, tabHostWindow);
|
||||||
|
|
||||||
|
tabHostWindow.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ITab? RemoveActiveTab()
|
||||||
|
{
|
||||||
|
if (ActiveTab == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
var activeTabIndex = Tabs.IndexOf(ActiveTab);
|
var activeTabIndex = Tabs.IndexOf(ActiveTab);
|
||||||
if (activeTabIndex == -1)
|
if (activeTabIndex == -1)
|
||||||
return;
|
return null;
|
||||||
|
|
||||||
|
var tab = Tabs[activeTabIndex];
|
||||||
Tabs.RemoveAt(activeTabIndex);
|
Tabs.RemoveAt(activeTabIndex);
|
||||||
|
|
||||||
if (activeTabIndex == Tabs.Count)
|
if (activeTabIndex == Tabs.Count)
|
||||||
@ -184,10 +223,14 @@ namespace PettingZoo.UI.Main
|
|||||||
|
|
||||||
ActiveTab = activeTabIndex >= 0 ? Tabs[activeTabIndex] : null;
|
ActiveTab = activeTabIndex >= 0 ? Tabs[activeTabIndex] : null;
|
||||||
closeTabCommand.RaiseCanExecuteChanged();
|
closeTabCommand.RaiseCanExecuteChanged();
|
||||||
|
undockTabCommand.RaiseCanExecuteChanged();
|
||||||
|
RaisePropertyChanged(nameof(NoTabsVisibility));
|
||||||
|
|
||||||
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool CloseTabCanExecute()
|
private bool HasActiveTabCanExecute()
|
||||||
{
|
{
|
||||||
return ActiveTab != null;
|
return ActiveTab != null;
|
||||||
}
|
}
|
||||||
@ -199,6 +242,22 @@ namespace PettingZoo.UI.Main
|
|||||||
ActiveTab = tab;
|
ActiveTab = tab;
|
||||||
|
|
||||||
closeTabCommand.RaiseCanExecuteChanged();
|
closeTabCommand.RaiseCanExecuteChanged();
|
||||||
|
undockTabCommand.RaiseCanExecuteChanged();
|
||||||
|
RaisePropertyChanged(nameof(NoTabsVisibility));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void DockTab(ITab tab)
|
||||||
|
{
|
||||||
|
if (undockedTabs.Remove(tab, out var tabHostWindow))
|
||||||
|
tabHostWindow.Close();
|
||||||
|
|
||||||
|
AddTab(tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UndockedTabClosed(ITab tab)
|
||||||
|
{
|
||||||
|
undockedTabs.Remove(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -232,7 +291,7 @@ namespace PettingZoo.UI.Main
|
|||||||
|
|
||||||
public class DesignTimeMainWindowViewModel : MainWindowViewModel
|
public class DesignTimeMainWindowViewModel : MainWindowViewModel
|
||||||
{
|
{
|
||||||
public DesignTimeMainWindowViewModel() : base(null!, null!, null!)
|
public DesignTimeMainWindowViewModel() : base(null!, null!, null!, null!)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ namespace PettingZoo.UI.Tab
|
|||||||
{
|
{
|
||||||
string Title { get; }
|
string Title { get; }
|
||||||
ContentControl Content { get; }
|
ContentControl Content { get; }
|
||||||
ICommand CloseTabCommand { get; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,5 +3,8 @@
|
|||||||
public interface ITabHost
|
public interface ITabHost
|
||||||
{
|
{
|
||||||
void AddTab(ITab tab);
|
void AddTab(ITab tab);
|
||||||
|
|
||||||
|
void DockTab(ITab tab);
|
||||||
|
void UndockedTabClosed(ITab tab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,54 +10,57 @@
|
|||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance res:DesignTimePublisherViewModel, IsDesignTimeCreatable=True}"
|
d:DataContext="{d:DesignInstance res:DesignTimePublisherViewModel, IsDesignTimeCreatable=True}"
|
||||||
Background="White">
|
Background="White">
|
||||||
<ui:GridLayout Style="{StaticResource Form}" Margin="4" Grid.IsSharedSizeScope="True">
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<Grid.RowDefinitions>
|
<ui:GridLayout Style="{StaticResource Form}" Margin="4" Grid.IsSharedSizeScope="True">
|
||||||
<RowDefinition Height="Auto"/>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="16"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="16"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="16"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="16"/>
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
<RowDefinition Height="Auto" />
|
||||||
<Grid.ColumnDefinitions>
|
<RowDefinition Height="Auto" />
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
</Grid.RowDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<Grid.ColumnDefinitions>
|
||||||
</Grid.ColumnDefinitions>
|
<ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="1">
|
<Label Grid.Row="0" Grid.Column="1">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelSendToExchange}" IsChecked="{Binding SendToExchange}" Style="{StaticResource TypeSelection}" />
|
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelSendToExchange}" IsChecked="{Binding SendToExchange}" Style="{StaticResource TypeSelection}" />
|
||||||
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelSendToQueue}" IsChecked="{Binding SendToQueue}" Style="{StaticResource TypeSelection}" />
|
<RadioButton Content="{x:Static res:PublisherViewStrings.LabelSendToQueue}" IsChecked="{Binding SendToQueue}" Style="{StaticResource TypeSelection}" />
|
||||||
|
</StackPanel>
|
||||||
|
</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>
|
</StackPanel>
|
||||||
</Label>
|
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding ReplyTo}" IsEnabled="{Binding ReplyToSpecified}" />
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelExchange}" Visibility="{Binding ExchangeVisibility}" />
|
<StackPanel Orientation="Horizontal" Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center">
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Exchange}" Visibility="{Binding ExchangeVisibility}" />
|
<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>
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static res:PublisherViewStrings.LabelRoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
<ContentControl Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="2" Margin="0 8 0 0" Content="{Binding MessageTypeControl}" />
|
||||||
<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}" />
|
<Button Grid.Row="10" Grid.Column="1" Command="{Binding PublishCommand}" Content="{x:Static res:PublisherViewStrings.CommandPublish}" HorizontalAlignment="Left" />
|
||||||
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Queue}" Visibility="{Binding QueueVisibility}" />
|
</ui:GridLayout>
|
||||||
|
</ScrollViewer>
|
||||||
<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="9" Grid.Column="0" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Auto">
|
|
||||||
<ContentControl Margin="0 8 0 0" Content="{Binding MessageTypeControl}" />
|
|
||||||
</ScrollViewer>
|
|
||||||
</ui:GridLayout>
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -5,8 +5,6 @@ using System.Windows.Controls;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
|
|
||||||
// TODO publish button in page instead of just in toolbar
|
|
||||||
|
|
||||||
namespace PettingZoo.UI.Tab.Publisher
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
{
|
{
|
||||||
public enum MessageType
|
public enum MessageType
|
||||||
|
72
PettingZoo/UI/Tab/Undocked/UndockedTabHostStrings.Designer.cs
generated
Normal file
72
PettingZoo/UI/Tab/Undocked/UndockedTabHostStrings.Designer.cs
generated
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Tab.Undocked {
|
||||||
|
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 UndockedTabHostStrings {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal UndockedTabHostStrings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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.Tab.Undocked.UndockedTabHostStrings", typeof(UndockedTabHostStrings).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 Dock tab.
|
||||||
|
/// </summary>
|
||||||
|
public static string CommandDock {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("CommandDock", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
123
PettingZoo/UI/Tab/Undocked/UndockedTabHostStrings.resx
Normal file
123
PettingZoo/UI/Tab/Undocked/UndockedTabHostStrings.resx
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=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="CommandDock" xml:space="preserve">
|
||||||
|
<value>Dock tab</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
85
PettingZoo/UI/Tab/Undocked/UndockedTabHostViewModel.cs
Normal file
85
PettingZoo/UI/Tab/Undocked/UndockedTabHostViewModel.cs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Tab.Undocked
|
||||||
|
{
|
||||||
|
public class UndockedTabHostViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly ITabHost tabHost;
|
||||||
|
private readonly ITab tab;
|
||||||
|
private readonly DelegateCommand dockCommand;
|
||||||
|
|
||||||
|
|
||||||
|
public string Title => tab.Title;
|
||||||
|
public ContentControl Content => tab.Content;
|
||||||
|
public IEnumerable<TabToolbarCommand> ToolbarCommands => tab.ToolbarCommands;
|
||||||
|
|
||||||
|
public Visibility ToolbarCommandsSeparatorVisibility =>
|
||||||
|
ToolbarCommands.Any() ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
public ICommand DockCommand => dockCommand;
|
||||||
|
|
||||||
|
|
||||||
|
public UndockedTabHostViewModel(ITabHost tabHost, ITab tab)
|
||||||
|
{
|
||||||
|
this.tabHost = tabHost;
|
||||||
|
this.tab = tab;
|
||||||
|
|
||||||
|
tab.PropertyChanged += (_, args) =>
|
||||||
|
{
|
||||||
|
RaisePropertyChanged(args.PropertyName);
|
||||||
|
if (args.PropertyName == nameof(ToolbarCommands))
|
||||||
|
RaisePropertyChanged(nameof(ToolbarCommandsSeparatorVisibility));
|
||||||
|
};
|
||||||
|
|
||||||
|
dockCommand = new DelegateCommand(DockCommandExecute);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void DockCommandExecute()
|
||||||
|
{
|
||||||
|
tabHost.DockTab(tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void WindowClosed()
|
||||||
|
{
|
||||||
|
tabHost.UndockedTabClosed(tab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class DesignTimeUndockedTabHostViewModel : UndockedTabHostViewModel
|
||||||
|
{
|
||||||
|
public DesignTimeUndockedTabHostViewModel() : base(null!, new DesignTimeTab())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class DesignTimeTab : ITab
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
public IEnumerable<TabToolbarCommand> ToolbarCommands { get; } = Array.Empty<TabToolbarCommand>();
|
||||||
|
|
||||||
|
public string Title => "Design-time tab title";
|
||||||
|
public ContentControl Content => null!;
|
||||||
|
|
||||||
|
|
||||||
|
public void Activate()
|
||||||
|
{
|
||||||
|
// Just to prevent the "PropertyChanged is never used" message
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Deactivate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
PettingZoo/UI/Tab/Undocked/UndockedTabHostWindow.xaml
Normal file
44
PettingZoo/UI/Tab/Undocked/UndockedTabHostWindow.xaml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<Window x:Class="PettingZoo.UI.Tab.Undocked.UndockedTabHostWindow"
|
||||||
|
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:undocked="clr-namespace:PettingZoo.UI.Tab.Undocked"
|
||||||
|
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DataContext="{d:DesignInstance undocked:DesignTimeUndockedTabHostViewModel, IsDesignTimeCreatable=True}"
|
||||||
|
Title="{Binding Title}"
|
||||||
|
Height="450"
|
||||||
|
Width="800"
|
||||||
|
WindowStyle="ThreeDBorderWindow">
|
||||||
|
<DockPanel>
|
||||||
|
<ToolBar DockPanel.Dock="Top" ToolBarTray.IsLocked="True">
|
||||||
|
<Button Command="{Binding DockCommand}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="{svgc:SvgImage Source=/Images/Dock.svg, AppName=PettingZoo}" Width="16" Height="16" Style="{StaticResource ToolbarIcon}"/>
|
||||||
|
<TextBlock Margin="3,0,0,0" Text="{x:Static undocked:UndockedTabHostStrings.CommandDock}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Visibility="{Binding ToolbarCommandsSeparatorVisibility}" />
|
||||||
|
<ItemsControl ItemsSource="{Binding ToolbarCommands}">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Button Command="{Binding Command}" Style="{DynamicResource {x:Static ToolBar.ButtonStyleKey}}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="{Binding Icon}" Width="16" Height="16" Style="{StaticResource ToolbarIcon}"/>
|
||||||
|
<TextBlock Margin="3,0,0,0" Text="{Binding Caption}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</ToolBar>
|
||||||
|
|
||||||
|
<ContentControl Content="{Binding Content}" />
|
||||||
|
</DockPanel>
|
||||||
|
</Window>
|
34
PettingZoo/UI/Tab/Undocked/UndockedTabHostWindow.xaml.cs
Normal file
34
PettingZoo/UI/Tab/Undocked/UndockedTabHostWindow.xaml.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Tab.Undocked
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for UndockedTabHostWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class UndockedTabHostWindow
|
||||||
|
{
|
||||||
|
public static UndockedTabHostWindow Create(ITabHost tabHost, ITab tab, double width, double height)
|
||||||
|
{
|
||||||
|
var viewModel = new UndockedTabHostViewModel(tabHost, tab);
|
||||||
|
var window = new UndockedTabHostWindow(viewModel)
|
||||||
|
{
|
||||||
|
Width = width,
|
||||||
|
Height = height
|
||||||
|
};
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public UndockedTabHostWindow(UndockedTabHostViewModel viewModel)
|
||||||
|
{
|
||||||
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Closed += (_, _) =>
|
||||||
|
{
|
||||||
|
viewModel.WindowClosed();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,6 @@ namespace PettingZoo.UI.Tab
|
|||||||
{
|
{
|
||||||
public string Title => getTitle(viewModel);
|
public string Title => getTitle(viewModel);
|
||||||
public ContentControl Content { get; }
|
public ContentControl Content { get; }
|
||||||
public ICommand CloseTabCommand { get; }
|
|
||||||
|
|
||||||
public IEnumerable<TabToolbarCommand> ToolbarCommands => viewModel is ITabToolbarCommands tabToolbarCommands
|
public IEnumerable<TabToolbarCommand> ToolbarCommands => viewModel is ITabToolbarCommands tabToolbarCommands
|
||||||
? tabToolbarCommands.ToolbarCommands
|
? tabToolbarCommands.ToolbarCommands
|
||||||
@ -25,14 +24,13 @@ namespace PettingZoo.UI.Tab
|
|||||||
private readonly Func<TViewModel, string> getTitle;
|
private readonly Func<TViewModel, string> getTitle;
|
||||||
|
|
||||||
|
|
||||||
public ViewTab(ICommand closeTabCommand, TView view, TViewModel viewModel, Expression<Func<TViewModel, string>> title)
|
public ViewTab(TView view, TViewModel viewModel, Expression<Func<TViewModel, string>> title)
|
||||||
{
|
{
|
||||||
if (title.Body is not MemberExpression titleMemberExpression)
|
if (title.Body is not MemberExpression titleMemberExpression)
|
||||||
throw new ArgumentException(@"Invalid expression type, expected viewModel => viewModel.TitlePropertyName", nameof(title));
|
throw new ArgumentException(@"Invalid expression type, expected viewModel => viewModel.TitlePropertyName", nameof(title));
|
||||||
|
|
||||||
var titlePropertyName = titleMemberExpression.Member.Name;
|
var titlePropertyName = titleMemberExpression.Member.Name;
|
||||||
|
|
||||||
CloseTabCommand = closeTabCommand;
|
|
||||||
this.viewModel = viewModel;
|
this.viewModel = viewModel;
|
||||||
getTitle = title.Compile();
|
getTitle = title.Compile();
|
||||||
Content = view;
|
Content = view;
|
||||||
|
@ -8,13 +8,11 @@ namespace PettingZoo.UI.Tab
|
|||||||
public class ViewTabFactory : ITabFactory
|
public class ViewTabFactory : ITabFactory
|
||||||
{
|
{
|
||||||
private readonly ITabHost tabHost;
|
private readonly ITabHost tabHost;
|
||||||
private readonly ICommand closeTabCommand;
|
|
||||||
|
|
||||||
|
|
||||||
public ViewTabFactory(ITabHost tabHost, ICommand closeTabCommand)
|
public ViewTabFactory(ITabHost tabHost)
|
||||||
{
|
{
|
||||||
this.tabHost = tabHost;
|
this.tabHost = tabHost;
|
||||||
this.closeTabCommand = closeTabCommand;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -22,7 +20,6 @@ namespace PettingZoo.UI.Tab
|
|||||||
{
|
{
|
||||||
var viewModel = new SubscriberViewModel(tabHost, this, connection, subscriber);
|
var viewModel = new SubscriberViewModel(tabHost, this, connection, subscriber);
|
||||||
return new ViewTab<SubscriberView, SubscriberViewModel>(
|
return new ViewTab<SubscriberView, SubscriberViewModel>(
|
||||||
closeTabCommand,
|
|
||||||
new SubscriberView(viewModel),
|
new SubscriberView(viewModel),
|
||||||
viewModel,
|
viewModel,
|
||||||
vm => vm.Title);
|
vm => vm.Title);
|
||||||
@ -33,7 +30,6 @@ namespace PettingZoo.UI.Tab
|
|||||||
{
|
{
|
||||||
var viewModel = new PublisherViewModel(tabHost, this, connection, fromReceivedMessage);
|
var viewModel = new PublisherViewModel(tabHost, this, connection, fromReceivedMessage);
|
||||||
return new ViewTab<PublisherView, PublisherViewModel>(
|
return new ViewTab<PublisherView, PublisherViewModel>(
|
||||||
closeTabCommand,
|
|
||||||
new PublisherView(viewModel),
|
new PublisherView(viewModel),
|
||||||
viewModel,
|
viewModel,
|
||||||
vm => vm.Title);
|
vm => vm.Title);
|
||||||
|
Loading…
Reference in New Issue
Block a user