mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Sidebar - Redesigned sidebar with customizable categories Profiles - Added the ability to configure custom profile icons Profiles - Added the ability to activate multiple profiles for modules at once Profiles - Added the ability to create profiles for no modules Profiles - Added the ability to suspend a profile or an entire category Profiles - Added profile activation conditions Profiles - Added file-based importing/exporting Profile editor - Condensed UI, removed tabs Profile editor - Disable condition operators until a left-side is picked
337 lines
14 KiB
C#
337 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Media;
|
|
using Artemis.Core;
|
|
using Artemis.Core.Modules;
|
|
using Artemis.Core.Services;
|
|
using Artemis.UI.Shared;
|
|
using Artemis.UI.Shared.Input;
|
|
using Artemis.UI.Shared.Services;
|
|
using Stylet;
|
|
|
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions.Abstract
|
|
{
|
|
public abstract class DataModelConditionPredicateViewModel : DataModelConditionViewModel, IDisposable
|
|
{
|
|
private readonly IConditionOperatorService _conditionOperatorService;
|
|
private readonly IDataModelUIService _dataModelUIService;
|
|
private readonly List<Module> _modules;
|
|
private readonly IProfileEditorService _profileEditorService;
|
|
private DataModelStaticViewModel _rightSideInputViewModel;
|
|
private DataModelDynamicViewModel _rightSideSelectionViewModel;
|
|
private BaseConditionOperator _selectedOperator;
|
|
|
|
private List<Type> _supportedInputTypes;
|
|
|
|
protected DataModelConditionPredicateViewModel(
|
|
DataModelConditionPredicate dataModelConditionPredicate,
|
|
List<Module> modules,
|
|
IProfileEditorService profileEditorService,
|
|
IDataModelUIService dataModelUIService,
|
|
IConditionOperatorService conditionOperatorService,
|
|
ISettingsService settingsService) : base(dataModelConditionPredicate)
|
|
{
|
|
_modules = modules;
|
|
_profileEditorService = profileEditorService;
|
|
_dataModelUIService = dataModelUIService;
|
|
_conditionOperatorService = conditionOperatorService;
|
|
_supportedInputTypes = new List<Type>();
|
|
|
|
SelectOperatorCommand = new DelegateCommand(ExecuteSelectOperatorCommand);
|
|
Operators = new BindableCollection<BaseConditionOperator>();
|
|
|
|
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
|
|
}
|
|
|
|
public DataModelConditionPredicate DataModelConditionPredicate => (DataModelConditionPredicate) Model;
|
|
public PluginSetting<bool> ShowDataModelValues { get; }
|
|
|
|
public bool CanSelectOperator => DataModelConditionPredicate.LeftPath is {IsValid: true};
|
|
|
|
public BaseConditionOperator SelectedOperator
|
|
{
|
|
get => _selectedOperator;
|
|
set => SetAndNotify(ref _selectedOperator, value);
|
|
}
|
|
|
|
public DataModelDynamicViewModel RightSideSelectionViewModel
|
|
{
|
|
get => _rightSideSelectionViewModel;
|
|
set => SetAndNotify(ref _rightSideSelectionViewModel, value);
|
|
}
|
|
|
|
public DataModelStaticViewModel RightSideInputViewModel
|
|
{
|
|
get => _rightSideInputViewModel;
|
|
set => SetAndNotify(ref _rightSideInputViewModel, value);
|
|
}
|
|
|
|
public DelegateCommand SelectOperatorCommand { get; }
|
|
public BindableCollection<BaseConditionOperator> Operators { get; }
|
|
|
|
protected SolidColorBrush LeftSideColor { get; set; }
|
|
|
|
public override void Evaluate()
|
|
{
|
|
IsConditionMet = DataModelConditionPredicate.Evaluate();
|
|
}
|
|
|
|
public override void Delete()
|
|
{
|
|
base.Delete();
|
|
_profileEditorService.SaveSelectedProfileElement();
|
|
}
|
|
|
|
public virtual void Initialize()
|
|
{
|
|
LeftSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_modules);
|
|
LeftSideSelectionViewModel.PropertySelected += LeftSideOnPropertySelected;
|
|
if (LeftSideColor != null)
|
|
LeftSideSelectionViewModel.ButtonBrush = LeftSideColor;
|
|
|
|
// Determine which types are currently supported
|
|
_supportedInputTypes = GetSupportedInputTypes();
|
|
|
|
Update();
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
|
|
LeftSideSelectionViewModel.ChangeDataModelPath(DataModelConditionPredicate.LeftPath);
|
|
|
|
Type leftSideType = GetLeftSideType();
|
|
|
|
// Get the supported operators
|
|
Operators.Clear();
|
|
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType ?? typeof(object), ConditionParameterSide.Left));
|
|
if (DataModelConditionPredicate.Operator == null)
|
|
DataModelConditionPredicate.UpdateOperator(Operators.FirstOrDefault());
|
|
// The core doesn't care about best matches so if there is a new preferred operator, use that instead
|
|
else if (!Operators.Contains(DataModelConditionPredicate.Operator))
|
|
DataModelConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.Description == DataModelConditionPredicate.Operator.Description) ?? Operators.FirstOrDefault());
|
|
|
|
NotifyOfPropertyChange(nameof(CanSelectOperator));
|
|
SelectedOperator = DataModelConditionPredicate.Operator;
|
|
|
|
// Without a selected operator or one that supports a right side, leave the right side input empty
|
|
if (SelectedOperator?.RightSideType == null)
|
|
{
|
|
DisposeRightSideStaticViewModel();
|
|
DisposeRightSideDynamicViewModel();
|
|
return;
|
|
}
|
|
|
|
// Ensure the right side has the proper VM
|
|
if (DataModelConditionPredicate.PredicateType == ProfileRightSideType.Dynamic)
|
|
{
|
|
DisposeRightSideStaticViewModel();
|
|
if (RightSideSelectionViewModel == null)
|
|
CreateRightSideSelectionViewModel();
|
|
|
|
RightSideSelectionViewModel.ChangeDataModelPath(DataModelConditionPredicate.RightPath);
|
|
RightSideSelectionViewModel.FilterTypes = new[] {SelectedOperator.RightSideType};
|
|
}
|
|
else
|
|
{
|
|
DisposeRightSideDynamicViewModel();
|
|
if (RightSideInputViewModel == null)
|
|
CreateRightSideInputViewModel();
|
|
|
|
Type preferredType = DataModelConditionPredicate.GetPreferredRightSideType();
|
|
if (preferredType != null && RightSideInputViewModel.TargetType != preferredType)
|
|
RightSideInputViewModel.UpdateTargetType(preferredType);
|
|
|
|
RightSideInputViewModel.Value = DataModelConditionPredicate.RightStaticValue;
|
|
}
|
|
}
|
|
|
|
public void ApplyLeftSide()
|
|
{
|
|
Type newType = LeftSideSelectionViewModel.DataModelPath.GetPropertyType();
|
|
bool converted = ConvertIfRequired(newType);
|
|
if (converted)
|
|
return;
|
|
|
|
DataModelConditionPredicate.UpdateLeftSide(LeftSideSelectionViewModel.DataModelPath);
|
|
_profileEditorService.SaveSelectedProfileElement();
|
|
|
|
SelectedOperator = DataModelConditionPredicate.Operator;
|
|
Update();
|
|
}
|
|
|
|
public void ApplyRightSideDynamic()
|
|
{
|
|
DataModelConditionPredicate.UpdateRightSideDynamic(RightSideSelectionViewModel.DataModelPath);
|
|
_profileEditorService.SaveSelectedProfileElement();
|
|
|
|
Update();
|
|
}
|
|
|
|
public void ApplyRightSideStatic(object value)
|
|
{
|
|
DataModelConditionPredicate.UpdateRightSideStatic(value);
|
|
_profileEditorService.SaveSelectedProfileElement();
|
|
|
|
Update();
|
|
}
|
|
|
|
public void ApplyOperator()
|
|
{
|
|
DataModelConditionPredicate.UpdateOperator(SelectedOperator);
|
|
_profileEditorService.SaveSelectedProfileElement();
|
|
|
|
Update();
|
|
}
|
|
|
|
protected abstract List<Type> GetSupportedInputTypes();
|
|
protected abstract Type GetLeftSideType();
|
|
|
|
protected virtual List<DataModelPropertiesViewModel> GetExtraRightSideDataModelViewModels()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
private void ExecuteSelectOperatorCommand(object context)
|
|
{
|
|
if (!(context is BaseConditionOperator dataModelConditionOperator))
|
|
return;
|
|
|
|
SelectedOperator = dataModelConditionOperator;
|
|
ApplyOperator();
|
|
}
|
|
|
|
public override void UpdateModules()
|
|
{
|
|
if (LeftSideSelectionViewModel != null)
|
|
{
|
|
LeftSideSelectionViewModel.PropertySelected -= LeftSideOnPropertySelected;
|
|
LeftSideSelectionViewModel.Dispose();
|
|
LeftSideSelectionViewModel = null;
|
|
}
|
|
DisposeRightSideStaticViewModel();
|
|
DisposeRightSideDynamicViewModel();
|
|
|
|
// If the modules changed the paths may no longer be valid if they targeted a module no longer available, in that case clear the path
|
|
if (DataModelConditionPredicate.LeftPath?.Target != null && !DataModelConditionPredicate.LeftPath.Target.IsExpansion && !_modules.Contains(DataModelConditionPredicate.LeftPath.Target.Module))
|
|
DataModelConditionPredicate.UpdateLeftSide(null);
|
|
if (DataModelConditionPredicate.RightPath?.Target != null && !DataModelConditionPredicate.RightPath.Target.IsExpansion && !_modules.Contains(DataModelConditionPredicate.RightPath.Target.Module))
|
|
DataModelConditionPredicate.UpdateRightSideDynamic(null);
|
|
|
|
Initialize();
|
|
}
|
|
|
|
#region IDisposable
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
if (LeftSideSelectionViewModel != null)
|
|
{
|
|
LeftSideSelectionViewModel.PropertySelected -= LeftSideOnPropertySelected;
|
|
LeftSideSelectionViewModel.Dispose();
|
|
LeftSideSelectionViewModel = null;
|
|
}
|
|
|
|
DisposeRightSideStaticViewModel();
|
|
DisposeRightSideDynamicViewModel();
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region View model creation
|
|
|
|
private void CreateRightSideSelectionViewModel()
|
|
{
|
|
RightSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_modules);
|
|
RightSideSelectionViewModel.ButtonBrush = (SolidColorBrush) Application.Current.FindResource("PrimaryHueMidBrush");
|
|
RightSideSelectionViewModel.DisplaySwitchButton = true;
|
|
RightSideSelectionViewModel.PropertySelected += RightSideOnPropertySelected;
|
|
RightSideSelectionViewModel.SwitchToStaticRequested += RightSideSelectionViewModelOnSwitchToStaticRequested;
|
|
|
|
List<DataModelPropertiesViewModel> extra = GetExtraRightSideDataModelViewModels();
|
|
if (extra != null)
|
|
RightSideSelectionViewModel.ExtraDataModelViewModels.AddRange(extra);
|
|
}
|
|
|
|
private void CreateRightSideInputViewModel()
|
|
{
|
|
Type preferredType = DataModelConditionPredicate.GetPreferredRightSideType();
|
|
RightSideInputViewModel = _dataModelUIService.GetStaticInputViewModel(preferredType, LeftSideSelectionViewModel.DataModelPath?.GetPropertyDescription());
|
|
RightSideInputViewModel.ButtonBrush = (SolidColorBrush) Application.Current.FindResource("PrimaryHueMidBrush");
|
|
RightSideInputViewModel.DisplaySwitchButton = true;
|
|
RightSideInputViewModel.ValueUpdated += RightSideOnValueEntered;
|
|
RightSideInputViewModel.SwitchToDynamicRequested += RightSideInputViewModelOnSwitchToDynamicRequested;
|
|
}
|
|
|
|
private void DisposeRightSideStaticViewModel()
|
|
{
|
|
if (RightSideInputViewModel == null)
|
|
return;
|
|
RightSideInputViewModel.ValueUpdated -= RightSideOnValueEntered;
|
|
RightSideInputViewModel.SwitchToDynamicRequested -= RightSideInputViewModelOnSwitchToDynamicRequested;
|
|
RightSideInputViewModel.Dispose();
|
|
RightSideInputViewModel = null;
|
|
}
|
|
|
|
private void DisposeRightSideDynamicViewModel()
|
|
{
|
|
if (RightSideSelectionViewModel == null)
|
|
return;
|
|
RightSideSelectionViewModel.PropertySelected -= RightSideOnPropertySelected;
|
|
RightSideSelectionViewModel.SwitchToStaticRequested -= RightSideSelectionViewModelOnSwitchToStaticRequested;
|
|
RightSideSelectionViewModel.Dispose();
|
|
RightSideSelectionViewModel = null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Event handlers
|
|
|
|
private void LeftSideOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
|
|
{
|
|
ApplyLeftSide();
|
|
}
|
|
|
|
private void RightSideOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
|
|
{
|
|
ApplyRightSideDynamic();
|
|
}
|
|
|
|
private void RightSideOnValueEntered(object sender, DataModelInputStaticEventArgs e)
|
|
{
|
|
ApplyRightSideStatic(e.Value);
|
|
}
|
|
|
|
private void RightSideSelectionViewModelOnSwitchToStaticRequested(object sender, EventArgs e)
|
|
{
|
|
DataModelConditionPredicate.PredicateType = ProfileRightSideType.Static;
|
|
|
|
// Ensure the right static value is never null when the preferred type is a value type
|
|
Type preferredType = DataModelConditionPredicate.GetPreferredRightSideType();
|
|
if (DataModelConditionPredicate.RightStaticValue == null && preferredType != null && preferredType.IsValueType)
|
|
DataModelConditionPredicate.UpdateRightSideStatic(preferredType.GetDefault());
|
|
|
|
Update();
|
|
}
|
|
|
|
private void RightSideInputViewModelOnSwitchToDynamicRequested(object sender, EventArgs e)
|
|
{
|
|
DataModelConditionPredicate.PredicateType = ProfileRightSideType.Dynamic;
|
|
Update();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |