From cd8656cb0de4b32af4cc01b9dfd16ad231921883 Mon Sep 17 00:00:00 2001 From: Robert Date: Sat, 23 Apr 2022 21:12:06 +0200 Subject: [PATCH] Profile editor - Added effect renaming Core - Fixed effect loading Core - Fixed some effects not applying on per-LED brushes --- src/.idea/.idea.Artemis/.idea/avalonia.xml | 3 + src/Artemis.Core/Constants.cs | 6 ++ src/Artemis.Core/Models/Profile/Layer.cs | 3 +- .../Plugins/LayerBrushes/PerLedLayerBrush.cs | 5 +- .../LayerEffects/Internal/BaseLayerEffect.cs | 2 +- .../LayerEffects/LayerEffectDescriptor.cs | 1 + src/Artemis.Core/Stores/LayerEffectStore.cs | 2 +- .../Commands/RemoveLayerEffect.cs | 48 ++++++++++ .../Commands/RenameLayerEffect.cs | 44 ++++++++++ src/Artemis.UI/Artemis.UI.csproj | 8 ++ .../SKPointPropertyInputViewModel.cs | 11 +-- .../SKSizePropertyInputViewModel.cs | 11 +-- .../Properties/PropertyGroupViewModel.cs | 3 +- .../LayerEffectRenameView.axaml | 15 ++++ .../LayerEffectRenameView.axaml.cs | 35 ++++++++ .../LayerEffectRenameViewModel.cs | 45 ++++++++++ .../Properties/Tree/TreeGroupView.axaml | 87 ++++++++----------- .../Properties/Tree/TreeGroupViewModel.cs | 42 ++++++--- 18 files changed, 292 insertions(+), 79 deletions(-) create mode 100644 src/Artemis.UI.Shared/Services/ProfileEditor/Commands/RemoveLayerEffect.cs create mode 100644 src/Artemis.UI.Shared/Services/ProfileEditor/Commands/RenameLayerEffect.cs create mode 100644 src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml create mode 100644 src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml.cs create mode 100644 src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameViewModel.cs diff --git a/src/.idea/.idea.Artemis/.idea/avalonia.xml b/src/.idea/.idea.Artemis/.idea/avalonia.xml index 663884d07..2097abb8a 100644 --- a/src/.idea/.idea.Artemis/.idea/avalonia.xml +++ b/src/.idea/.idea.Artemis/.idea/avalonia.xml @@ -18,9 +18,12 @@ + + + diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs index b63d493c2..69208acb3 100644 --- a/src/Artemis.Core/Constants.cs +++ b/src/Artemis.Core/Constants.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Reflection; using Artemis.Core.JsonConverters; using Artemis.Core.Services; using Artemis.Core.Services.Core; @@ -14,6 +15,11 @@ namespace Artemis.Core /// public static class Constants { + /// + /// The Artemis.Core assembly + /// + public static readonly Assembly CoreAssembly = typeof(Constants).Assembly; + /// /// The full path to the Artemis application folder /// diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 4153c6cd8..67493f42b 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -627,13 +627,12 @@ namespace Artemis.Core if (LayerBrush == null) throw new ArtemisCoreException("The layer is not yet ready for rendering"); + using SKAutoCanvasRestore _ = new(canvas); foreach (BaseLayerEffect baseLayerEffect in LayerEffects) { if (!baseLayerEffect.Suspended) baseLayerEffect.InternalPreProcess(canvas, bounds, layerPaint); } - - using SKAutoCanvasRestore _ = new(canvas); canvas.ClipPath(renderPath); // Restore the blend mode before doing the actual render diff --git a/src/Artemis.Core/Plugins/LayerBrushes/PerLedLayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrushes/PerLedLayerBrush.cs index a60db4405..a4296b7aa 100644 --- a/src/Artemis.Core/Plugins/LayerBrushes/PerLedLayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrushes/PerLedLayerBrush.cs @@ -35,7 +35,6 @@ namespace Artemis.Core.LayerBrushes canvas.SetMatrix(canvas.TotalMatrix.PreConcat(Layer.GetTransformMatrix(true, false, false, true).Invert())); using SKPath pointsPath = new(); - using SKPaint ledPaint = new(); foreach (ArtemisLed artemisLed in Layer.Leds) { pointsPath.AddPoly(new[] @@ -61,7 +60,7 @@ namespace Artemis.Core.LayerBrushes continue; // Let the brush determine the color - ledPaint.Color = GetColor(artemisLed, renderPoint); + paint.Color = GetColor(artemisLed, renderPoint); SKRect ledRectangle = SKRect.Create( artemisLed.AbsoluteRectangle.Left - Layer.Bounds.Left, @@ -70,7 +69,7 @@ namespace Artemis.Core.LayerBrushes artemisLed.AbsoluteRectangle.Height ); - canvas.DrawRect(ledRectangle, ledPaint); + canvas.DrawRect(ledRectangle, paint); } }, "Failed to render"); } diff --git a/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs b/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs index 495f24dba..9692ac27c 100644 --- a/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs +++ b/src/Artemis.Core/Plugins/LayerEffects/Internal/BaseLayerEffect.cs @@ -222,8 +222,8 @@ namespace Artemis.Core.LayerEffects /// public void Load() { - Name = LayerEffectEntity.Name; HasBeenRenamed = LayerEffectEntity.HasBeenRenamed; + Name = HasBeenRenamed ? LayerEffectEntity.Name : Descriptor.DisplayName; Order = LayerEffectEntity.Order; } diff --git a/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs b/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs index 59fa31b5c..5c605de8d 100644 --- a/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs +++ b/src/Artemis.Core/Plugins/LayerEffects/LayerEffectDescriptor.cs @@ -87,6 +87,7 @@ public class LayerEffectDescriptor else { effect.LayerEffectEntity = new LayerEffectEntity(); + effect.Name = DisplayName; effect.Initialize(); effect.Save(); } diff --git a/src/Artemis.Core/Stores/LayerEffectStore.cs b/src/Artemis.Core/Stores/LayerEffectStore.cs index 9793e2021..863da5043 100644 --- a/src/Artemis.Core/Stores/LayerEffectStore.cs +++ b/src/Artemis.Core/Stores/LayerEffectStore.cs @@ -51,7 +51,7 @@ namespace Artemis.Core { lock (Registrations) { - return Registrations.FirstOrDefault(d => d.PluginFeature.Id == providerId && d.LayerEffectDescriptor.LayerEffectType?.Name == typeName); + return Registrations.FirstOrDefault(d => d.PluginFeature.Id == providerId && d.LayerEffectDescriptor.LayerEffectType?.FullName == typeName); } } diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/RemoveLayerEffect.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/RemoveLayerEffect.cs new file mode 100644 index 000000000..e7d284c72 --- /dev/null +++ b/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/RemoveLayerEffect.cs @@ -0,0 +1,48 @@ +using System; +using Artemis.Core; +using Artemis.Core.LayerEffects; + +namespace Artemis.UI.Shared.Services.ProfileEditor.Commands; + +/// +/// Represents a profile editor command that can be used to remove a layer effect from a profile element. +/// +public class RemoveLayerEffect : IProfileEditorCommand, IDisposable +{ + private readonly RenderProfileElement _renderProfileElement; + private readonly BaseLayerEffect _layerEffect; + private bool _executed; + + /// + /// Creates a new instance of the class. + /// + public RemoveLayerEffect(BaseLayerEffect layerEffect) + { + _renderProfileElement = layerEffect.ProfileElement; + _layerEffect = layerEffect; + } + + /// + public string DisplayName => "Remove layer effect"; + + /// + public void Execute() + { + _renderProfileElement.RemoveLayerEffect(_layerEffect); + _executed = true; + } + + /// + public void Undo() + { + _renderProfileElement.AddLayerEffect(_layerEffect); + _executed = false; + } + + /// + public void Dispose() + { + if (_executed) + _layerEffect.Dispose(); + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/RenameLayerEffect.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/RenameLayerEffect.cs new file mode 100644 index 000000000..6cceb5578 --- /dev/null +++ b/src/Artemis.UI.Shared/Services/ProfileEditor/Commands/RenameLayerEffect.cs @@ -0,0 +1,44 @@ +using System; +using Artemis.Core; +using Artemis.Core.LayerEffects; + +namespace Artemis.UI.Shared.Services.ProfileEditor.Commands; + +/// +/// Represents a profile editor command that can be used to rename a layer effect +/// +public class RenameLayerEffect : IProfileEditorCommand +{ + private readonly BaseLayerEffect _layerEffect; + private readonly string _name; + private readonly string _oldName; + private readonly bool _wasRenamed; + + /// + /// Creates a new instance of the class. + /// + public RenameLayerEffect(BaseLayerEffect layerEffect, string name) + { + _layerEffect = layerEffect; + _name = name; + _oldName = layerEffect.Name; + _wasRenamed = layerEffect.HasBeenRenamed; + } + + /// + public string DisplayName => "Rename layer effect"; + + /// + public void Execute() + { + _layerEffect.Name = _name; + _layerEffect.HasBeenRenamed = true; + } + + /// + public void Undo() + { + _layerEffect.Name = _oldName; + _layerEffect.HasBeenRenamed = _wasRenamed; + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index af2c19e4d..c5a63eca7 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -68,6 +68,14 @@ NodeScriptWindowView.axaml + + LayerEffectRenameView.axaml + Code + + + SidebarCategoryEditView.axaml + Code + diff --git a/src/Artemis.UI/DefaultTypes/PropertyInput/SKPointPropertyInputViewModel.cs b/src/Artemis.UI/DefaultTypes/PropertyInput/SKPointPropertyInputViewModel.cs index db5dd9efc..4f711f997 100644 --- a/src/Artemis.UI/DefaultTypes/PropertyInput/SKPointPropertyInputViewModel.cs +++ b/src/Artemis.UI/DefaultTypes/PropertyInput/SKPointPropertyInputViewModel.cs @@ -1,4 +1,5 @@ -using Artemis.Core; +using System; +using Artemis.Core; using Artemis.UI.Shared.Services.ProfileEditor; using Artemis.UI.Shared.Services.PropertyInput; using ReactiveUI; @@ -14,17 +15,17 @@ public class SKPointPropertyInputViewModel : PropertyInputViewModel { if (LayerProperty.PropertyDescription.MinInputValue.IsNumber()) { - this.ValidationRule(vm => vm.X, i => i >= (float) LayerProperty.PropertyDescription.MinInputValue, + this.ValidationRule(vm => vm.X, i => i >= Convert.ToSingle(LayerProperty.PropertyDescription.MinInputValue), $"X must be equal to or greater than {LayerProperty.PropertyDescription.MinInputValue}."); - this.ValidationRule(vm => vm.Y, i => i >= (float) LayerProperty.PropertyDescription.MinInputValue, + this.ValidationRule(vm => vm.Y, i => i >= Convert.ToSingle(LayerProperty.PropertyDescription.MinInputValue), $"Y must be equal to or greater than {LayerProperty.PropertyDescription.MinInputValue}."); } if (LayerProperty.PropertyDescription.MaxInputValue.IsNumber()) { - this.ValidationRule(vm => vm.X, i => i <= (float) LayerProperty.PropertyDescription.MaxInputValue, + this.ValidationRule(vm => vm.X, i => i <= Convert.ToSingle(LayerProperty.PropertyDescription.MaxInputValue), $"X must be equal to or smaller than {LayerProperty.PropertyDescription.MaxInputValue}."); - this.ValidationRule(vm => vm.Y, i => i <= (float) LayerProperty.PropertyDescription.MaxInputValue, + this.ValidationRule(vm => vm.Y, i => i <= Convert.ToSingle(LayerProperty.PropertyDescription.MaxInputValue), $"Y must be equal to or smaller than {LayerProperty.PropertyDescription.MaxInputValue}."); } } diff --git a/src/Artemis.UI/DefaultTypes/PropertyInput/SKSizePropertyInputViewModel.cs b/src/Artemis.UI/DefaultTypes/PropertyInput/SKSizePropertyInputViewModel.cs index 510d93959..e1c006d32 100644 --- a/src/Artemis.UI/DefaultTypes/PropertyInput/SKSizePropertyInputViewModel.cs +++ b/src/Artemis.UI/DefaultTypes/PropertyInput/SKSizePropertyInputViewModel.cs @@ -1,4 +1,5 @@ -using Artemis.Core; +using System; +using Artemis.Core; using Artemis.UI.Shared.Services.ProfileEditor; using Artemis.UI.Shared.Services.PropertyInput; using ReactiveUI; @@ -16,17 +17,17 @@ public class SKSizePropertyInputViewModel : PropertyInputViewModel { if (LayerProperty.PropertyDescription.MinInputValue.IsNumber()) { - this.ValidationRule(vm => vm.Width, i => i >= (float) LayerProperty.PropertyDescription.MinInputValue, + this.ValidationRule(vm => vm.Width, i => i >= Convert.ToSingle(LayerProperty.PropertyDescription.MinInputValue), $"Width must be equal to or greater than {LayerProperty.PropertyDescription.MinInputValue}."); - this.ValidationRule(vm => vm.Height, i => i >= (float) LayerProperty.PropertyDescription.MinInputValue, + this.ValidationRule(vm => vm.Height, i => i >= Convert.ToSingle(LayerProperty.PropertyDescription.MinInputValue), $"Height must be equal to or greater than {LayerProperty.PropertyDescription.MinInputValue}."); } if (LayerProperty.PropertyDescription.MaxInputValue.IsNumber()) { - this.ValidationRule(vm => vm.Width, i => i <= (float) LayerProperty.PropertyDescription.MaxInputValue, + this.ValidationRule(vm => vm.Width, i => i <= Convert.ToSingle(LayerProperty.PropertyDescription.MaxInputValue), $"Width must be equal to or smaller than {LayerProperty.PropertyDescription.MaxInputValue}."); - this.ValidationRule(vm => vm.Height, i => i <= (float) LayerProperty.PropertyDescription.MaxInputValue, + this.ValidationRule(vm => vm.Height, i => i <= Convert.ToSingle(LayerProperty.PropertyDescription.MaxInputValue), $"Height must be equal to or smaller than {LayerProperty.PropertyDescription.MaxInputValue}."); } } diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyGroupViewModel.cs index 83da67450..faa1e3841 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyGroupViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertyGroupViewModel.cs @@ -117,7 +117,8 @@ public class PropertyGroupViewModel : ViewModelBase, IDisposable { // Get all properties and property groups and create VMs for them // The group has methods for getting this without reflection but then we lose the order of the properties as they are defined on the group - foreach (PropertyInfo propertyInfo in LayerPropertyGroup.GetType().GetProperties()) + // Sorting is done to ensure properties defined by the Core (such as on layers) are always on top. + foreach (PropertyInfo propertyInfo in LayerPropertyGroup.GetType().GetProperties().OrderBy(p => p.DeclaringType?.Assembly != Constants.CoreAssembly)) { if (Attribute.IsDefined(propertyInfo, typeof(LayerPropertyIgnoreAttribute))) continue; 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 new file mode 100644 index 000000000..81414eae7 --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file 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 new file mode 100644 index 000000000..425743459 --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameView.axaml.cs @@ -0,0 +1,35 @@ +using System.Threading.Tasks; +using Artemis.UI.Shared.Extensions; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; +using Avalonia.Threading; +using ReactiveUI; + +namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs; + +public class LayerEffectRenameView : ReactiveUserControl +{ + public LayerEffectRenameView() + { + InitializeComponent(); + this.WhenActivated(_ => + { + this.ClearAllDataValidationErrors(); + Dispatcher.UIThread.Post(DelayedAutoFocus); + }); + } + + private async void DelayedAutoFocus() + { + // Don't ask + await Task.Delay(200); + this.Get("NameTextBox").SelectAll(); + this.Get("NameTextBox").Focus(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameViewModel.cs new file mode 100644 index 000000000..fd180e95c --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/ContentDialogs/LayerEffectRenameViewModel.cs @@ -0,0 +1,45 @@ +using System.Reactive; +using Artemis.Core.LayerEffects; +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.Properties.Tree.ContentDialogs +{ + public class LayerEffectRenameViewModel : ContentDialogViewModelBase + { + private readonly IProfileEditorService _profileEditorService; + private readonly BaseLayerEffect _layerEffect; + private string? _layerEffectName; + + public LayerEffectRenameViewModel(IProfileEditorService profileEditorService, BaseLayerEffect layerEffect) + { + _profileEditorService = profileEditorService; + _layerEffect = layerEffect; + _layerEffectName = layerEffect.Name; + + Confirm = ReactiveCommand.Create(ExecuteConfirm, ValidationContext.Valid); + this.ValidationRule(vm => vm.LayerEffectName, categoryName => !string.IsNullOrWhiteSpace(categoryName), "You must specify a valid name"); + } + + public string? LayerEffectName + { + get => _layerEffectName; + set => this.RaiseAndSetIfChanged(ref _layerEffectName, value); + } + + public ReactiveCommand Confirm { get; } + + private void ExecuteConfirm() + { + if (LayerEffectName == null) + return; + + _profileEditorService.ExecuteCommand(new RenameLayerEffect(_layerEffect, LayerEffectName)); + ContentDialog?.Hide(ContentDialogResult.Primary); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupView.axaml index 0d84c6054..71bdfb6e8 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupView.axaml @@ -9,7 +9,8 @@ xmlns:properties="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties" xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.TreeGroupView"> + x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.TreeGroupView" + x:DataType="viewModel:TreeGroupViewModel"> @@ -26,8 +27,8 @@ Height="29"> - - + IsVisible="{CompiledBinding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.None}}" /> + IsVisible="{CompiledBinding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.General}}"> - General + General + IsVisible="{CompiledBinding GroupType, Converter={StaticResource EnumBoolConverter}, ConverterParameter={x:Static viewModel:LayerPropertyGroupType.Transform}}"> - Transform + Transform - Brush - + IsVisible="{CompiledBinding LayerBrush.ConfigurationDialog, Converter={x:Static ObjectConverters.IsNotNull}}"> Extra options available! - @@ -102,61 +103,45 @@ - - + Effect - + IsVisible="{CompiledBinding !LayerEffect.HasBeenRenamed}" /> + IsVisible="{CompiledBinding LayerEffect.HasBeenRenamed}" /> - - @@ -186,15 +171,15 @@ Do not bind directly to the PropertyGroupViewModel.Children collection Instead use a reference provided by the VM that is null when collapsed, virtualization for noobs --> - - + - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupViewModel.cs index 48bd28fde..73b57931b 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/Tree/TreeGroupViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.ObjectModel; using System.Linq; +using System.Reactive; using System.Reactive.Disposables; using System.Reflection; using System.Threading.Tasks; @@ -8,12 +9,15 @@ using Artemis.Core; using Artemis.Core.LayerBrushes; using Artemis.Core.LayerEffects; using Artemis.UI.Exceptions; +using Artemis.UI.Screens.ProfileEditor.Properties.Tree.ContentDialogs; using Artemis.UI.Screens.ProfileEditor.Properties.Windows; using Artemis.UI.Shared; using Artemis.UI.Shared.LayerBrushes; using Artemis.UI.Shared.LayerEffects; 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 Ninject; using Ninject.Parameters; using ReactiveUI; @@ -41,19 +45,25 @@ public class TreeGroupViewModel : ActivatableViewModelBase }); // TODO: Update ProfileElementPropertyGroupViewModel visibility on change (can remove the sub on line 41 as well then) + OpenBrushSettings = ReactiveCommand.CreateFromTask(ExecuteOpenBrushSettings); + OpenEffectSettings = ReactiveCommand.CreateFromTask(ExecuteOpenEffectSettings); + RenameEffect = ReactiveCommand.CreateFromTask(ExecuteRenameEffect); + DeleteEffect = ReactiveCommand.Create(ExecuteDeleteEffect); } - public PropertyGroupViewModel PropertyGroupViewModel { get; } public LayerPropertyGroup LayerPropertyGroup => PropertyGroupViewModel.LayerPropertyGroup; public BaseLayerBrush? LayerBrush => PropertyGroupViewModel.LayerBrush; public BaseLayerEffect? LayerEffect => PropertyGroupViewModel.LayerEffect; - - public ObservableCollection? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null; - public LayerPropertyGroupType GroupType { get; private set; } + public ObservableCollection? Children => PropertyGroupViewModel.IsExpanded ? PropertyGroupViewModel.Children : null; + + public ReactiveCommand OpenBrushSettings { get; } + public ReactiveCommand OpenEffectSettings { get; } + public ReactiveCommand RenameEffect { get; } + public ReactiveCommand DeleteEffect { get; } - public async Task OpenBrushSettings() + private async Task ExecuteOpenBrushSettings() { if (LayerBrush?.ConfigurationDialog is not LayerBrushConfigurationDialog configurationViewModel) return; @@ -83,7 +93,7 @@ public class TreeGroupViewModel : ActivatableViewModelBase } } - public async Task OpenEffectSettings() + private async Task ExecuteOpenEffectSettings() { if (LayerEffect?.ConfigurationDialog is not LayerEffectConfigurationDialog configurationViewModel) return; @@ -113,14 +123,26 @@ public class TreeGroupViewModel : ActivatableViewModelBase } } - public async Task RenameEffect() + private async Task ExecuteRenameEffect() { - await _windowService.ShowConfirmContentDialog("Not yet implemented", "Try again later :p"); + if (LayerEffect == null) + return; + + await _windowService.CreateContentDialog() + .WithTitle("Rename layer effect") + .WithViewModel(out LayerEffectRenameViewModel vm, ("layerEffect", LayerEffect)) + .HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Confirm)) + .WithCloseButtonText("Cancel") + .WithDefaultButton(ContentDialogButton.Primary) + .ShowAsync(); } - public async Task DeleteEffect() + private void ExecuteDeleteEffect() { - await _windowService.ShowConfirmContentDialog("Not yet implemented", "Try again later :p"); + if (LayerEffect == null) + return; + + _profileEditorService.ExecuteCommand(new RemoveLayerEffect(LayerEffect)); } public double GetDepth()