mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
257 lines
9.8 KiB
C#
257 lines
9.8 KiB
C#
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reactive;
|
|
using System.Reactive.Linq;
|
|
using System.Threading.Tasks;
|
|
using Artemis.Core;
|
|
using Artemis.Core.Modules;
|
|
using Artemis.Core.Services;
|
|
using Artemis.UI.DryIoc.Factories;
|
|
using Artemis.UI.Screens.VisualScripting;
|
|
using Artemis.UI.Shared;
|
|
using Artemis.UI.Shared.Services;
|
|
using Artemis.UI.Shared.Services.ProfileEditor;
|
|
using Avalonia.Media.Imaging;
|
|
using Avalonia.Threading;
|
|
using Material.Icons;
|
|
using ReactiveUI;
|
|
|
|
namespace Artemis.UI.Screens.Sidebar;
|
|
|
|
public class ProfileConfigurationEditViewModel : DialogViewModelBase<ProfileConfiguration?>
|
|
{
|
|
private readonly ObservableAsPropertyHelper<ModuleActivationRequirementsViewModel?> _moduleActivationRequirementsViewModel;
|
|
private readonly ProfileCategory _profileCategory;
|
|
private readonly IProfileEditorService _profileEditorService;
|
|
private readonly IProfileService _profileService;
|
|
private readonly IWindowService _windowService;
|
|
private Hotkey? _disableHotkey;
|
|
private Hotkey? _enableHotkey;
|
|
private bool _fadeInAndOut;
|
|
private ProfileConfigurationHotkeyMode _hotkeyMode;
|
|
private ProfileConfigurationIconType _iconType;
|
|
private ProfileConfiguration _profileConfiguration;
|
|
private string _profileName;
|
|
private Bitmap? _selectedBitmapSource;
|
|
private string? _selectedIconPath;
|
|
private ProfileIconViewModel? _selectedMaterialIcon;
|
|
private ProfileModuleViewModel? _selectedModule;
|
|
|
|
public ProfileConfigurationEditViewModel(
|
|
ProfileCategory profileCategory,
|
|
ProfileConfiguration profileConfiguration,
|
|
IWindowService windowService,
|
|
IProfileService profileService,
|
|
IProfileEditorService profileEditorService,
|
|
IPluginManagementService pluginManagementService,
|
|
INodeVmFactory nodeVmFactory)
|
|
{
|
|
_profileCategory = profileCategory;
|
|
_windowService = windowService;
|
|
_profileService = profileService;
|
|
_profileEditorService = profileEditorService;
|
|
|
|
_profileConfiguration = profileConfiguration == ProfileConfiguration.Empty
|
|
? profileService.CreateProfileConfiguration(profileCategory, "New profile", Enum.GetValues<MaterialIconKind>().First().ToString())
|
|
: profileConfiguration;
|
|
_profileName = _profileConfiguration.Name;
|
|
_iconType = _profileConfiguration.Icon.IconType;
|
|
_hotkeyMode = _profileConfiguration.HotkeyMode;
|
|
_fadeInAndOut = _profileConfiguration.FadeInAndOut;
|
|
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 == ProfileConfiguration.Empty;
|
|
DisplayName = IsNew ? "Artemis | Add profile" : "Artemis | Edit profile properties";
|
|
Modules = new ObservableCollection<ProfileModuleViewModel?>(pluginManagementService.GetFeaturesOfType<Module>().Where(m => !m.IsAlwaysAvailable).Select(m => new ProfileModuleViewModel(m)));
|
|
Modules.Insert(0, null);
|
|
_selectedModule = Modules.FirstOrDefault(m => m?.Module == _profileConfiguration.Module);
|
|
|
|
VisualEditorViewModel = nodeVmFactory.NodeScriptViewModel(_profileConfiguration.ActivationCondition, true);
|
|
|
|
BrowseBitmapFile = ReactiveCommand.CreateFromTask(ExecuteBrowseBitmapFile);
|
|
OpenConditionEditor = ReactiveCommand.CreateFromTask(ExecuteOpenConditionEditor);
|
|
Confirm = ReactiveCommand.CreateFromTask(ExecuteConfirm);
|
|
Delete = ReactiveCommand.CreateFromTask(ExecuteDelete);
|
|
Cancel = ReactiveCommand.Create(ExecuteCancel);
|
|
|
|
_moduleActivationRequirementsViewModel = this.WhenAnyValue(vm => vm.SelectedModule)
|
|
.Select(m => m != null ? new ModuleActivationRequirementsViewModel(m.Module) : null)
|
|
.ToProperty(this, vm => vm.ModuleActivationRequirementsViewModel);
|
|
|
|
Dispatcher.UIThread.Post(LoadIcon, DispatcherPriority.Background);
|
|
}
|
|
|
|
public bool IsNew { get; }
|
|
|
|
public ProfileConfiguration ProfileConfiguration
|
|
{
|
|
get => _profileConfiguration;
|
|
set => RaiseAndSetIfChanged(ref _profileConfiguration, value);
|
|
}
|
|
|
|
public string ProfileName
|
|
{
|
|
get => _profileName;
|
|
set => RaiseAndSetIfChanged(ref _profileName, value);
|
|
}
|
|
|
|
public ProfileConfigurationHotkeyMode HotkeyMode
|
|
{
|
|
get => _hotkeyMode;
|
|
set => RaiseAndSetIfChanged(ref _hotkeyMode, value);
|
|
}
|
|
|
|
public Hotkey? EnableHotkey
|
|
{
|
|
get => _enableHotkey;
|
|
set => RaiseAndSetIfChanged(ref _enableHotkey, value);
|
|
}
|
|
|
|
public Hotkey? DisableHotkey
|
|
{
|
|
get => _disableHotkey;
|
|
set => RaiseAndSetIfChanged(ref _disableHotkey, value);
|
|
}
|
|
|
|
public bool FadeInAndOut
|
|
{
|
|
get => _fadeInAndOut;
|
|
set => RaiseAndSetIfChanged(ref _fadeInAndOut, value);
|
|
}
|
|
|
|
public ObservableCollection<ProfileModuleViewModel?> Modules { get; }
|
|
|
|
public ProfileModuleViewModel? SelectedModule
|
|
{
|
|
get => _selectedModule;
|
|
set => RaiseAndSetIfChanged(ref _selectedModule, value);
|
|
}
|
|
|
|
public NodeScriptViewModel VisualEditorViewModel { get; }
|
|
public ModuleActivationRequirementsViewModel? ModuleActivationRequirementsViewModel => _moduleActivationRequirementsViewModel.Value;
|
|
|
|
public ReactiveCommand<Unit, Unit> OpenConditionEditor { get; }
|
|
public ReactiveCommand<Unit, Unit> BrowseBitmapFile { get; }
|
|
public ReactiveCommand<Unit, Unit> Confirm { get; }
|
|
public ReactiveCommand<Unit, Unit> Delete { get; }
|
|
public ReactiveCommand<Unit, Unit> Cancel { get; }
|
|
|
|
private async Task ExecuteDelete()
|
|
{
|
|
if (IsNew)
|
|
return;
|
|
if (!await _windowService.ShowConfirmContentDialog("Delete profile", "Are you sure you want to permanently delete this profile?"))
|
|
return;
|
|
|
|
if (_profileConfiguration.IsBeingEdited)
|
|
_profileEditorService.ChangeCurrentProfileConfiguration(null);
|
|
_profileService.RemoveProfileConfiguration(_profileConfiguration);
|
|
Close(_profileConfiguration);
|
|
}
|
|
|
|
private async Task ExecuteConfirm()
|
|
{
|
|
ProfileConfiguration.Name = ProfileName;
|
|
ProfileConfiguration.Module = SelectedModule?.Module;
|
|
ProfileConfiguration.HotkeyMode = HotkeyMode;
|
|
ProfileConfiguration.EnableHotkey = EnableHotkey;
|
|
ProfileConfiguration.DisableHotkey = DisableHotkey;
|
|
ProfileConfiguration.FadeInAndOut = FadeInAndOut;
|
|
|
|
await SaveIcon();
|
|
|
|
_profileService.SaveProfileConfigurationIcon(ProfileConfiguration);
|
|
_profileService.SaveProfileCategory(_profileCategory);
|
|
Close(ProfileConfiguration);
|
|
}
|
|
|
|
private void ExecuteCancel()
|
|
{
|
|
if (IsNew)
|
|
_profileService.RemoveProfileConfiguration(_profileConfiguration);
|
|
Close(null);
|
|
}
|
|
|
|
#region Icon
|
|
|
|
public ProfileConfigurationIconType IconType
|
|
{
|
|
get => _iconType;
|
|
set => RaiseAndSetIfChanged(ref _iconType, value);
|
|
}
|
|
|
|
public ProfileIconViewModel? SelectedMaterialIcon
|
|
{
|
|
get => _selectedMaterialIcon;
|
|
set => RaiseAndSetIfChanged(ref _selectedMaterialIcon, value);
|
|
}
|
|
|
|
public Bitmap? SelectedBitmapSource
|
|
{
|
|
get => _selectedBitmapSource;
|
|
set => RaiseAndSetIfChanged(ref _selectedBitmapSource, value);
|
|
}
|
|
|
|
private void LoadIcon()
|
|
{
|
|
// Preselect the icon based on streams if needed
|
|
if (_profileConfiguration.Icon.IconType == ProfileConfigurationIconType.BitmapImage)
|
|
try
|
|
{
|
|
SelectedBitmapSource = new Bitmap(_profileConfiguration.Icon.GetIconStream());
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_windowService.ShowConfirmContentDialog("Failed to load profile icon", e.Message, "Meh", null);
|
|
}
|
|
|
|
// Prepare the contents of the dropdown box, it should be virtualized so no need to wait with this
|
|
ObservableCollection<ProfileIconViewModel> icons = new(Enum.GetValues<MaterialIconKind>()
|
|
.Select(kind => new ProfileIconViewModel(kind))
|
|
.DistinctBy(vm => vm.DisplayName)
|
|
.OrderBy(vm => vm.DisplayName));
|
|
|
|
// Preselect the icon or fall back to a random one
|
|
SelectedMaterialIcon = !IsNew && Enum.TryParse(_profileConfiguration.Icon.IconName, out MaterialIconKind enumValue)
|
|
? icons.FirstOrDefault(m => m.Icon == enumValue)
|
|
: icons.ElementAt(new Random().Next(0, icons.Count - 1));
|
|
}
|
|
|
|
private async Task SaveIcon()
|
|
{
|
|
if (IconType == ProfileConfigurationIconType.MaterialIcon && SelectedMaterialIcon != null)
|
|
{
|
|
ProfileConfiguration.Icon.SetIconByName(SelectedMaterialIcon.Icon.ToString());
|
|
}
|
|
else if (_selectedIconPath != null)
|
|
{
|
|
await using FileStream fileStream = File.OpenRead(_selectedIconPath);
|
|
ProfileConfiguration.Icon.SetIconByStream(Path.GetFileName(_selectedIconPath), fileStream);
|
|
}
|
|
}
|
|
|
|
private async Task ExecuteBrowseBitmapFile()
|
|
{
|
|
string[]? result = await _windowService.CreateOpenFileDialog()
|
|
.HavingFilter(f => f.WithExtension("png").WithExtension("jpg").WithExtension("bmp").WithName("Bitmap image"))
|
|
.ShowAsync();
|
|
|
|
if (result == null)
|
|
return;
|
|
|
|
SelectedBitmapSource = new Bitmap(result[0]);
|
|
_selectedIconPath = result[0];
|
|
}
|
|
|
|
private async Task ExecuteOpenConditionEditor()
|
|
{
|
|
await _windowService.ShowDialogAsync<NodeScriptWindowViewModel, bool>(ProfileConfiguration.ActivationCondition);
|
|
}
|
|
|
|
#endregion
|
|
} |