From 192b4f0df29156df2d355db04d993f416758b610 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 19 Apr 2023 16:03:57 +0200 Subject: [PATCH] UI - Rename folders and layers in a dialog to avoid hotkey issues UI - Fixed renaming an effect executing twice, requiring two undo-actions to undo it UI - Always disable editor hotkeys when typing in any input --- .../ProfileEditor/IProfileEditorService.cs | 11 ---- .../ProfileEditor/ProfileEditorService.cs | 13 +---- src/Artemis.UI.Shared/Utilities.cs | 39 ++++++++++++- .../Panels/MenuBar/MenuBarViewModel.cs | 2 +- .../Panels/Playback/PlaybackViewModel.cs | 2 +- .../ProfileElementRenameView.axaml | 15 +++++ .../ProfileElementRenameView.axaml.cs | 31 ++++++++++ .../ProfileElementRenameViewModel.cs | 47 ++++++++++++++++ .../ProfileTree/FolderTreeItemView.axaml | 11 +--- .../ProfileTree/FolderTreeItemView.axaml.cs | 28 ---------- .../ProfileTree/LayerTreeItemView.axaml | 11 +--- .../ProfileTree/LayerTreeItemView.axaml.cs | 28 ---------- .../ProfileTree/ProfileTreeViewModel.cs | 2 +- .../Panels/ProfileTree/TreeItemViewModel.cs | 56 ++++++------------- .../LayerEffectRenameView.axaml | 2 +- .../LayerEffectRenameView.axaml.cs | 1 - .../LayerEffectRenameViewModel.cs | 2 + .../SidebarCategoryEditView.axaml | 2 +- .../SidebarCategoryEditViewModel.cs | 2 + .../NodeScriptWindowViewModel.cs | 8 ++- 20 files changed, 166 insertions(+), 147 deletions(-) create mode 100644 src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameView.axaml create mode 100644 src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameView.axaml.cs create mode 100644 src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameViewModel.cs diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/IProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/IProfileEditorService.cs index 82a217a99..e766659c6 100644 --- a/src/Artemis.UI.Shared/Services/ProfileEditor/IProfileEditorService.cs +++ b/src/Artemis.UI.Shared/Services/ProfileEditor/IProfileEditorService.cs @@ -51,11 +51,6 @@ public interface IProfileEditorService : IArtemisSharedUIService /// IObservable SuspendedEditing { get; } - /// - /// Gets an observable of the suspended keybindings state. - /// - IObservable SuspendedKeybindings { get; } - /// /// Gets an observable of the suspended keybindings state. /// @@ -102,12 +97,6 @@ public interface IProfileEditorService : IArtemisSharedUIService /// The new suspended state. void ChangeSuspendedEditing(bool suspend); - /// - /// Changes the current suspended keybindings state. - /// - /// The new suspended state. - void ChangeSuspendedKeybindings(bool suspend); - /// /// Changes the current focus mode. /// diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs index d02f99dcc..270798b89 100644 --- a/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs +++ b/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs @@ -31,7 +31,6 @@ internal class ProfileEditorService : IProfileEditorService private readonly IRgbService _rgbService; private readonly SourceList _selectedKeyframes; private readonly BehaviorSubject _suspendedEditingSubject = new(false); - private readonly BehaviorSubject _suspendedKeybindingsSubject = new(false); private readonly BehaviorSubject _timeSubject = new(TimeSpan.Zero); private readonly IWindowService _windowService; private ProfileEditorCommandScope? _profileEditorHistoryScope; @@ -61,7 +60,6 @@ internal class ProfileEditorService : IProfileEditorService Time = _timeSubject.AsObservable(); Playing = _playingSubject.AsObservable(); SuspendedEditing = _suspendedEditingSubject.AsObservable(); - SuspendedKeybindings = _suspendedKeybindingsSubject.AsObservable(); PixelsPerSecond = _pixelsPerSecondSubject.AsObservable(); FocusMode = _focusModeSubject.AsObservable(); SelectedKeyframes = selectedKeyframes; @@ -210,7 +208,6 @@ internal class ProfileEditorService : IProfileEditorService _profileConfigurationSubject.OnNext(profileConfiguration); ChangeTime(TimeSpan.Zero); - ChangeSuspendedKeybindings(false); } public void ChangeCurrentProfileElement(RenderProfileElement? renderProfileElement) @@ -255,15 +252,7 @@ internal class ProfileEditorService : IProfileEditorService ApplyFocusMode(); } - - public void ChangeSuspendedKeybindings(bool suspend) - { - if (_suspendedKeybindingsSubject.Value == suspend) - return; - - _suspendedKeybindingsSubject.OnNext(suspend); - } - + public void ChangeFocusMode(ProfileEditorFocusMode focusMode) { if (_focusModeSubject.Value == focusMode) diff --git a/src/Artemis.UI.Shared/Utilities.cs b/src/Artemis.UI.Shared/Utilities.cs index 35abef7db..9428b183b 100644 --- a/src/Artemis.UI.Shared/Utilities.cs +++ b/src/Artemis.UI.Shared/Utilities.cs @@ -1,8 +1,43 @@ -using DryIoc; +using System; +using System.ComponentModel; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Avalonia.Controls; +using Avalonia.Input; +using IContainer = DryIoc.IContainer; namespace Artemis.UI.Shared; -internal static class UI +/// +/// Static UI helpers. +/// +public static class UI { + private static readonly BehaviorSubject KeyBindingsEnabledSubject = new(false); + + static UI() + { + if (KeyboardDevice.Instance != null) + KeyboardDevice.Instance.PropertyChanged += InstanceOnPropertyChanged; + } + + /// + /// Gets the current IoC locator. + /// public static IContainer Locator { get; set; } = null!; + + /// + /// Gets a boolean indicating whether hotkeys are to be disabled. + /// + public static IObservable KeyBindingsEnabled { get; } = KeyBindingsEnabledSubject.AsObservable(); + + private static void InstanceOnPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (KeyboardDevice.Instance == null || e.PropertyName != nameof(KeyboardDevice.FocusedElement)) + return; + + bool enabled = KeyboardDevice.Instance.FocusedElement is not TextBox; + if (KeyBindingsEnabledSubject.Value != enabled) + KeyBindingsEnabledSubject.OnNext(enabled); + } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs index b7cf96087..4d7247986 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarViewModel.cs @@ -58,7 +58,7 @@ public class MenuBarViewModel : ActivatableViewModelBase _focusNone = profileEditorService.FocusMode.Select(f => f == ProfileEditorFocusMode.None).ToProperty(this, vm => vm.FocusNone).DisposeWith(d); _focusFolder = profileEditorService.FocusMode.Select(f => f == ProfileEditorFocusMode.Folder).ToProperty(this, vm => vm.FocusFolder).DisposeWith(d); _focusSelection = profileEditorService.FocusMode.Select(f => f == ProfileEditorFocusMode.Selection).ToProperty(this, vm => vm.FocusSelection).DisposeWith(d); - _keyBindingsEnabled = profileEditorService.SuspendedKeybindings.Select(s => !s).ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); + _keyBindingsEnabled = Shared.UI.KeyBindingsEnabled.ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); }); AddFolder = ReactiveCommand.Create(ExecuteAddFolder); diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Playback/PlaybackViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Playback/PlaybackViewModel.cs index 376ddb92a..80039a4ba 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Playback/PlaybackViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Playback/PlaybackViewModel.cs @@ -52,7 +52,7 @@ public class PlaybackViewModel : ActivatableViewModelBase _currentTime = _profileEditorService.Time.ToProperty(this, vm => vm.CurrentTime).DisposeWith(d); _formattedCurrentTime = _profileEditorService.Time.Select(t => $"{Math.Floor(t.TotalSeconds):00}.{t.Milliseconds:000}").ToProperty(this, vm => vm.FormattedCurrentTime).DisposeWith(d); _playing = _profileEditorService.Playing.ToProperty(this, vm => vm.Playing).DisposeWith(d); - _keyBindingsEnabled = _profileEditorService.SuspendedKeybindings.Select(s => !s).ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); + _keyBindingsEnabled = Shared.UI.KeyBindingsEnabled.ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); _lastUpdate = DateTime.MinValue; DispatcherTimer updateTimer = new(TimeSpan.FromMilliseconds(60.0 / 1000), DispatcherPriority.Render, Update); diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameView.axaml new file mode 100644 index 000000000..d9a846e3e --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameView.axaml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameView.axaml.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameView.axaml.cs new file mode 100644 index 000000000..bdcc4c91f --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameView.axaml.cs @@ -0,0 +1,31 @@ +using System.Threading.Tasks; +using Artemis.UI.Shared.Extensions; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; +using Avalonia.Threading; +using ReactiveUI; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.ContentDialogs; + +public partial class ProfileElementRenameView : ReactiveUserControl +{ + public ProfileElementRenameView() + { + InitializeComponent(); + this.WhenActivated(_ => + { + this.ClearAllDataValidationErrors(); + Dispatcher.UIThread.Post(DelayedAutoFocus); + }); + } + + private async void DelayedAutoFocus() + { + // Don't ask + await Task.Delay(200); + NameTextBox.SelectAll(); + NameTextBox.Focus(); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameViewModel.cs new file mode 100644 index 000000000..26a07ff15 --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ContentDialogs/ProfileElementRenameViewModel.cs @@ -0,0 +1,47 @@ +using System.Reactive; +using Artemis.Core; +using Artemis.UI.Shared; +using Artemis.UI.Shared.Services.ProfileEditor; +using Artemis.UI.Shared.Services.ProfileEditor.Commands; +using FluentAvalonia.UI.Controls; +using ReactiveUI; +using ReactiveUI.Validation.Extensions; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.ContentDialogs; + +public class ProfileElementRenameViewModel : ContentDialogViewModelBase +{ + private readonly IProfileEditorService _profileEditorService; + private readonly ProfileElement _profileElement; + private string? _profileElementName; + + public ProfileElementRenameViewModel(IProfileEditorService profileEditorService, ProfileElement profileElement) + { + _profileEditorService = profileEditorService; + _profileElement = profileElement; + _profileElementName = profileElement.Name; + + Confirm = ReactiveCommand.Create(ExecuteConfirm, ValidationContext.Valid); + Enter = ReactiveCommand.Create(() => ContentDialog?.Hide(ContentDialogResult.Primary), Confirm.CanExecute); + this.ValidationRule(vm => vm.ProfileElementName, name => !string.IsNullOrWhiteSpace(name), "You must specify a valid name"); + } + + public string? ProfileElementName + { + get => _profileElementName; + set => RaiseAndSetIfChanged(ref _profileElementName, value); + } + + + public ReactiveCommand Enter { get; } + public ReactiveCommand Confirm { get; } + + private void ExecuteConfirm() + { + if (ProfileElementName == null) + return; + + _profileEditorService.ExecuteCommand(new RenameProfileElement(_profileElement, ProfileElementName)); + ContentDialog?.Hide(ContentDialogResult.Primary); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml index 60f0456da..aa95e39f5 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml @@ -25,15 +25,8 @@ Kind="FolderOpen" Margin="0 0 5 0" IsVisible="{Binding IsExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" /> - - + + - { - ViewModel?.Rename.Subscribe(_ => - { - Input.Focus(); - Input.SelectAll(); - }).DisposeWith(d); - }); - } - - - private void InputElement_OnKeyUp(object? sender, KeyEventArgs e) - { - if (e.Key == Key.Enter) - ViewModel?.SubmitRename(); - else if (e.Key == Key.Escape) - ViewModel?.CancelRename(); - } - - private void InputElement_OnLostFocus(object? sender, RoutedEventArgs e) - { - ViewModel?.CancelRename(); } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml index 44eb5b0d0..5bd4a809b 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml @@ -18,15 +18,8 @@ - - + + - { - ViewModel?.Rename.Subscribe(_ => - { - Input.Focus(); - Input.SelectAll(); - }).DisposeWith(d); - }); - } - - - private void InputElement_OnKeyUp(object? sender, KeyEventArgs e) - { - if (e.Key == Key.Enter) - ViewModel?.SubmitRename(); - else if (e.Key == Key.Escape) - ViewModel?.CancelRename(); - } - - private void InputElement_OnLostFocus(object? sender, RoutedEventArgs e) - { - ViewModel?.CancelRename(); } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs index adbd6153d..7a331d321 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs @@ -45,7 +45,7 @@ public class ProfileTreeViewModel : TreeItemViewModel _focusNone = profileEditorService.FocusMode.Select(f => f == ProfileEditorFocusMode.None).ToProperty(this, vm => vm.FocusNone).DisposeWith(d); _focusFolder = profileEditorService.FocusMode.Select(f => f == ProfileEditorFocusMode.Folder).ToProperty(this, vm => vm.FocusFolder).DisposeWith(d); _focusSelection = profileEditorService.FocusMode.Select(f => f == ProfileEditorFocusMode.Selection).ToProperty(this, vm => vm.FocusSelection).DisposeWith(d); - _keyBindingsEnabled = profileEditorService.SuspendedKeybindings.Select(s => !s).ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); + _keyBindingsEnabled = Shared.UI.KeyBindingsEnabled.ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); }); ClearSelection = ReactiveCommand.Create(() => profileEditorService.ChangeCurrentProfileElement(null), this.WhenAnyValue(vm => vm.KeyBindingsEnabled)); diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs index 1ff9b311a..9d995f005 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs @@ -9,9 +9,11 @@ using System.Threading.Tasks; using Artemis.Core; using Artemis.UI.DryIoc.Factories; using Artemis.UI.Extensions; +using Artemis.UI.Screens.ProfileEditor.ProfileTree.ContentDialogs; using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs; using Artemis.UI.Shared; using Artemis.UI.Shared.Services; +using Artemis.UI.Shared.Services.Builders; using Artemis.UI.Shared.Services.ProfileEditor; using Artemis.UI.Shared.Services.ProfileEditor.Commands; using Avalonia; @@ -30,8 +32,6 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase private bool _isFlyoutOpen; private ObservableAsPropertyHelper? _isFocused; private ProfileElement? _profileElement; - private string? _renameValue; - private bool _renaming; private TimeSpan _time; protected TreeItemViewModel(TreeItemViewModel? parent, @@ -50,7 +50,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase AddLayer = ReactiveCommand.Create(ExecuteAddLayer); AddFolder = ReactiveCommand.Create(ExecuteAddFolder); OpenAdaptionHints = ReactiveCommand.CreateFromTask(ExecuteOpenAdaptionHints, this.WhenAnyValue(vm => vm.ProfileElement).Select(p => p is Layer)); - Rename = ReactiveCommand.Create(ExecuteRename); + Rename = ReactiveCommand.CreateFromTask(ExecuteRename); Delete = ReactiveCommand.Create(ExecuteDelete); Duplicate = ReactiveCommand.CreateFromTask(ExecuteDuplicate); Copy = ReactiveCommand.CreateFromTask(ExecuteCopy); @@ -96,12 +96,6 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase set => RaiseAndSetIfChanged(ref _isFlyoutOpen, value); } - public bool Renaming - { - get => _renaming; - set => RaiseAndSetIfChanged(ref _renaming, value); - } - public bool CanPaste { get => _canPaste; @@ -120,13 +114,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase public ReactiveCommand Paste { get; } public ReactiveCommand Delete { get; } public abstract bool SupportsChildren { get; } - - public string? RenameValue - { - get => _renameValue; - set => RaiseAndSetIfChanged(ref _renameValue, value); - } - + public async Task ShowBrokenStateExceptions() { if (ProfileElement == null) @@ -143,26 +131,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase return; } } - - public void SubmitRename() - { - if (ProfileElement == null) - { - Renaming = false; - return; - } - - ProfileEditorService.ExecuteCommand(new RenameProfileElement(ProfileElement, RenameValue)); - Renaming = false; - ProfileEditorService.ChangeSuspendedKeybindings(false); - } - - public void CancelRename() - { - Renaming = false; - ProfileEditorService.ChangeSuspendedKeybindings(false); - } - + public void InsertElement(TreeItemViewModel elementViewModel, int targetIndex) { if (elementViewModel.Parent == this && Children.IndexOf(elementViewModel) == targetIndex) @@ -250,11 +219,18 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase ProfileEditorService.ExecuteCommand(new RemoveProfileElement(renderProfileElement)); } - private void ExecuteRename() + private async Task ExecuteRename() { - Renaming = true; - RenameValue = ProfileElement?.Name; - ProfileEditorService.ChangeSuspendedKeybindings(true); + if (ProfileElement == null) + return; + + await _windowService.CreateContentDialog() + .WithTitle(ProfileElement is Folder ? "Rename folder" : "Rename layer") + .WithViewModel(out ProfileElementRenameViewModel vm, ProfileElement) + .HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Confirm)) + .WithCloseButtonText("Cancel") + .WithDefaultButton(ContentDialogButton.Primary) + .ShowAsync(); } private void ExecuteAddFolder() diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml index 744838e50..ba9da9a27 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml @@ -8,7 +8,7 @@ x:DataType="contentDialogs:LayerEffectRenameViewModel"> - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml.cs index 19972807c..9f99d70b9 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml.cs @@ -26,5 +26,4 @@ public partial class LayerEffectRenameView : ReactiveUserControl ContentDialog?.Hide(ContentDialogResult.Primary), Confirm.CanExecute); this.ValidationRule(vm => vm.LayerEffectName, categoryName => !string.IsNullOrWhiteSpace(categoryName), "You must specify a valid name"); } @@ -32,6 +33,7 @@ public class LayerEffectRenameViewModel : ContentDialogViewModelBase } public ReactiveCommand Confirm { get; } + public ReactiveCommand Enter { get; } private void ExecuteConfirm() { diff --git a/src/Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditView.axaml b/src/Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditView.axaml index 351b50f79..a27bb9281 100644 --- a/src/Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditView.axaml +++ b/src/Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditView.axaml @@ -8,7 +8,7 @@ x:DataType="sidebar:SidebarCategoryEditViewModel"> - + diff --git a/src/Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditViewModel.cs b/src/Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditViewModel.cs index 5096cc2d3..0884562ed 100644 --- a/src/Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditViewModel.cs @@ -24,6 +24,7 @@ public class SidebarCategoryEditViewModel : ContentDialogViewModelBase _categoryName = _category.Name; Confirm = ReactiveCommand.Create(ExecuteConfirm, ValidationContext.Valid); + Enter = ReactiveCommand.Create(() => ContentDialog?.Hide(ContentDialogResult.Primary), Confirm.CanExecute); this.ValidationRule(vm => vm.CategoryName, categoryName => !string.IsNullOrWhiteSpace(categoryName?.Trim()), "You must specify a valid name"); this.ValidationRule(vm => vm.CategoryName, categoryName => profileService.ProfileCategories.All(c => c.Name != categoryName?.Trim()), "You must specify a unique name"); } @@ -35,6 +36,7 @@ public class SidebarCategoryEditViewModel : ContentDialogViewModelBase } public ReactiveCommand Confirm { get; } + public ReactiveCommand Enter { get; } private void ExecuteConfirm() { diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs b/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs index 37348d46d..831c69b93 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs +++ b/src/Artemis.UI/Screens/VisualScripting/NodeScriptWindowViewModel.cs @@ -27,6 +27,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase private readonly ISettingsService _settingsService; private readonly IWindowService _windowService; private bool _pauseUpdate; + private ObservableAsPropertyHelper? _keyBindingsEnabled; public NodeScriptWindowViewModel(NodeScript nodeScript, INodeService nodeService, @@ -49,7 +50,7 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase _windowService = windowService; CreateNode = ReactiveCommand.Create(ExecuteCreateNode); - AutoArrange = ReactiveCommand.CreateFromTask(ExecuteAutoArrange); + AutoArrange = ReactiveCommand.CreateFromTask(ExecuteAutoArrange, this.WhenAnyValue(vm => vm.KeyBindingsEnabled)); Export = ReactiveCommand.CreateFromTask(ExecuteExport); Import = ReactiveCommand.CreateFromTask(ExecuteImport); @@ -64,6 +65,8 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase this.WhenActivated(d => { + _keyBindingsEnabled = Shared.UI.KeyBindingsEnabled.ToProperty(this, vm => vm.KeyBindingsEnabled).DisposeWith(d); + DispatcherTimer updateTimer = new(TimeSpan.FromMilliseconds(25.0 / 1000), DispatcherPriority.Normal, Update); // TODO: Remove in favor of saving each time a node editor command is executed DispatcherTimer saveTimer = new(TimeSpan.FromMinutes(2), DispatcherPriority.Normal, Save); @@ -89,7 +92,8 @@ public class NodeScriptWindowViewModel : NodeScriptWindowViewModelBase public ReactiveCommand AutoArrange { get; } public ReactiveCommand Export { get; } public ReactiveCommand Import { get; } - + public bool KeyBindingsEnabled => _keyBindingsEnabled?.Value ?? false; + public PluginSetting ShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false); public PluginSetting ShowFullPaths => _settingsService.GetSetting("ProfileEditor.ShowFullPaths", false); public PluginSetting AlwaysShowValues => _settingsService.GetSetting("ProfileEditor.AlwaysShowValues", true);