using System; using System.Collections.Generic; using System.Linq; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.Exceptions; using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDataBinding.ModifierTypes; using Artemis.UI.Shared; using Artemis.UI.Shared.Input; using Artemis.UI.Shared.Services; using Stylet; namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDataBinding { public sealed class DataBindingModifierViewModel : PropertyChangedBase, IDisposable { private readonly IDataBindingService _dataBindingService; private readonly IDataModelUIService _dataModelUIService; private readonly IProfileEditorService _profileEditorService; private DataModelDynamicViewModel _dynamicSelectionViewModel; private ModifierTypeCategoryViewModel _modifierTypeViewModels; private BaseDataBindingModifierType _selectedModifierType; private DataModelStaticViewModel _staticInputViewModel; public DataBindingModifierViewModel(DataBindingModifier modifier, IDataBindingService dataBindingService, ISettingsService settingsService, IDataModelUIService dataModelUIService, IProfileEditorService profileEditorService) { _dataBindingService = dataBindingService; _dataModelUIService = dataModelUIService; _profileEditorService = profileEditorService; ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues"); Modifier = modifier; SelectModifierTypeCommand = new DelegateCommand(ExecuteSelectModifierTypeCommand); Update(); } public DelegateCommand SelectModifierTypeCommand { get; } public PluginSetting ShowDataModelValues { get; } public DataBindingModifier Modifier { get; } public ModifierTypeCategoryViewModel ModifierTypeViewModels { get => _modifierTypeViewModels; set => SetAndNotify(ref _modifierTypeViewModels, value); } public BaseDataBindingModifierType SelectedModifierType { get => _selectedModifierType; set => SetAndNotify(ref _selectedModifierType, value); } public DataModelDynamicViewModel DynamicSelectionViewModel { get => _dynamicSelectionViewModel; private set => SetAndNotify(ref _dynamicSelectionViewModel, value); } public DataModelStaticViewModel StaticInputViewModel { get => _staticInputViewModel; private set => SetAndNotify(ref _staticInputViewModel, value); } public void Delete() { Modifier.DirectDataBinding.RemoveModifier(Modifier); _profileEditorService.UpdateSelectedProfileElement(); } private void ParameterSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e) { Modifier.UpdateParameterDynamic(e.DataModelPath); _profileEditorService.UpdateSelectedProfileElement(); } private void StaticInputViewModelOnValueUpdated(object sender, DataModelInputStaticEventArgs e) { Modifier.UpdateParameterStatic(e.Value); _profileEditorService.UpdateSelectedProfileElement(); } private void Update() { Type sourceType = Modifier.DirectDataBinding.GetSourceType(); if (sourceType == null) throw new ArtemisUIException("Cannot use a data binding modifier VM for a data binding without a source"); if (Modifier.ModifierType == null || Modifier.ModifierType.ParameterType == null) { DisposeDynamicSelectionViewModel(); DisposeStaticInputViewModel(); } else if (Modifier.ParameterType == ProfileRightSideType.Dynamic) { DisposeStaticInputViewModel(); DynamicSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule()); if (DynamicSelectionViewModel != null) { DynamicSelectionViewModel.DisplaySwitchButton = true; DynamicSelectionViewModel.PropertySelected += ParameterSelectionViewModelOnPropertySelected; DynamicSelectionViewModel.SwitchToStaticRequested += DynamicSelectionViewModelOnSwitchToStaticRequested; DynamicSelectionViewModel.FilterTypes = new[] {Modifier.ModifierType.ParameterType ?? sourceType}; } } else { DisposeDynamicSelectionViewModel(); StaticInputViewModel = _dataModelUIService.GetStaticInputViewModel(Modifier.ModifierType.ParameterType ?? sourceType, null); if (StaticInputViewModel != null) { StaticInputViewModel.DisplaySwitchButton = true; StaticInputViewModel.ValueUpdated += StaticInputViewModelOnValueUpdated; StaticInputViewModel.SwitchToDynamicRequested += StaticInputViewModelOnSwitchToDynamicRequested; } } // Modifier type ModifierTypeCategoryViewModel root = new(null, null); IEnumerable> modifierTypes = _dataBindingService.GetCompatibleModifierTypes(sourceType, ModifierTypePart.Value).GroupBy(t => t.Category); foreach (IGrouping dataBindingModifierTypes in modifierTypes) { IEnumerable viewModels = dataBindingModifierTypes.Select(t => new ModifierTypeViewModel(t)); if (dataBindingModifierTypes.Key == null) root.Children.AddRange(viewModels); else root.Children.Add(new ModifierTypeCategoryViewModel(dataBindingModifierTypes.Key, viewModels)); } ModifierTypeViewModels = root; SelectedModifierType = Modifier.ModifierType; // Parameter if (DynamicSelectionViewModel != null) DynamicSelectionViewModel.ChangeDataModelPath(Modifier.ParameterPath); else if (StaticInputViewModel != null) StaticInputViewModel.Value = Modifier.ParameterStaticValue; } private void ExecuteSelectModifierTypeCommand(object context) { if (!(context is ModifierTypeViewModel modifierTypeViewModel)) return; Modifier.UpdateModifierType(modifierTypeViewModel.ModifierType); _profileEditorService.UpdateSelectedProfileElement(); Update(); } #region IDisposable /// public void Dispose() { DisposeDynamicSelectionViewModel(); DisposeStaticInputViewModel(); } private void DisposeStaticInputViewModel() { if (StaticInputViewModel != null) { StaticInputViewModel.Dispose(); StaticInputViewModel.ValueUpdated -= StaticInputViewModelOnValueUpdated; StaticInputViewModel.SwitchToDynamicRequested -= StaticInputViewModelOnSwitchToDynamicRequested; StaticInputViewModel = null; } } private void DisposeDynamicSelectionViewModel() { if (DynamicSelectionViewModel != null) { DynamicSelectionViewModel.Dispose(); DynamicSelectionViewModel.PropertySelected -= ParameterSelectionViewModelOnPropertySelected; DynamicSelectionViewModel.SwitchToStaticRequested -= DynamicSelectionViewModelOnSwitchToStaticRequested; DynamicSelectionViewModel = null; } } #endregion #region Event handlers private void DynamicSelectionViewModelOnSwitchToStaticRequested(object sender, EventArgs e) { Modifier.ParameterType = ProfileRightSideType.Static; // Ensure the right static value is never null when the preferred type is a value type if (SelectedModifierType.ParameterType != null && SelectedModifierType.ParameterType.IsValueType && Modifier.ParameterStaticValue == null) Modifier.UpdateParameterStatic(SelectedModifierType.ParameterType.GetDefault()); Update(); } private void StaticInputViewModelOnSwitchToDynamicRequested(object sender, EventArgs e) { Modifier.ParameterType = ProfileRightSideType.Dynamic; Update(); } #endregion } }