using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reflection; using Artemis.Core; using Artemis.Core.LayerBrushes; using Artemis.Core.LayerEffects; using Artemis.UI.Exceptions; using Artemis.UI.Screens.ProfileEditor.Dialogs; using Artemis.UI.Screens.ProfileEditor.Windows; using Artemis.UI.Shared.LayerBrushes; using Artemis.UI.Shared.LayerEffects; using Artemis.UI.Shared.Services; using Ninject; using Ninject.Parameters; using Stylet; namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree { public class TreeGroupViewModel : Screen { public enum LayerPropertyGroupType { General, Transform, LayerBrushRoot, LayerEffectRoot, None } private readonly IDialogService _dialogService; private readonly IProfileEditorService _profileEditorService; private readonly IWindowManager _windowManager; private LayerBrushSettingsWindowViewModel _layerBrushSettingsWindowVm; private LayerEffectSettingsWindowViewModel _layerEffectSettingsWindowVm; public TreeGroupViewModel(LayerPropertyGroupViewModel layerPropertyGroupViewModel, IProfileEditorService profileEditorService, IDialogService dialogService, IWindowManager windowManager) { _profileEditorService = profileEditorService; _dialogService = dialogService; _windowManager = windowManager; LayerPropertyGroupViewModel = layerPropertyGroupViewModel; LayerPropertyGroup = LayerPropertyGroupViewModel.LayerPropertyGroup; DetermineGroupType(); } public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; } public LayerPropertyGroup LayerPropertyGroup { get; } public LayerPropertyGroupType GroupType { get; set; } public IObservableCollection Items => LayerPropertyGroupViewModel.IsExpanded && LayerPropertyGroupViewModel.IsVisible ? LayerPropertyGroupViewModel.Items : null; public void OpenBrushSettings() { BaseLayerBrush layerBrush = LayerPropertyGroup.LayerBrush; LayerBrushConfigurationDialog configurationViewModel = (LayerBrushConfigurationDialog) layerBrush.ConfigurationDialog; if (configurationViewModel == null) return; try { // Limit to one constructor, there's no need to have more and it complicates things anyway ConstructorInfo[] constructors = configurationViewModel.Type.GetConstructors(); if (constructors.Length != 1) throw new ArtemisUIException("Brush configuration dialogs must have exactly one constructor"); // Find the BaseLayerBrush parameter, it is required by the base constructor so its there for sure ParameterInfo brushParameter = constructors.First().GetParameters().First(p => typeof(BaseLayerBrush).IsAssignableFrom(p.ParameterType)); ConstructorArgument argument = new(brushParameter.Name, layerBrush); BrushConfigurationViewModel viewModel = (BrushConfigurationViewModel) layerBrush.Descriptor.Provider.Plugin.Kernel.Get(configurationViewModel.Type, argument); _layerBrushSettingsWindowVm = new LayerBrushSettingsWindowViewModel(viewModel); _windowManager.ShowDialog(_layerBrushSettingsWindowVm); } catch (Exception e) { _dialogService.ShowExceptionDialog("An exception occured while trying to show the brush's settings window", e); } } public void OpenEffectSettings() { BaseLayerEffect layerEffect = LayerPropertyGroup.LayerEffect; LayerEffectConfigurationDialog configurationViewModel = (LayerEffectConfigurationDialog) layerEffect.ConfigurationDialog; if (configurationViewModel == null) return; try { // Limit to one constructor, there's no need to have more and it complicates things anyway ConstructorInfo[] constructors = configurationViewModel.Type.GetConstructors(); if (constructors.Length != 1) throw new ArtemisUIException("Effect configuration dialogs must have exactly one constructor"); ParameterInfo effectParameter = constructors.First().GetParameters().First(p => typeof(BaseLayerEffect).IsAssignableFrom(p.ParameterType)); ConstructorArgument argument = new(effectParameter.Name, layerEffect); EffectConfigurationViewModel viewModel = (EffectConfigurationViewModel) layerEffect.Descriptor.Provider.Plugin.Kernel.Get(configurationViewModel.Type, argument); _layerEffectSettingsWindowVm = new LayerEffectSettingsWindowViewModel(viewModel); _windowManager.ShowDialog(_layerEffectSettingsWindowVm); } catch (Exception e) { _dialogService.ShowExceptionDialog("An exception occured while trying to show the effect's settings window", e); throw; } } public async void RenameEffect() { object result = await _dialogService.ShowDialogAt( "PropertyTreeDialogHost", new Dictionary { {"subject", "effect"}, {"currentName", LayerPropertyGroup.LayerEffect.Name} } ); if (result is string newName) { LayerPropertyGroup.LayerEffect.Name = newName; LayerPropertyGroup.LayerEffect.HasBeenRenamed = true; _profileEditorService.UpdateSelectedProfile(); } } public void DeleteEffect() { if (LayerPropertyGroup.LayerEffect == null) return; LayerPropertyGroup.ProfileElement.RemoveLayerEffect(LayerPropertyGroup.LayerEffect); _profileEditorService.UpdateSelectedProfile(); } public void EnableToggled() { _profileEditorService.UpdateSelectedProfile(); } public double GetDepth() { int depth = 0; LayerPropertyGroup current = LayerPropertyGroup.Parent; while (current != null) { depth++; current = current.Parent; } return depth; } private void LayerPropertyGroupViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(LayerPropertyGroupViewModel.IsExpanded) || e.PropertyName == nameof(LayerPropertyGroupViewModel.IsVisible)) NotifyOfPropertyChange(nameof(Items)); } private void DetermineGroupType() { if (LayerPropertyGroup is LayerGeneralProperties) GroupType = LayerPropertyGroupType.General; else if (LayerPropertyGroup is LayerTransformProperties) GroupType = LayerPropertyGroupType.Transform; else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerBrush != null) GroupType = LayerPropertyGroupType.LayerBrushRoot; else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerEffect != null) GroupType = LayerPropertyGroupType.LayerEffectRoot; else GroupType = LayerPropertyGroupType.None; } #region Overrides of Screen /// protected override void OnInitialActivate() { LayerPropertyGroupViewModel.PropertyChanged += LayerPropertyGroupViewModelOnPropertyChanged; base.OnInitialActivate(); } /// protected override void OnClose() { LayerPropertyGroupViewModel.PropertyChanged -= LayerPropertyGroupViewModelOnPropertyChanged; // Clean up windows that may be open, sorry but your brush/effect is closed! _layerBrushSettingsWindowVm?.RequestClose(); _layerEffectSettingsWindowVm?.RequestClose(); base.OnClose(); } #endregion } }