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

Sidebar - Moved VMs and views

Sidebar - Implemented profile selection
Windows - Fix designer breaking due to the input provider
This commit is contained in:
Robert 2021-12-09 23:32:59 +01:00
parent 971e32f7a5
commit 0c3f84cbeb
31 changed files with 244 additions and 60 deletions

View File

@ -95,6 +95,7 @@ namespace Artemis.Core.Services
MouseMoveDataReceived?.Invoke(this, new InputProviderMouseMoveEventArgs(device, cursorX, cursorY, deltaX, deltaY)); MouseMoveDataReceived?.Invoke(this, new InputProviderMouseMoveEventArgs(device, cursorX, cursorY, deltaX, deltaY));
} }
// TODO: Remove this as the core should handle this in GetDeviceByIdentifier
/// <summary> /// <summary>
/// Invokes the <see cref="IdentifierReceived" /> event which the <see cref="IInputService" /> listens to as long as /// Invokes the <see cref="IdentifierReceived" /> event which the <see cref="IInputService" /> listens to as long as
/// this provider is registered /// this provider is registered

View File

@ -98,6 +98,7 @@ namespace Artemis.Core.Services
BustIdentifierCache(); BustIdentifierCache();
} }
// TODO: Move the OnIdentifierReceived logic into here and get rid of OnIdentifierReceived, this and OnIdentifierReceived are always called in combination with each other
public ArtemisDevice? GetDeviceByIdentifier(InputProvider provider, object identifier, InputDeviceType type) public ArtemisDevice? GetDeviceByIdentifier(InputProvider provider, object identifier, InputDeviceType type)
{ {
if (provider == null) throw new ArgumentNullException(nameof(provider)); if (provider == null) throw new ArgumentNullException(nameof(provider));

View File

@ -4,6 +4,7 @@ using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
@ -91,7 +92,7 @@ namespace Artemis.UI.Shared.Controls
/// to an SVG /// to an SVG
/// </summary> /// </summary>
public static readonly StyledProperty<Hotkey?> HotkeyProperty = public static readonly StyledProperty<Hotkey?> HotkeyProperty =
AvaloniaProperty.Register<HotkeyBox, Hotkey?>(nameof(Hotkey), notifying: HotkeyChanging); AvaloniaProperty.Register<HotkeyBox, Hotkey?>(nameof(Hotkey), defaultBindingMode: BindingMode.TwoWay, notifying: HotkeyChanging);
public static readonly StyledProperty<string?> WatermarkProperty = public static readonly StyledProperty<string?> WatermarkProperty =
AvaloniaProperty.Register<HotkeyBox, string?>(nameof(Watermark)); AvaloniaProperty.Register<HotkeyBox, string?>(nameof(Watermark));

View File

@ -1,5 +1,4 @@
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Windows.Providers;
using Artemis.UI.Windows.Providers.Input; using Artemis.UI.Windows.Providers.Input;
using Avalonia; using Avalonia;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
@ -17,15 +16,17 @@ namespace Artemis.UI.Windows
_kernel = ArtemisBootstrapper.Bootstrap(this); _kernel = ArtemisBootstrapper.Bootstrap(this);
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance; RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
RegisterProviders(_kernel);
} }
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()
{ {
ArtemisBootstrapper.Initialize(); ArtemisBootstrapper.Initialize();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
_applicationStateManager = new ApplicationStateManager(_kernel!, desktop.Args); _applicationStateManager = new ApplicationStateManager(_kernel!, desktop.Args);
RegisterProviders(_kernel!);
}
} }
private void RegisterProviders(StandardKernel standardKernel) private void RegisterProviders(StandardKernel standardKernel)

View File

@ -185,7 +185,7 @@ namespace Artemis.UI.Windows.Providers.Input
if (identifier != null) if (identifier != null)
try try
{ {
device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Keyboard); device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Mouse);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -51,10 +51,10 @@
<Compile Update="Screens\Debugger\Tabs\Settings\DebugSettingsView.axaml.cs"> <Compile Update="Screens\Debugger\Tabs\Settings\DebugSettingsView.axaml.cs">
<DependentUpon>DebugSettingsView.axaml</DependentUpon> <DependentUpon>DebugSettingsView.axaml</DependentUpon>
</Compile> </Compile>
<Compile Update="Screens\Root\Sidebar\ContentDialogs\SidebarCategoryEditView.axaml.cs"> <Compile Update="Screens\Sidebar\ContentDialogs\SidebarCategoryEditView.axaml.cs">
<DependentUpon>SidebarCategoryEditView.axaml</DependentUpon> <DependentUpon>SidebarCategoryEditView.axaml</DependentUpon>
</Compile> </Compile>
<Compile Update="Screens\Root\Sidebar\Dialogs\ProfileConfigurationEditView.axaml.cs"> <Compile Update="Screens\Sidebar\Dialogs\ProfileConfigurationEditView.axaml.cs">
<DependentUpon>ProfileConfigurationEditView.axaml</DependentUpon> <DependentUpon>ProfileConfigurationEditView.axaml</DependentUpon>
</Compile> </Compile>
</ItemGroup> </ItemGroup>

View File

@ -3,9 +3,11 @@ using Artemis.Core;
using Artemis.UI.Screens.Device; using Artemis.UI.Screens.Device;
using Artemis.UI.Screens.Device.Tabs; using Artemis.UI.Screens.Device.Tabs;
using Artemis.UI.Screens.Plugins; using Artemis.UI.Screens.Plugins;
using Artemis.UI.Screens.Root.Sidebar; using Artemis.UI.Screens.ProfileEditor;
using Artemis.UI.Screens.Settings.Tabs; using Artemis.UI.Screens.Settings.Tabs;
using Artemis.UI.Screens.Sidebar;
using Artemis.UI.Screens.SurfaceEditor; using Artemis.UI.Screens.SurfaceEditor;
using Artemis.UI.Services;
using ReactiveUI; using ReactiveUI;
namespace Artemis.UI.Ninject.Factories namespace Artemis.UI.Ninject.Factories
@ -49,4 +51,9 @@ namespace Artemis.UI.Ninject.Factories
{ {
PluginPrerequisiteViewModel PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall); PluginPrerequisiteViewModel PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall);
} }
public interface IProfileEditorVmFactory : IVmFactory
{
ProfileEditorViewModel ProfileEditorViewModel(IScreen hostScreen);
}
} }

View File

@ -4,5 +4,10 @@
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.Screens.ProfileEditor.ProfileEditorView"> x:Class="Artemis.UI.Screens.ProfileEditor.ProfileEditorView">
Welcome to Avalonia! <StackPanel Orientation="Horizontal">
<TextBlock Classes="h4 subtitle" Text="Wow, you're editing "/>
<TextBlock Classes="h4" Text="{Binding Profile.Name}"/>
<TextBlock Classes="h4 subtitle" Text=". That's amazing! keep it up man, you can do it!!!!11!11"/>
</StackPanel>
</UserControl> </UserControl>

View File

@ -1,8 +1,28 @@
using Artemis.UI.Shared; using System;
using System.Reactive.Disposables;
using Artemis.Core;
using Artemis.UI.Services;
using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor namespace Artemis.UI.Screens.ProfileEditor
{ {
public class ProfileEditorViewModel : ActivatableViewModelBase public class ProfileEditorViewModel : MainScreenViewModel
{ {
private ProfileConfiguration? _profile;
/// <inheritdoc />
public ProfileEditorViewModel(IScreen hostScreen, IProfileEditorService profileEditorService) : base(hostScreen, "profile-editor")
{
this.WhenActivated(disposables =>
{
profileEditorService.CurrentProfileConfiguration.WhereNotNull().Subscribe(p => Profile = p).DisposeWith(disposables);
});
}
public ProfileConfiguration? Profile
{
get => _profile;
set => this.RaiseAndSetIfChanged(ref _profile, value);
}
} }
} }

View File

@ -4,7 +4,7 @@ using System.Threading.Tasks;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Root.Sidebar; using Artemis.UI.Screens.Sidebar;
using Artemis.UI.Services.Interfaces; using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared; using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;

View File

@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
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.Screens.Root.Sidebar.Dialogs.SidebarCategoryEditView"> x:Class="Artemis.UI.Screens.Sidebar.ContentDialogs.SidebarCategoryEditView">
<StackPanel> <StackPanel>
<StackPanel.KeyBindings> <StackPanel.KeyBindings>
<KeyBinding Gesture="Enter" Command="{Binding Confirm}" /> <KeyBinding Gesture="Enter" Command="{Binding Confirm}" />

View File

@ -3,7 +3,7 @@ using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
using ReactiveUI; using ReactiveUI;
namespace Artemis.UI.Screens.Root.Sidebar.Dialogs namespace Artemis.UI.Screens.Sidebar.ContentDialogs
{ {
public class SidebarCategoryEditView : ReactiveUserControl<SidebarCategoryEditViewModel> public class SidebarCategoryEditView : ReactiveUserControl<SidebarCategoryEditViewModel>
{ {

View File

@ -6,7 +6,7 @@ using FluentAvalonia.UI.Controls;
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Validation.Extensions; using ReactiveUI.Validation.Extensions;
namespace Artemis.UI.Screens.Root.Sidebar.Dialogs namespace Artemis.UI.Screens.Sidebar.ContentDialogs
{ {
public class SidebarCategoryEditViewModel : ContentDialogViewModelBase public class SidebarCategoryEditViewModel : ContentDialogViewModelBase
{ {

View File

@ -4,15 +4,16 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core" xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared" xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:local="clr-namespace:Artemis.UI.Screens.Root.Sidebar.Dialogs"
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared" xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:svg="clr-namespace:Avalonia.Svg.Skia;assembly=Avalonia.Svg.Skia" xmlns:svg="clr-namespace:Avalonia.Svg.Skia;assembly=Avalonia.Svg.Skia"
xmlns:local="clr-namespace:Artemis.UI.Screens.Sidebar.Dialogs"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="850" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="850"
x:Class="Artemis.UI.Screens.Root.Sidebar.Dialogs.ProfileConfigurationEditView" x:Class="Artemis.UI.Screens.Sidebar.Dialogs.ProfileConfigurationEditView"
Title="{Binding DisplayName}" Title="{Binding DisplayName}"
Icon="/Assets/Images/Logo/bow.ico" Icon="/Assets/Images/Logo/bow.ico"
Width="800" Width="800"
MinWidth="420"
Height="850"> Height="850">
<Window.Resources> <Window.Resources>
<converters:EnumToBooleanConverter x:Key="EnumBoolConverter" /> <converters:EnumToBooleanConverter x:Key="EnumBoolConverter" />
@ -24,6 +25,14 @@
<Style Selector="TextBlock.label"> <Style Selector="TextBlock.label">
<Setter Property="Margin" Value="0 10 0 5" /> <Setter Property="Margin" Value="0 10 0 5" />
</Style> </Style>
<Style Selector="TextBlock.section-header">
<Setter Property="Margin" Value="0 0 5 0" />
</Style>
<Style Selector="TextBlock.section-subtitle">
<Setter Property="VerticalAlignment" Value="Bottom" />
<Setter Property="Margin" Value="0 0 0 1" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</StackPanel.Styles> </StackPanel.Styles>
<Grid> <Grid>
@ -31,12 +40,10 @@
<TextBlock Classes="h4" IsVisible="{Binding !IsNew}" Text="{Binding ProfileConfiguration.Name}" /> <TextBlock Classes="h4" IsVisible="{Binding !IsNew}" Text="{Binding ProfileConfiguration.Name}" />
</Grid> </Grid>
<TextBlock Classes="h5">General</TextBlock>
<Border Classes="card" Margin="0 0 0 15"> <Border Classes="card" Margin="0 0 0 15">
<StackPanel> <StackPanel>
<TextBlock Classes="label">Profile name</TextBlock> <TextBlock Classes="label">Profile name</TextBlock>
<TextBox Text="{Binding ProfileName}" /> <TextBox Watermark="Name" Text="{Binding ProfileName}" />
<TextBlock Classes="label">Module</TextBlock> <TextBlock Classes="label">Module</TextBlock>
<ComboBox SelectedItem="{Binding SelectedModule}" IsEnabled="{Binding Modules.Count}" Items="{Binding Modules}" HorizontalAlignment="Stretch"> <ComboBox SelectedItem="{Binding SelectedModule}" IsEnabled="{Binding Modules.Count}" Items="{Binding Modules}" HorizontalAlignment="Stretch">
<ComboBox.ItemsPanel> <ComboBox.ItemsPanel>
@ -71,7 +78,7 @@
<TextBlock Classes="label">Icon</TextBlock> <TextBlock Classes="label">Icon</TextBlock>
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
IsVisible="{Binding IconType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationIconType.BitmapImage}}"> IsVisible="{Binding IconType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationIconType.BitmapImage}}">
<Border Background="{DynamicResource CheckerboardBrush}" CornerRadius="{DynamicResource CardCornerRadius}" Width="98" Height="98"> <Border Background="{DynamicResource CheckerboardBrush}" CornerRadius="{DynamicResource CardCornerRadius}" Width="78" Height="78">
<Image Source="{Binding SelectedBitmapSource}" Margin="10" /> <Image Source="{Binding SelectedBitmapSource}" Margin="10" />
</Border> </Border>
<Button Command="{Binding BrowseBitmapFile}" <Button Command="{Binding BrowseBitmapFile}"
@ -83,7 +90,7 @@
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
IsVisible="{Binding IconType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationIconType.SvgImage}}"> IsVisible="{Binding IconType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationIconType.SvgImage}}">
<Border Background="{DynamicResource CheckerboardBrush}" CornerRadius="{DynamicResource CardCornerRadius}" Width="98" Height="98"> <Border Background="{DynamicResource CheckerboardBrush}" CornerRadius="{DynamicResource CardCornerRadius}" Width="78" Height="78">
<Image Margin="10" Source="{Binding SelectedSvgSource}" /> <Image Margin="10" Source="{Binding SelectedSvgSource}" />
</Border> </Border>
<Button Command="{Binding BrowseSvgFile}" <Button Command="{Binding BrowseSvgFile}"
@ -95,8 +102,8 @@
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
IsVisible="{Binding IconType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationIconType.MaterialIcon}}"> IsVisible="{Binding IconType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationIconType.MaterialIcon}}">
<Border Background="{DynamicResource CheckerboardBrush}" CornerRadius="{DynamicResource CardCornerRadius}" Width="98" Height="98"> <Border Background="{DynamicResource CheckerboardBrush}" CornerRadius="{DynamicResource CardCornerRadius}" Width="78" Height="78">
<avalonia:MaterialIcon Kind="{Binding SelectedMaterialIcon.Icon}" Width="65" Height="65" /> <avalonia:MaterialIcon Kind="{Binding SelectedMaterialIcon.Icon}" Width="45" Height="45" />
</Border> </Border>
<ComboBox Items="{Binding MaterialIcons}" <ComboBox Items="{Binding MaterialIcons}"
SelectedItem="{Binding SelectedMaterialIcon}" SelectedItem="{Binding SelectedMaterialIcon}"
@ -124,16 +131,44 @@
</StackPanel> </StackPanel>
</Border> </Border>
<TextBlock Classes="h5">Keybindings</TextBlock> <StackPanel Orientation="Horizontal">
<TextBlock Classes="subtitle">You may set up hotkeys to activate/deactivate the profile</TextBlock> <TextBlock Classes="h5 section-header">Keybindings</TextBlock>
<TextBlock Classes="subtitle section-subtitle">You may set up hotkeys to activate/deactivate the profile</TextBlock>
</StackPanel>
<Border Classes="card" Margin="0 5 0 15"> <Border Classes="card" Margin="0 5 0 15">
<TextBlock>TODO</TextBlock> <StackPanel>
<TextBlock>Hotkey mode</TextBlock>
<WrapPanel Orientation="Horizontal">
<RadioButton Content="None"
IsChecked="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.None}}" />
<RadioButton Content="Toggle"
IsChecked="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.Toggle}}" />
<RadioButton Content="Separate enable/disable"
IsChecked="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.EnableDisable}}" />
</WrapPanel>
<controls:HotkeyBox Watermark="Toggle hotkey"
Hotkey="{Binding EnableHotkey}"
IsVisible="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.Toggle}}"
HorizontalAlignment="Left"
Width="200"
Margin="0 5 0 0"/>
<StackPanel Orientation="Horizontal"
IsVisible="{Binding HotkeyMode, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static core:ProfileConfigurationHotkeyMode.EnableDisable}}"
HorizontalAlignment="Left"
Margin="0 5 0 0">
<controls:HotkeyBox Watermark="Enable hotkey" Hotkey="{Binding EnableHotkey}" Margin="0 0 4 0" Width="200"/>
<controls:HotkeyBox Watermark="Disable hotkey" Hotkey="{Binding DisableHotkey}" Margin="4 0 0 0" Width="200"/>
</StackPanel>
</StackPanel>
</Border> </Border>
<TextBlock Classes="h5">Activation conditions</TextBlock> <StackPanel Orientation="Horizontal">
<TextBlock Classes="subtitle">If you only want this profile to be active under certain conditions, configure those conditions below</TextBlock> <TextBlock Classes="h5 section-header">Activation conditions</TextBlock>
<TextBlock Classes="subtitle section-subtitle">Set up certain conditions under which the profile should be active</TextBlock>
</StackPanel>
<Border Classes="card" Margin="0 5 0 15"> <Border Classes="card" Margin="0 5 0 15">
<TextBlock>TODO</TextBlock> <TextBlock TextWrapping="Wrap">Here you'll find the node editor layer at some point, use your imagination for now.</TextBlock>
</Border> </Border>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>

View File

@ -1,9 +1,8 @@
using Avalonia; using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Root.Sidebar.Dialogs namespace Artemis.UI.Screens.Sidebar.Dialogs
{ {
public partial class ProfileConfigurationEditView : ReactiveWindow<ProfileConfigurationEditViewModel> public partial class ProfileConfigurationEditView : ReactiveWindow<ProfileConfigurationEditViewModel>
{ {

View File

@ -11,12 +11,11 @@ using Artemis.UI.Shared.Services.Interfaces;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Svg.Skia; using Avalonia.Svg.Skia;
using Avalonia.Threading; using Avalonia.Threading;
using Castle.Core.Resource;
using Material.Icons; using Material.Icons;
using Newtonsoft.Json; using Newtonsoft.Json;
using ReactiveUI; using ReactiveUI;
namespace Artemis.UI.Screens.Root.Sidebar.Dialogs namespace Artemis.UI.Screens.Sidebar.Dialogs
{ {
public class ProfileConfigurationEditViewModel : DialogViewModelBase<bool> public class ProfileConfigurationEditViewModel : DialogViewModelBase<bool>
{ {
@ -24,6 +23,7 @@ namespace Artemis.UI.Screens.Root.Sidebar.Dialogs
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private readonly IWindowService _windowService; private readonly IWindowService _windowService;
private ProfileConfigurationIconType _iconType; private ProfileConfigurationIconType _iconType;
private ProfileConfigurationHotkeyMode _hotkeyMode;
private ObservableCollection<ProfileIconViewModel>? _materialIcons; private ObservableCollection<ProfileIconViewModel>? _materialIcons;
private ProfileConfiguration _profileConfiguration; private ProfileConfiguration _profileConfiguration;
private string _profileName; private string _profileName;
@ -32,6 +32,8 @@ namespace Artemis.UI.Screens.Root.Sidebar.Dialogs
private ProfileModuleViewModel? _selectedModule; private ProfileModuleViewModel? _selectedModule;
private string? _selectedIconPath; private string? _selectedIconPath;
private SvgImage? _selectedSvgSource; private SvgImage? _selectedSvgSource;
private Hotkey? _enableHotkey;
private Hotkey? _disableHotkey;
public ProfileConfigurationEditViewModel(ProfileCategory profileCategory, ProfileConfiguration? profileConfiguration, IWindowService windowService, public ProfileConfigurationEditViewModel(ProfileCategory profileCategory, ProfileConfiguration? profileConfiguration, IWindowService windowService,
IProfileService profileService, IPluginManagementService pluginManagementService) IProfileService profileService, IPluginManagementService pluginManagementService)
@ -42,6 +44,11 @@ namespace Artemis.UI.Screens.Root.Sidebar.Dialogs
_profileConfiguration = profileConfiguration ?? profileService.CreateProfileConfiguration(profileCategory, "New profile", Enum.GetValues<MaterialIconKind>().First().ToString()); _profileConfiguration = profileConfiguration ?? profileService.CreateProfileConfiguration(profileCategory, "New profile", Enum.GetValues<MaterialIconKind>().First().ToString());
_profileName = _profileConfiguration.Name; _profileName = _profileConfiguration.Name;
_iconType = _profileConfiguration.Icon.IconType; _iconType = _profileConfiguration.Icon.IconType;
_hotkeyMode = _profileConfiguration.HotkeyMode;
if (_profileConfiguration.EnableHotkey != null)
_enableHotkey = new Hotkey() {Key = _profileConfiguration.EnableHotkey.Key, Modifiers = profileConfiguration.EnableHotkey.Modifiers};
if (_profileConfiguration.DisableHotkey != null)
_disableHotkey = new Hotkey() {Key = _profileConfiguration.DisableHotkey.Key, Modifiers = profileConfiguration.DisableHotkey.Modifiers};
IsNew = profileConfiguration == null; IsNew = profileConfiguration == null;
DisplayName = IsNew ? "Artemis | Add profile" : "Artemis | Edit profile"; DisplayName = IsNew ? "Artemis | Add profile" : "Artemis | Edit profile";
@ -66,6 +73,24 @@ namespace Artemis.UI.Screens.Root.Sidebar.Dialogs
set => this.RaiseAndSetIfChanged(ref _profileName, value); set => this.RaiseAndSetIfChanged(ref _profileName, value);
} }
public ProfileConfigurationHotkeyMode HotkeyMode
{
get => _hotkeyMode;
set => this.RaiseAndSetIfChanged(ref _hotkeyMode, value);
}
public Hotkey? EnableHotkey
{
get => _enableHotkey;
set => this.RaiseAndSetIfChanged(ref _enableHotkey, value);
}
public Hotkey? DisableHotkey
{
get => _disableHotkey;
set => this.RaiseAndSetIfChanged(ref _disableHotkey, value);
}
public ObservableCollection<ProfileModuleViewModel> Modules { get; } public ObservableCollection<ProfileModuleViewModel> Modules { get; }
public ProfileModuleViewModel? SelectedModule public ProfileModuleViewModel? SelectedModule
@ -126,6 +151,10 @@ namespace Artemis.UI.Screens.Root.Sidebar.Dialogs
{ {
ProfileConfiguration.Name = ProfileName; ProfileConfiguration.Name = ProfileName;
ProfileConfiguration.Module = SelectedModule?.Module; ProfileConfiguration.Module = SelectedModule?.Module;
ProfileConfiguration.HotkeyMode = HotkeyMode;
ProfileConfiguration.EnableHotkey = EnableHotkey;
ProfileConfiguration.DisableHotkey = DisableHotkey;
await SaveIcon(); await SaveIcon();
_profileService.SaveProfileConfigurationIcon(ProfileConfiguration); _profileService.SaveProfileConfigurationIcon(ProfileConfiguration);

View File

@ -1,7 +1,7 @@
using Artemis.UI.Shared; using Artemis.UI.Shared;
using Material.Icons; using Material.Icons;
namespace Artemis.UI.Screens.Root.Sidebar.Dialogs namespace Artemis.UI.Screens.Sidebar.Dialogs
{ {
public class ProfileIconViewModel : ViewModelBase public class ProfileIconViewModel : ViewModelBase
{ {

View File

@ -2,7 +2,7 @@
using Artemis.UI.Shared; using Artemis.UI.Shared;
using Material.Icons; using Material.Icons;
namespace Artemis.UI.Screens.Root.Sidebar.Dialogs namespace Artemis.UI.Screens.Sidebar.Dialogs
{ {
public class ProfileModuleViewModel : ViewModelBase public class ProfileModuleViewModel : ViewModelBase
{ {

View File

@ -3,10 +3,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:local="clr-namespace:Artemis.UI.Screens.Root.Sidebar"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared" xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:local="clr-namespace:Artemis.UI.Screens.Sidebar"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Root.Sidebar.SidebarCategoryView"> x:Class="Artemis.UI.Screens.Sidebar.SidebarCategoryView">
<UserControl.Styles> <UserControl.Styles>
<Style Selector=":is(Button).category-button"> <Style Selector=":is(Button).category-button">
<Setter Property="IsVisible" Value="False" /> <Setter Property="IsVisible" Value="False" />

View File

@ -2,7 +2,7 @@
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Root.Sidebar namespace Artemis.UI.Screens.Sidebar
{ {
public class SidebarCategoryView : ReactiveUserControl<SidebarCategoryViewModel> public class SidebarCategoryView : ReactiveUserControl<SidebarCategoryViewModel>
{ {

View File

@ -1,18 +1,21 @@
using System.Collections.ObjectModel; using System;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Reactive.Disposables;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Root.Sidebar.Dialogs; using Artemis.UI.Screens.Sidebar.ContentDialogs;
using Artemis.UI.Screens.Sidebar.Dialogs;
using Artemis.UI.Services;
using Artemis.UI.Shared; using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using ReactiveUI; using ReactiveUI;
namespace Artemis.UI.Screens.Sidebar
namespace Artemis.UI.Screens.Root.Sidebar
{ {
public class SidebarCategoryViewModel : ViewModelBase public class SidebarCategoryViewModel : ActivatableViewModelBase
{ {
private readonly SidebarViewModel _sidebarViewModel; private readonly SidebarViewModel _sidebarViewModel;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
@ -20,7 +23,7 @@ namespace Artemis.UI.Screens.Root.Sidebar
private readonly ISidebarVmFactory _vmFactory; private readonly ISidebarVmFactory _vmFactory;
private SidebarProfileConfigurationViewModel? _selectedProfileConfiguration; private SidebarProfileConfigurationViewModel? _selectedProfileConfiguration;
public SidebarCategoryViewModel(SidebarViewModel sidebarViewModel, ProfileCategory profileCategory, IProfileService profileService, IWindowService windowService, ISidebarVmFactory vmFactory) public SidebarCategoryViewModel(SidebarViewModel sidebarViewModel, ProfileCategory profileCategory, IProfileService profileService, IWindowService windowService, IProfileEditorService profileEditorService, ISidebarVmFactory vmFactory)
{ {
_sidebarViewModel = sidebarViewModel; _sidebarViewModel = sidebarViewModel;
_profileService = profileService; _profileService = profileService;
@ -31,6 +34,16 @@ namespace Artemis.UI.Screens.Root.Sidebar
if (ShowItems) if (ShowItems)
CreateProfileViewModels(); CreateProfileViewModels();
this.WhenActivated(disposables =>
{
profileEditorService.CurrentProfileConfiguration
.Subscribe(p => SelectedProfileConfiguration = ProfileConfigurations.FirstOrDefault(c => ReferenceEquals(c.ProfileConfiguration, p)))
.DisposeWith(disposables);
this.WhenAnyValue(vm => vm.SelectedProfileConfiguration)
.WhereNotNull()
.Subscribe(s => profileEditorService.ChangeCurrentProfileConfiguration(s.ProfileConfiguration));
});
} }
public ProfileCategory ProfileCategory { get; } public ProfileCategory ProfileCategory { get; }

View File

@ -6,7 +6,7 @@
xmlns:converters="clr-namespace:Artemis.UI.Converters" xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared" xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Root.Sidebar.SidebarProfileConfigurationView"> x:Class="Artemis.UI.Screens.Sidebar.SidebarProfileConfigurationView">
<UserControl.Resources> <UserControl.Resources>
<converters:ValuesAdditionConverter x:Key="ValuesAddition" /> <converters:ValuesAdditionConverter x:Key="ValuesAddition" />
</UserControl.Resources> </UserControl.Resources>

View File

@ -1,7 +1,7 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.Root.Sidebar namespace Artemis.UI.Screens.Sidebar
{ {
public class SidebarProfileConfigurationView : UserControl public class SidebarProfileConfigurationView : UserControl
{ {

View File

@ -1,11 +1,11 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Screens.Root.Sidebar.Dialogs; using Artemis.UI.Screens.Sidebar.Dialogs;
using Artemis.UI.Shared; using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Screens.Root.Sidebar namespace Artemis.UI.Screens.Sidebar
{ {
public class SidebarProfileConfigurationViewModel : ViewModelBase public class SidebarProfileConfigurationViewModel : ViewModelBase
{ {

View File

@ -4,7 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Root.Sidebar.SidebarScreenView"> x:Class="Artemis.UI.Screens.Sidebar.SidebarScreenView">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<avalonia:MaterialIcon Kind="{Binding Icon}" Width="16" Height="16" /> <avalonia:MaterialIcon Kind="{Binding Icon}" Width="16" Height="16" />
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="{Binding DisplayName}" /> <TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="{Binding DisplayName}" />

View File

@ -1,7 +1,7 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.Root.Sidebar namespace Artemis.UI.Screens.Sidebar
{ {
public partial class SidebarScreenView : UserControl public partial class SidebarScreenView : UserControl
{ {

View File

@ -5,7 +5,7 @@ using Ninject;
using Ninject.Parameters; using Ninject.Parameters;
using ReactiveUI; using ReactiveUI;
namespace Artemis.UI.Screens.Root.Sidebar namespace Artemis.UI.Screens.Sidebar
{ {
public class SidebarScreenViewModel<T> : SidebarScreenViewModel where T : MainScreenViewModel public class SidebarScreenViewModel<T> : SidebarScreenViewModel where T : MainScreenViewModel
{ {

View File

@ -6,7 +6,7 @@
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:svg="clr-namespace:Avalonia.Svg.Skia;assembly=Avalonia.Svg.Skia" xmlns:svg="clr-namespace:Avalonia.Svg.Skia;assembly=Avalonia.Svg.Skia"
mc:Ignorable="d" d:DesignWidth="240" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="240" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Root.Sidebar.SidebarView"> x:Class="Artemis.UI.Screens.Sidebar.SidebarView">
<Grid RowDefinitions="60,Auto,Auto,*,Auto,Auto"> <Grid RowDefinitions="60,Auto,Auto,*,Auto,Auto">
<Grid Grid.Row="0" IsHitTestVisible="False" ColumnDefinitions="Auto,*"> <Grid Grid.Row="0" IsHitTestVisible="False" ColumnDefinitions="Auto,*">
<Image Grid.Column="0"> <Image Grid.Column="0">

View File

@ -1,7 +1,7 @@
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Root.Sidebar namespace Artemis.UI.Screens.Sidebar
{ {
public class SidebarView : ReactiveUserControl<SidebarViewModel> public class SidebarView : ReactiveUserControl<SidebarViewModel>
{ {

View File

@ -2,15 +2,18 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Reactive.Disposables; using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Home; using Artemis.UI.Screens.Home;
using Artemis.UI.Screens.Root.Sidebar.Dialogs; using Artemis.UI.Screens.ProfileEditor;
using Artemis.UI.Screens.Settings; using Artemis.UI.Screens.Settings;
using Artemis.UI.Screens.Sidebar.ContentDialogs;
using Artemis.UI.Screens.SurfaceEditor; using Artemis.UI.Screens.SurfaceEditor;
using Artemis.UI.Screens.Workshop; using Artemis.UI.Screens.Workshop;
using Artemis.UI.Services;
using Artemis.UI.Shared; using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
@ -19,7 +22,7 @@ using Ninject;
using ReactiveUI; using ReactiveUI;
using RGB.NET.Core; using RGB.NET.Core;
namespace Artemis.UI.Screens.Root.Sidebar namespace Artemis.UI.Screens.Sidebar
{ {
public class SidebarViewModel : ActivatableViewModelBase public class SidebarViewModel : ActivatableViewModelBase
{ {
@ -28,17 +31,21 @@ namespace Artemis.UI.Screens.Root.Sidebar
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly ISidebarVmFactory _sidebarVmFactory; private readonly ISidebarVmFactory _sidebarVmFactory;
private readonly IWindowService _windowService; private readonly IWindowService _windowService;
private readonly IProfileEditorService _profileEditorService;
private ArtemisDevice? _headerDevice; private ArtemisDevice? _headerDevice;
private SidebarScreenViewModel? _selectedSidebarScreen; private SidebarScreenViewModel? _selectedSidebarScreen;
public SidebarViewModel(IScreen hostScreen, IKernel kernel, IProfileService profileService, IRgbService rgbService, ISidebarVmFactory sidebarVmFactory, IWindowService windowService)
public SidebarViewModel(IScreen hostScreen, IKernel kernel, IProfileService profileService, IRgbService rgbService, IWindowService windowService,
IProfileEditorService profileEditorService, ISidebarVmFactory sidebarVmFactory, IProfileEditorVmFactory profileEditorVmFactory)
{ {
_hostScreen = hostScreen; _hostScreen = hostScreen;
_profileService = profileService; _profileService = profileService;
_rgbService = rgbService; _rgbService = rgbService;
_sidebarVmFactory = sidebarVmFactory;
_windowService = windowService; _windowService = windowService;
_profileEditorService = profileEditorService;
_sidebarVmFactory = sidebarVmFactory;
SidebarScreens = new ObservableCollection<SidebarScreenViewModel> SidebarScreens = new ObservableCollection<SidebarScreenViewModel>
{ {
@ -58,9 +65,23 @@ namespace Artemis.UI.Screens.Root.Sidebar
.WhereNotNull() .WhereNotNull()
.Subscribe(c => SelectedSidebarScreen = SidebarScreens.FirstOrDefault(s => s.ScreenType == c.GetType())) .Subscribe(c => SelectedSidebarScreen = SidebarScreens.FirstOrDefault(s => s.ScreenType == c.GetType()))
.DisposeWith(disposables); .DisposeWith(disposables);
this.WhenAnyValue(vm => vm.SelectedSidebarScreen) this.WhenAnyValue(vm => vm.SelectedSidebarScreen)
.WhereNotNull() .WhereNotNull()
.Subscribe(s => _hostScreen.Router.Navigate.Execute(s.CreateInstance(kernel, _hostScreen))); .Subscribe(s =>
{
_hostScreen.Router.Navigate.Execute(s.CreateInstance(kernel, _hostScreen));
profileEditorService.ChangeCurrentProfileConfiguration(null);
});
this.WhenAnyObservable(vm => vm._profileEditorService.CurrentProfileConfiguration)
.WhereNotNull()
.Subscribe(_ =>
{
if (_hostScreen.Router.GetCurrentViewModel() is not ProfileEditorViewModel)
_hostScreen.Router.Navigate.Execute(profileEditorVmFactory.ProfileEditorViewModel(_hostScreen));
})
.DisposeWith(disposables);
}); });
} }
@ -92,7 +113,7 @@ namespace Artemis.UI.Screens.Root.Sidebar
.WithTitle("Add new category") .WithTitle("Add new category")
.WithViewModel<SidebarCategoryEditViewModel>(out var vm, ("category", null)) .WithViewModel<SidebarCategoryEditViewModel>(out var vm, ("category", null))
.HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Confirm)) .HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Confirm))
.WithCloseButtonText("Cancel") .WithCloseButtonText("Cancel")
.WithDefaultButton(ContentDialogButton.Primary) .WithDefaultButton(ContentDialogButton.Primary)
.ShowAsync(); .ShowAsync();

View File

@ -0,0 +1,51 @@
using System;
using System.Diagnostics;
using System.Reactive.Linq;
using Artemis.Core;
using Artemis.UI.Services.Interfaces;
using ReactiveUI;
namespace Artemis.UI.Services
{
public class ProfileEditorService : IProfileEditorService
{
private readonly ReactiveCommand<ProfileConfiguration?, ProfileConfiguration?> _changeCurrentProfileConfiguration;
private readonly ReactiveCommand<RenderProfileElement?, RenderProfileElement?> _changeCurrentProfileElement;
private ProfileConfiguration? _currentProfileConfiguration;
private RenderProfileElement? _currentProfileElement;
public ProfileEditorService()
{
_changeCurrentProfileConfiguration = ReactiveCommand.CreateFromObservable<ProfileConfiguration?, ProfileConfiguration?>(Observable.Return);
_changeCurrentProfileElement = ReactiveCommand.CreateFromObservable<RenderProfileElement?, RenderProfileElement?>(Observable.Return);
CurrentProfileConfiguration = Observable.Defer(() => Observable.Return(_currentProfileConfiguration)).Concat(_changeCurrentProfileConfiguration);
CurrentProfileElement = Observable.Defer(() => Observable.Return(_currentProfileElement)).Concat(_changeCurrentProfileElement);
}
public IObservable<ProfileConfiguration?> CurrentProfileConfiguration { get; }
public IObservable<RenderProfileElement?> CurrentProfileElement { get; }
public void ChangeCurrentProfileConfiguration(ProfileConfiguration? profileConfiguration)
{
_currentProfileConfiguration = profileConfiguration;
_changeCurrentProfileConfiguration.Execute(profileConfiguration).Subscribe();
}
public void ChangeCurrentProfileElement(RenderProfileElement? renderProfileElement)
{
_currentProfileElement = renderProfileElement;
_changeCurrentProfileElement.Execute(renderProfileElement).Subscribe();
}
}
public interface IProfileEditorService : IArtemisUIService
{
IObservable<ProfileConfiguration?> CurrentProfileConfiguration { get; }
IObservable<RenderProfileElement?> CurrentProfileElement { get; }
void ChangeCurrentProfileConfiguration(ProfileConfiguration? profileConfiguration);
void ChangeCurrentProfileElement(RenderProfileElement? renderProfileElement);
}
}