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:
parent
26639ca8fd
commit
b963aa0909
@ -1,5 +1,4 @@
|
|||||||
using System.IO;
|
using Artemis.Core.Services;
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.Storage;
|
using Artemis.Storage;
|
||||||
using Artemis.Storage.Migrations.Interfaces;
|
using Artemis.Storage.Migrations.Interfaces;
|
||||||
using Artemis.Storage.Repositories.Interfaces;
|
using Artemis.Storage.Repositories.Interfaces;
|
||||||
|
|||||||
@ -16,6 +16,7 @@ using McMaster.NETCore.Plugins;
|
|||||||
using Ninject;
|
using Ninject;
|
||||||
using Ninject.Extensions.ChildKernel;
|
using Ninject.Extensions.ChildKernel;
|
||||||
using Ninject.Parameters;
|
using Ninject.Parameters;
|
||||||
|
using Ninject.Planning.Bindings.Resolvers;
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
@ -410,6 +411,9 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
// Create the Ninject child kernel and load the module
|
// Create the Ninject child kernel and load the module
|
||||||
plugin.Kernel = new ChildKernel(_kernel, new PluginModule(plugin));
|
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));
|
OnPluginEnabling(new PluginEventArgs(plugin));
|
||||||
|
|
||||||
plugin.SetEnabled(true);
|
plugin.SetEnabled(true);
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ApplicationIcon />
|
<ApplicationIcon />
|
||||||
<StartupObject />
|
<StartupObject />
|
||||||
|
<OutputPath>bin\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DocumentationFile>C:\Repos\Artemis\src\Artemis.UI.Avalonia.Shared\Artemis.UI.Avalonia.Shared.xml</DocumentationFile>
|
<DocumentationFile>C:\Repos\Artemis\src\Artemis.UI.Avalonia.Shared\Artemis.UI.Avalonia.Shared.xml</DocumentationFile>
|
||||||
|
|||||||
@ -282,9 +282,14 @@
|
|||||||
Gets the plugin this configuration view model is associated with
|
Gets the plugin this configuration view model is associated with
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="P:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.Close">
|
<member name="M:Artemis.UI.Avalonia.Shared.PluginConfigurationViewModel.Close">
|
||||||
<summary>
|
<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>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="T:Artemis.UI.Avalonia.Shared.Services.Builders.FileDialogFilterBuilder">
|
<member name="T:Artemis.UI.Avalonia.Shared.Services.Builders.FileDialogFilterBuilder">
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System.Reactive;
|
using System;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia.Shared
|
namespace Artemis.UI.Avalonia.Shared
|
||||||
{
|
{
|
||||||
@ -16,7 +15,6 @@ namespace Artemis.UI.Avalonia.Shared
|
|||||||
protected PluginConfigurationViewModel(Plugin plugin)
|
protected PluginConfigurationViewModel(Plugin plugin)
|
||||||
{
|
{
|
||||||
Plugin = plugin;
|
Plugin = plugin;
|
||||||
Close = ReactiveCommand.Create(() => { });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -25,8 +23,16 @@ namespace Artemis.UI.Avalonia.Shared
|
|||||||
public Plugin Plugin { get; }
|
public Plugin Plugin { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A command that closes the window
|
/// Closes the window hosting the view model
|
||||||
/// </summary>
|
/// </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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,6 +33,8 @@ namespace Artemis.UI.Avalonia.Shared.Services
|
|||||||
|
|
||||||
public void ShowWindow(object viewModel)
|
public void ShowWindow(object viewModel)
|
||||||
{
|
{
|
||||||
|
Window parent = GetCurrentWindow();
|
||||||
|
|
||||||
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
|
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
|
||||||
Type? type = viewModel.GetType().Assembly.GetType(name);
|
Type? type = viewModel.GetType().Assembly.GetType(name);
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ namespace Artemis.UI.Avalonia.Shared.Services
|
|||||||
|
|
||||||
Window window = (Window) Activator.CreateInstance(type)!;
|
Window window = (Window) Activator.CreateInstance(type)!;
|
||||||
window.DataContext = viewModel;
|
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>
|
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)
|
public async Task<TResult> ShowDialogAsync<TResult>(DialogViewModelBase<TResult> viewModel)
|
||||||
{
|
{
|
||||||
if (Application.Current.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime classic)
|
Window parent = GetCurrentWindow();
|
||||||
{
|
|
||||||
throw new ArtemisSharedUIException("Can't show a dialog when application lifetime is not IClassicDesktopStyleApplicationLifetime.");
|
|
||||||
}
|
|
||||||
|
|
||||||
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
|
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
|
||||||
Type? type = viewModel.GetType().Assembly.GetType(name);
|
Type? type = viewModel.GetType().Assembly.GetType(name);
|
||||||
@ -92,7 +91,6 @@ namespace Artemis.UI.Avalonia.Shared.Services
|
|||||||
|
|
||||||
Window window = (Window) Activator.CreateInstance(type)!;
|
Window window = (Window) Activator.CreateInstance(type)!;
|
||||||
window.DataContext = viewModel;
|
window.DataContext = viewModel;
|
||||||
Window parent = classic.Windows.FirstOrDefault(w => w.IsActive) ?? classic.MainWindow;
|
|
||||||
return await window.ShowDialog<TResult>(parent);
|
return await window.ShowDialog<TResult>(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,8 @@ namespace Artemis.UI.Avalonia
|
|||||||
private void InitializeNinject()
|
private void InitializeNinject()
|
||||||
{
|
{
|
||||||
_kernel = new StandardKernel();
|
_kernel = new StandardKernel();
|
||||||
|
_kernel.Settings.InjectNonPublic = true;
|
||||||
|
|
||||||
_kernel.Load<CoreModule>();
|
_kernel.Load<CoreModule>();
|
||||||
_kernel.Load<UIModule>();
|
_kernel.Load<UIModule>();
|
||||||
_kernel.Load<SharedUIModule>();
|
_kernel.Load<SharedUIModule>();
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<OutputPath>bin\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DocumentationFile></DocumentationFile>
|
<DocumentationFile></DocumentationFile>
|
||||||
|
|||||||
@ -8,10 +8,13 @@
|
|||||||
Title="Artemis | Device Properties"
|
Title="Artemis | Device Properties"
|
||||||
Width="1250"
|
Width="1250"
|
||||||
Height="900"
|
Height="900"
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
WindowStartupLocation="CenterOwner"
|
||||||
Padding="0 32 0 0">
|
ExtendClientAreaToDecorationsHint="True">
|
||||||
<Grid ColumnDefinitions="*,0,1.5*" >
|
<Grid>
|
||||||
<Grid Grid.Column="0" Name="DeviceDisplayGrid" >
|
<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>
|
<Grid.Background>
|
||||||
<VisualBrush TileMode="Tile" Stretch="Uniform" DestinationRect="0,0,25,25">
|
<VisualBrush TileMode="Tile" Stretch="Uniform" DestinationRect="0,0,25,25">
|
||||||
<VisualBrush.Visual>
|
<VisualBrush.Visual>
|
||||||
@ -32,10 +35,10 @@
|
|||||||
ShowColors="True"
|
ShowColors="True"
|
||||||
Margin="20" />
|
Margin="20" />
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal"
|
<StackPanel Orientation="Horizontal"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Margin="15"
|
Margin="15"
|
||||||
IsVisible="{Binding Device.Layout.RgbLayout.Author, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
IsVisible="{Binding Device.Layout.RgbLayout.Author, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||||
<TextBlock Classes="h5" Text="Device layout by " />
|
<TextBlock Classes="h5" Text="Device layout by " />
|
||||||
<TextBlock Classes="h5" FontWeight="Bold" Text="{Binding Device.Layout.RgbLayout.Author}" />
|
<TextBlock Classes="h5" FontWeight="Bold" Text="{Binding Device.Layout.RgbLayout.Author}" />
|
||||||
@ -43,23 +46,25 @@
|
|||||||
</Grid>
|
</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">
|
<Border Grid.Column="2" Classes="card" CornerRadius="10 0 0 0">
|
||||||
<TabControl Items="{Binding Tabs}">
|
<TabControl Items="{Binding Tabs}">
|
||||||
<TabControl.ItemTemplate>
|
<TabControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<TextBlock Text="{Binding DisplayName}" />
|
<TextBlock Text="{Binding DisplayName}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</TabControl.ItemTemplate>
|
</TabControl.ItemTemplate>
|
||||||
<TabControl.ContentTemplate>
|
<TabControl.ContentTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
<ContentControl Content="{Binding}" Margin="0 10 0 0"/>
|
<ContentControl Content="{Binding}" Margin="0 10 0 0" />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</TabControl.ContentTemplate>
|
</TabControl.ContentTemplate>
|
||||||
</TabControl>
|
</TabControl>
|
||||||
</Border>
|
</Border>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</Window>
|
</Window>
|
||||||
@ -4,6 +4,14 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginSettingsWindowView"
|
x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginSettingsWindowView"
|
||||||
Title="{Binding DisplayName}">
|
Title="{Binding DisplayName}"
|
||||||
<ContentControl Content="{Binding ConfigurationViewModel}"></ContentControl>
|
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>
|
</Window>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
using Artemis.UI.Avalonia.Screens.Plugins.ViewModels;
|
using Artemis.UI.Avalonia.Screens.Plugins.ViewModels;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.Mixins;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
@ -17,7 +17,22 @@ namespace Artemis.UI.Avalonia.Screens.Plugins.Views
|
|||||||
this.AttachDevTools();
|
this.AttachDevTools();
|
||||||
#endif
|
#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()
|
private void InitializeComponent()
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<ContentControl Grid.Column="0" Content="{Binding SidebarViewModel}" />
|
<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 Router="{Binding Router}">
|
||||||
<reactiveUi:RoutedViewHost.PageTransition>
|
<reactiveUi:RoutedViewHost.PageTransition>
|
||||||
<CrossFade Duration="0.1" />
|
<CrossFade Duration="0.1" />
|
||||||
|
|||||||
@ -11,8 +11,9 @@ namespace Artemis.UI.Avalonia
|
|||||||
|
|
||||||
public IControl Build(object data)
|
public IControl Build(object data)
|
||||||
{
|
{
|
||||||
string name = data.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
|
Type dataType = data.GetType();
|
||||||
Type? type = Type.GetType(name);
|
string name = dataType.FullName!.Split('`')[0].Replace("ViewModel", "View");
|
||||||
|
Type? type = dataType.Assembly.GetType(name);
|
||||||
|
|
||||||
if (type != null)
|
if (type != null)
|
||||||
return (Control) Activator.CreateInstance(type)!;
|
return (Control) Activator.CreateInstance(type)!;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user