1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Window Service - Always provide current window as parent

Plugins - Allow self-binding of unregistered services
Plugins UI - Style settings window
This commit is contained in:
Robert 2021-11-13 00:23:09 +01:00
parent 26639ca8fd
commit b963aa0909
13 changed files with 92 additions and 47 deletions

View File

@ -1,5 +1,4 @@
using System.IO;
using Artemis.Core.Services;
using Artemis.Core.Services;
using Artemis.Storage;
using Artemis.Storage.Migrations.Interfaces;
using Artemis.Storage.Repositories.Interfaces;

View File

@ -16,6 +16,7 @@ using McMaster.NETCore.Plugins;
using Ninject;
using Ninject.Extensions.ChildKernel;
using Ninject.Parameters;
using Ninject.Planning.Bindings.Resolvers;
using RGB.NET.Core;
using Serilog;
@ -410,6 +411,9 @@ namespace Artemis.Core.Services
// Create the Ninject child kernel and load the module
plugin.Kernel = new ChildKernel(_kernel, new PluginModule(plugin));
// The kernel used by Core is unforgiving about missing bindings, no need to be so hard on plugin devs
plugin.Kernel.Components.Add<IMissingBindingResolver, SelfBindingResolver>();
OnPluginEnabling(new PluginEventArgs(plugin));
plugin.SetEnabled(true);

View File

@ -5,6 +5,7 @@
<Nullable>enable</Nullable>
<ApplicationIcon />
<StartupObject />
<OutputPath>bin\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>C:\Repos\Artemis\src\Artemis.UI.Avalonia.Shared\Artemis.UI.Avalonia.Shared.xml</DocumentationFile>

View File

@ -282,9 +282,14 @@
Gets the plugin this configuration view model is associated with
</summary>
</member>
<member name="P:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.Close">
<member name="M:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.Close">
<summary>
A command that closes the window
Closes the window hosting the view model
</summary>
</member>
<member name="E:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.CloseRequested">
<summary>
Occurs when the the window hosting the view model should close
</summary>
</member>
<member name="T:Artemis.UI.Avalonia.Shared.Services.Builders.FileDialogFilterBuilder">

View File

@ -1,6 +1,5 @@
using System.Reactive;
using System;
using Artemis.Core;
using ReactiveUI;
namespace Artemis.UI.Avalonia.Shared
{
@ -16,7 +15,6 @@ namespace Artemis.UI.Avalonia.Shared
protected PluginConfigurationViewModel(Plugin plugin)
{
Plugin = plugin;
Close = ReactiveCommand.Create(() => { });
}
/// <summary>
@ -25,8 +23,16 @@ namespace Artemis.UI.Avalonia.Shared
public Plugin Plugin { get; }
/// <summary>
/// A command that closes the window
/// Closes the window hosting the view model
/// </summary>
public ReactiveCommand<Unit, Unit> Close { get; }
public void Close()
{
CloseRequested?.Invoke(this, EventArgs.Empty);
}
/// <summary>
/// Occurs when the the window hosting the view model should close
/// </summary>
public event EventHandler? CloseRequested;
}
}

View File

@ -33,6 +33,8 @@ namespace Artemis.UI.Avalonia.Shared.Services
public void ShowWindow(object viewModel)
{
Window parent = GetCurrentWindow();
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
Type? type = viewModel.GetType().Assembly.GetType(name);
@ -48,7 +50,7 @@ namespace Artemis.UI.Avalonia.Shared.Services
Window window = (Window) Activator.CreateInstance(type)!;
window.DataContext = viewModel;
window.Show();
window.Show(parent);
}
public async Task<TResult> ShowDialogAsync<TViewModel, TResult>(params (string name, object value)[] parameters) where TViewModel : DialogViewModelBase<TResult>
@ -72,10 +74,7 @@ namespace Artemis.UI.Avalonia.Shared.Services
public async Task<TResult> ShowDialogAsync<TResult>(DialogViewModelBase<TResult> viewModel)
{
if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime classic)
{
throw new ArtemisSharedUIException("Can't show a dialog when application lifetime is not IClassicDesktopStyleApplicationLifetime.");
}
Window parent = GetCurrentWindow();
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
Type? type = viewModel.GetType().Assembly.GetType(name);
@ -92,7 +91,6 @@ namespace Artemis.UI.Avalonia.Shared.Services
Window window = (Window) Activator.CreateInstance(type)!;
window.DataContext = viewModel;
Window parent = classic.Windows.FirstOrDefault(w => w.IsActive) ?? classic.MainWindow;
return await window.ShowDialog<TResult>(parent);
}

View File

@ -42,6 +42,8 @@ namespace Artemis.UI.Avalonia
private void InitializeNinject()
{
_kernel = new StandardKernel();
_kernel.Settings.InjectNonPublic = true;
_kernel.Load<CoreModule>();
_kernel.Load<UIModule>();
_kernel.Load<SharedUIModule>();

View File

@ -3,6 +3,7 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<Nullable>enable</Nullable>
<OutputPath>bin\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile></DocumentationFile>

View File

@ -8,10 +8,13 @@
Title="Artemis | Device Properties"
Width="1250"
Height="900"
ExtendClientAreaToDecorationsHint="True"
Padding="0 32 0 0">
<Grid ColumnDefinitions="*,0,1.5*" >
<Grid Grid.Column="0" Name="DeviceDisplayGrid" >
WindowStartupLocation="CenterOwner"
ExtendClientAreaToDecorationsHint="True">
<Grid>
<TextBlock Margin="10" IsHitTestVisible="False" Text="Artemis | Device Properties" />
<Grid Margin="0 32 0 0" ColumnDefinitions="*,0,1.5*">
<Grid Grid.Column="0" Name="DeviceDisplayGrid">
<Grid.Background>
<VisualBrush TileMode="Tile" Stretch="Uniform" DestinationRect="0,0,25,25">
<VisualBrush.Visual>
@ -32,10 +35,10 @@
ShowColors="True"
Margin="20" />
<StackPanel Orientation="Horizontal"
VerticalAlignment="Bottom"
HorizontalAlignment="Left"
Margin="15"
<StackPanel Orientation="Horizontal"
VerticalAlignment="Bottom"
HorizontalAlignment="Left"
Margin="15"
IsVisible="{Binding Device.Layout.RgbLayout.Author, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
<TextBlock Classes="h5" Text="Device layout by " />
<TextBlock Classes="h5" FontWeight="Bold" Text="{Binding Device.Layout.RgbLayout.Author}" />
@ -43,23 +46,25 @@
</Grid>
<GridSplitter Grid.Column="1" Width="15" Margin="-15 0 0 0" Background="Transparent" HorizontalAlignment="Stretch"/>
<GridSplitter Grid.Column="1" Width="15" Margin="-15 0 0 0" Background="Transparent" HorizontalAlignment="Stretch" />
<Border Grid.Column="2" Classes="card" CornerRadius="10 0 0 0">
<TabControl Items="{Binding Tabs}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ContentControl Content="{Binding}" Margin="0 10 0 0"/>
</ScrollViewer>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Border>
<Border Grid.Column="2" Classes="card" CornerRadius="10 0 0 0">
<TabControl Items="{Binding Tabs}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ContentControl Content="{Binding}" Margin="0 10 0 0" />
</ScrollViewer>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Border>
</Grid>
</Grid>
</Window>

View File

@ -4,6 +4,14 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginSettingsWindowView"
Title="{Binding DisplayName}">
<ContentControl Content="{Binding ConfigurationViewModel}"></ContentControl>
Title="{Binding DisplayName}"
ExtendClientAreaToDecorationsHint="True"
Width="800"
Height="800"
WindowStartupLocation="CenterOwner">
<Grid>
<TextBlock Margin="10" IsHitTestVisible="False" Text="{Binding DisplayName}"></TextBlock>
<ContentControl Margin="0 32 0 0" Content="{Binding ConfigurationViewModel}"></ContentControl>
</Grid>
</Window>

View File

@ -1,7 +1,7 @@
using System;
using System.Reactive.Disposables;
using Artemis.UI.Avalonia.Screens.Plugins.ViewModels;
using Avalonia;
using Avalonia.Controls.Mixins;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using ReactiveUI;
@ -17,7 +17,22 @@ namespace Artemis.UI.Avalonia.Screens.Plugins.Views
this.AttachDevTools();
#endif
this.WhenActivated(disposables => { ViewModel!.ConfigurationViewModel.Close.Subscribe(_ => Close()).DisposeWith(disposables); });
this.WhenActivated(disposables =>
{
ViewModel!.ConfigurationViewModel.CloseRequested += ConfigurationViewModelOnCloseRequested;
Disposable.Create(HandleDeactivation).DisposeWith(disposables);
}
);
}
private void HandleDeactivation()
{
ViewModel!.ConfigurationViewModel.CloseRequested -= ConfigurationViewModelOnCloseRequested;
}
private void ConfigurationViewModelOnCloseRequested(object? sender, EventArgs e)
{
Close();
}
private void InitializeComponent()

View File

@ -13,7 +13,7 @@
<ContentControl Grid.Column="0" Content="{Binding SidebarViewModel}" />
<Border Classes="router-container" Grid.Column="1" Margin="0 10 0 0">
<Border Classes="router-container" Grid.Column="1" Margin="0 40 0 0">
<reactiveUi:RoutedViewHost Router="{Binding Router}">
<reactiveUi:RoutedViewHost.PageTransition>
<CrossFade Duration="0.1" />

View File

@ -11,8 +11,9 @@ namespace Artemis.UI.Avalonia
public IControl Build(object data)
{
string name = data.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
Type? type = Type.GetType(name);
Type dataType = data.GetType();
string name = dataType.FullName!.Split('`')[0].Replace("ViewModel", "View");
Type? type = dataType.Assembly.GetType(name);
if (type != null)
return (Control) Activator.CreateInstance(type)!;