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.Migrations.Interfaces;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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>();
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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" />
|
||||
|
||||
@ -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)!;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user