mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-31 01:42:02 +00:00
Data bindings - Rework internals to support more situations
This commit is contained in:
parent
d3128e17f1
commit
267e8e6a1e
@ -36,9 +36,6 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void ApplyValue(float value)
|
public override void ApplyValue(float value)
|
||||||
{
|
{
|
||||||
if (ValueTypeSetExpression == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (DataBinding!.LayerProperty.PropertyDescription.MaxInputValue is float max)
|
if (DataBinding!.LayerProperty.PropertyDescription.MaxInputValue is float max)
|
||||||
value = Math.Min(value, max);
|
value = Math.Min(value, max);
|
||||||
if (DataBinding!.LayerProperty.PropertyDescription.MinInputValue is float min)
|
if (DataBinding!.LayerProperty.PropertyDescription.MinInputValue is float min)
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
internal BoolLayerProperty()
|
internal BoolLayerProperty()
|
||||||
{
|
{
|
||||||
KeyframesSupported = false;
|
KeyframesSupported = false;
|
||||||
RegisterDataBindingProperty(b => b, new GeneralDataBindingConverter<bool>());
|
RegisterDataBindingProperty(value => value, (_, newValue) => CurrentValue = newValue, new GeneralDataBindingConverter<bool>(), "Value");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
namespace Artemis.Core
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public class ColorGradientLayerProperty : LayerProperty<ColorGradient>
|
public class ColorGradientLayerProperty : LayerProperty<ColorGradient>
|
||||||
@ -6,12 +8,33 @@
|
|||||||
internal ColorGradientLayerProperty()
|
internal ColorGradientLayerProperty()
|
||||||
{
|
{
|
||||||
KeyframesSupported = false;
|
KeyframesSupported = false;
|
||||||
DataBindingsSupported = false;
|
DataBindingsSupported = true;
|
||||||
DefaultValue = new ColorGradient();
|
DefaultValue = new ColorGradient();
|
||||||
|
|
||||||
CurrentValueSet += OnCurrentValueSet;
|
CurrentValueSet += OnCurrentValueSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreateDataBindingRegistrations()
|
||||||
|
{
|
||||||
|
ClearDataBindingProperties();
|
||||||
|
if (CurrentValue == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int index = 0; index < CurrentValue.Stops.Count; index++)
|
||||||
|
{
|
||||||
|
int stopIndex = index;
|
||||||
|
DataBindingRegistration<ColorGradient, SKColor> registerDataBindingProperty = RegisterDataBindingProperty(
|
||||||
|
gradient => gradient.Stops[stopIndex].Color,
|
||||||
|
(gradient, value) => gradient.Stops[stopIndex].Color = value,
|
||||||
|
new ColorStopDataBindingConverter(),
|
||||||
|
$"Color #{stopIndex + 1}"
|
||||||
|
);
|
||||||
|
|
||||||
|
registerDataBindingProperty.DisplayName = $"Color #{stopIndex + 1}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implicitly converts an <see cref="ColorGradientLayerProperty" /> to a <see cref="ColorGradient" />
|
/// Implicitly converts an <see cref="ColorGradientLayerProperty" /> to a <see cref="ColorGradient" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -31,6 +54,8 @@
|
|||||||
// Don't allow color gradients to be null
|
// Don't allow color gradients to be null
|
||||||
if (BaseValue == null)
|
if (BaseValue == null)
|
||||||
BaseValue = DefaultValue ?? new ColorGradient();
|
BaseValue = DefaultValue ?? new ColorGradient();
|
||||||
|
|
||||||
|
CreateDataBindingRegistrations();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Overrides of LayerProperty<ColorGradient>
|
#region Overrides of LayerProperty<ColorGradient>
|
||||||
@ -41,10 +66,31 @@
|
|||||||
// Don't allow color gradients to be null
|
// Don't allow color gradients to be null
|
||||||
if (BaseValue == null)
|
if (BaseValue == null)
|
||||||
BaseValue = DefaultValue ?? new ColorGradient();
|
BaseValue = DefaultValue ?? new ColorGradient();
|
||||||
|
|
||||||
base.OnInitialize();
|
base.OnInitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class ColorStopDataBindingConverter : DataBindingConverter<ColorGradient, SKColor>
|
||||||
|
{
|
||||||
|
public ColorStopDataBindingConverter()
|
||||||
|
{
|
||||||
|
SupportsInterpolate = true;
|
||||||
|
SupportsSum = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override SKColor Sum(SKColor a, SKColor b)
|
||||||
|
{
|
||||||
|
return a.Sum(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override SKColor Interpolate(SKColor a, SKColor b, double progress)
|
||||||
|
{
|
||||||
|
return a.Interpolate(b, (float) progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -5,7 +5,7 @@
|
|||||||
{
|
{
|
||||||
internal FloatLayerProperty()
|
internal FloatLayerProperty()
|
||||||
{
|
{
|
||||||
RegisterDataBindingProperty(value => value, new FloatDataBindingConverter());
|
RegisterDataBindingProperty(value => value, (_, newValue) => CurrentValue = newValue, new FloatDataBindingConverter(), "Value");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
{
|
{
|
||||||
internal FloatRangeLayerProperty()
|
internal FloatRangeLayerProperty()
|
||||||
{
|
{
|
||||||
RegisterDataBindingProperty(range => range.Start, new FloatDataBindingConverter<FloatRange>());
|
RegisterDataBindingProperty(value => value.Start, (value, newValue) => value.Start = newValue, new FloatDataBindingConverter<FloatRange>(), "Start");
|
||||||
RegisterDataBindingProperty(range => range.End, new FloatDataBindingConverter<FloatRange>());
|
RegisterDataBindingProperty(value => value.End, (value, newValue) => value.End = newValue, new FloatDataBindingConverter<FloatRange>(), "End");
|
||||||
|
|
||||||
CurrentValueSet += OnCurrentValueSet;
|
CurrentValueSet += OnCurrentValueSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
internal IntLayerProperty()
|
internal IntLayerProperty()
|
||||||
{
|
{
|
||||||
RegisterDataBindingProperty(value => value, new IntDataBindingConverter());
|
RegisterDataBindingProperty(value => value, (_, newValue) => CurrentValue = newValue, new IntDataBindingConverter(), "Value");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
{
|
{
|
||||||
internal IntRangeLayerProperty()
|
internal IntRangeLayerProperty()
|
||||||
{
|
{
|
||||||
RegisterDataBindingProperty(range => range.Start, new IntDataBindingConverter<IntRange>());
|
RegisterDataBindingProperty(value => value.Start, (value, newValue) => value.Start = newValue, new IntDataBindingConverter<IntRange>(), "Start");
|
||||||
RegisterDataBindingProperty(range => range.End, new IntDataBindingConverter<IntRange>());
|
RegisterDataBindingProperty(value => value.End, (value, newValue) => value.End = newValue, new IntDataBindingConverter<IntRange>(), "End");
|
||||||
|
|
||||||
CurrentValueSet += OnCurrentValueSet;
|
CurrentValueSet += OnCurrentValueSet;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
internal SKColorLayerProperty()
|
internal SKColorLayerProperty()
|
||||||
{
|
{
|
||||||
RegisterDataBindingProperty(value => value, new SKColorDataBindingConverter());
|
RegisterDataBindingProperty(value => value, (_, newValue) => CurrentValue = newValue, new SKColorDataBindingConverter(), "Value");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -7,8 +7,9 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
internal SKPointLayerProperty()
|
internal SKPointLayerProperty()
|
||||||
{
|
{
|
||||||
RegisterDataBindingProperty(point => point.X, new FloatDataBindingConverter<SKPoint>());
|
RegisterDataBindingProperty(value => value.X, (value, newValue) => value.X = newValue, new FloatDataBindingConverter<SKPoint>(), "X");
|
||||||
RegisterDataBindingProperty(point => point.Y, new FloatDataBindingConverter<SKPoint>());
|
RegisterDataBindingProperty(value => value.Y, (value, newValue) => value.Y = newValue, new FloatDataBindingConverter<SKPoint>(), "Y");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -7,8 +7,8 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
internal SKSizeLayerProperty()
|
internal SKSizeLayerProperty()
|
||||||
{
|
{
|
||||||
RegisterDataBindingProperty(size => size.Height, new FloatDataBindingConverter<SKSize>());
|
RegisterDataBindingProperty(value => value.Height, (value, newValue) => value.Height = newValue, new FloatDataBindingConverter<SKSize>(), "Height");
|
||||||
RegisterDataBindingProperty(size => size.Width, new FloatDataBindingConverter<SKSize>());
|
RegisterDataBindingProperty(value => value.Width, (value, newValue) => value.Width = newValue, new FloatDataBindingConverter<SKSize>(), "Width");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -97,7 +97,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Type? GetTargetType()
|
public Type? GetTargetType()
|
||||||
{
|
{
|
||||||
return Registration?.PropertyExpression.ReturnType;
|
return Registration?.Getter.Method.ReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetEasing(TProperty value)
|
private void ResetEasing(TProperty value)
|
||||||
@ -293,7 +293,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
// Don't save an invalid state
|
// Don't save an invalid state
|
||||||
if (Registration != null)
|
if (Registration != null)
|
||||||
Entity.TargetExpression = Registration.PropertyExpression.ToString();
|
Entity.TargetExpression = Registration.Getter.ToString();
|
||||||
|
|
||||||
Entity.EasingTime = EasingTime;
|
Entity.EasingTime = EasingTime;
|
||||||
Entity.EasingFunction = (int) EasingFunction;
|
Entity.EasingFunction = (int) EasingFunction;
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
@ -10,21 +8,6 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class DataBindingConverter<TLayerProperty, TProperty> : IDataBindingConverter
|
public abstract class DataBindingConverter<TLayerProperty, TProperty> : IDataBindingConverter
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets a dynamically compiled getter pointing to the data bound property
|
|
||||||
/// </summary>
|
|
||||||
public Func<TLayerProperty, TProperty>? GetExpression { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a dynamically compiled setter pointing to the data bound property used for value types
|
|
||||||
/// </summary>
|
|
||||||
public Action<TProperty>? ValueTypeSetExpression { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a dynamically compiled setter pointing to the data bound property used for reference types
|
|
||||||
/// </summary>
|
|
||||||
public Action<TLayerProperty, TProperty>? ReferenceTypeSetExpression { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data binding this converter is applied to
|
/// Gets the data binding this converter is applied to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -40,9 +23,6 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool SupportsInterpolate { get; protected set; }
|
public bool SupportsInterpolate { get; protected set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Type SupportedType => typeof(TProperty);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the sum of <paramref name="a" /> and <paramref name="b" />
|
/// Returns the sum of <paramref name="a" /> and <paramref name="b" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -65,12 +45,9 @@ namespace Artemis.Core
|
|||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public virtual void ApplyValue(TProperty value)
|
public virtual void ApplyValue(TProperty value)
|
||||||
{
|
{
|
||||||
if (DataBinding == null)
|
if (DataBinding?.Registration == null)
|
||||||
throw new ArtemisCoreException("Data binding converter is not yet initialized");
|
throw new ArtemisCoreException("Data binding converter is not yet initialized");
|
||||||
if (ReferenceTypeSetExpression != null)
|
DataBinding.Registration.Setter(DataBinding.LayerProperty.CurrentValue, value);
|
||||||
ReferenceTypeSetExpression(DataBinding.LayerProperty.CurrentValue, value);
|
|
||||||
else if (ValueTypeSetExpression != null)
|
|
||||||
ValueTypeSetExpression(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -78,9 +55,9 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual TProperty GetValue()
|
public virtual TProperty GetValue()
|
||||||
{
|
{
|
||||||
if (DataBinding == null || GetExpression == null)
|
if (DataBinding?.Registration == null)
|
||||||
throw new ArtemisCoreException("Data binding converter is not yet initialized");
|
throw new ArtemisCoreException("Data binding converter is not yet initialized");
|
||||||
return GetExpression(DataBinding.LayerProperty.CurrentValue);
|
return DataBinding.Registration.Getter(DataBinding.LayerProperty.CurrentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -104,83 +81,10 @@ namespace Artemis.Core
|
|||||||
throw new ArtemisCoreException("Cannot initialize a data binding converter for a data binding without a registration");
|
throw new ArtemisCoreException("Cannot initialize a data binding converter for a data binding without a registration");
|
||||||
|
|
||||||
DataBinding = dataBinding;
|
DataBinding = dataBinding;
|
||||||
GetExpression = dataBinding.Registration.PropertyExpression.Compile();
|
|
||||||
CreateSetExpression();
|
|
||||||
|
|
||||||
OnInitialized();
|
OnInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateSetExpression()
|
/// <inheritdoc />
|
||||||
{
|
public Type SupportedType => typeof(TProperty);
|
||||||
// If the registration does not point towards a member of LayerProperty<T>.CurrentValue, assign directly to LayerProperty<T>.CurrentValue
|
|
||||||
if (DataBinding!.Registration?.Member == null)
|
|
||||||
{
|
|
||||||
CreateSetCurrentValueExpression();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the member of LayerProperty<T>.CurrentValue has a setter
|
|
||||||
MethodInfo? setterMethod = null;
|
|
||||||
if (DataBinding.Registration.Member is PropertyInfo propertyInfo)
|
|
||||||
setterMethod = propertyInfo.GetSetMethod();
|
|
||||||
// If there is no setter, the built-in data binding cannot do its job, stay null
|
|
||||||
if (setterMethod == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If LayerProperty<T>.CurrentValue is a value type, assign it directly to LayerProperty<T>.CurrentValue after applying the changes
|
|
||||||
if (typeof(TLayerProperty).IsValueType)
|
|
||||||
CreateSetValueTypeExpression();
|
|
||||||
// If it is a reference type it can safely be updated by its reference
|
|
||||||
else
|
|
||||||
CreateSetReferenceTypeExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateSetReferenceTypeExpression()
|
|
||||||
{
|
|
||||||
if (DataBinding!.Registration?.Member == null)
|
|
||||||
throw new ArtemisCoreException("Cannot create value setter for data binding without a registration");
|
|
||||||
|
|
||||||
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
|
||||||
ParameterExpression parameter = Expression.Parameter(typeof(TLayerProperty), "currentValue");
|
|
||||||
MemberExpression memberAccess = Expression.MakeMemberAccess(parameter, DataBinding.Registration.Member);
|
|
||||||
BinaryExpression assignment = Expression.Assign(memberAccess, propertyValue);
|
|
||||||
Expression<Action<TLayerProperty, TProperty>> referenceTypeLambda = Expression.Lambda<Action<TLayerProperty, TProperty>>(assignment, parameter, propertyValue);
|
|
||||||
|
|
||||||
ReferenceTypeSetExpression = referenceTypeLambda.Compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateSetValueTypeExpression()
|
|
||||||
{
|
|
||||||
if (DataBinding!.Registration?.Member == null)
|
|
||||||
throw new ArtemisCoreException("Cannot create value setter for data binding without a registration");
|
|
||||||
|
|
||||||
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
|
||||||
ParameterExpression variableCurrent = Expression.Variable(typeof(TLayerProperty), "current");
|
|
||||||
ConstantExpression layerProperty = Expression.Constant(DataBinding.LayerProperty);
|
|
||||||
MemberExpression layerPropertyMemberAccess = Expression.MakeMemberAccess(layerProperty,
|
|
||||||
DataBinding.LayerProperty.GetType().GetMember(nameof(DataBinding.LayerProperty.CurrentValue))[0]);
|
|
||||||
|
|
||||||
BlockExpression body = Expression.Block(
|
|
||||||
new[] {variableCurrent},
|
|
||||||
Expression.Assign(variableCurrent, layerPropertyMemberAccess),
|
|
||||||
Expression.Assign(Expression.MakeMemberAccess(variableCurrent, DataBinding.Registration.Member), propertyValue),
|
|
||||||
Expression.Assign(layerPropertyMemberAccess, variableCurrent)
|
|
||||||
);
|
|
||||||
|
|
||||||
Expression<Action<TProperty>> valueTypeLambda = Expression.Lambda<Action<TProperty>>(body, propertyValue);
|
|
||||||
ValueTypeSetExpression = valueTypeLambda.Compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateSetCurrentValueExpression()
|
|
||||||
{
|
|
||||||
ParameterExpression propertyValue = Expression.Parameter(typeof(TProperty), "propertyValue");
|
|
||||||
ConstantExpression layerProperty = Expression.Constant(DataBinding!.LayerProperty);
|
|
||||||
MemberExpression layerPropertyMemberAccess = Expression.MakeMemberAccess(layerProperty,
|
|
||||||
DataBinding.LayerProperty.GetType().GetMember(nameof(DataBinding.LayerProperty.CurrentValue))[0]);
|
|
||||||
|
|
||||||
BinaryExpression body = Expression.Assign(layerPropertyMemberAccess, propertyValue);
|
|
||||||
Expression<Action<TProperty>> lambda = Expression.Lambda<Action<TProperty>>(body, propertyValue);
|
|
||||||
ValueTypeSetExpression = lambda.Compile();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
|
||||||
using Artemis.Storage.Entities.Profile.DataBindings;
|
using Artemis.Storage.Entities.Profile.DataBindings;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -9,16 +7,16 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public class DataBindingRegistration<TLayerProperty, TProperty> : IDataBindingRegistration
|
public class DataBindingRegistration<TLayerProperty, TProperty> : IDataBindingRegistration
|
||||||
{
|
{
|
||||||
internal DataBindingRegistration(LayerProperty<TLayerProperty> layerProperty,
|
internal DataBindingRegistration(LayerProperty<TLayerProperty> layerProperty, DataBindingConverter<TLayerProperty, TProperty> converter,
|
||||||
DataBindingConverter<TLayerProperty, TProperty> converter,
|
Func<TLayerProperty, TProperty> getter,
|
||||||
Expression<Func<TLayerProperty, TProperty>> propertyExpression)
|
Action<TLayerProperty, TProperty> setter,
|
||||||
|
string displayName)
|
||||||
{
|
{
|
||||||
LayerProperty = layerProperty ?? throw new ArgumentNullException(nameof(layerProperty));
|
LayerProperty = layerProperty ?? throw new ArgumentNullException(nameof(layerProperty));
|
||||||
Converter = converter ?? throw new ArgumentNullException(nameof(converter));
|
Converter = converter ?? throw new ArgumentNullException(nameof(converter));
|
||||||
PropertyExpression = propertyExpression ?? throw new ArgumentNullException(nameof(propertyExpression));
|
Getter = getter ?? throw new ArgumentNullException(nameof(getter));
|
||||||
|
Setter = setter ?? throw new ArgumentNullException(nameof(setter));
|
||||||
if (propertyExpression.Body is MemberExpression memberExpression)
|
DisplayName = displayName ?? throw new ArgumentNullException(nameof(displayName));
|
||||||
Member = memberExpression.Member;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -32,15 +30,19 @@ namespace Artemis.Core
|
|||||||
public DataBindingConverter<TLayerProperty, TProperty> Converter { get; }
|
public DataBindingConverter<TLayerProperty, TProperty> Converter { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the expression that that accesses the property
|
/// Gets the function to call to get the value of the property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Expression<Func<TLayerProperty, TProperty>> PropertyExpression { get; }
|
public Func<TLayerProperty, TProperty> Getter { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the member the <see cref="PropertyExpression" /> targets
|
/// Gets the action to call to set the value of the property
|
||||||
/// <para><see langword="null"/> if the <see cref="PropertyExpression" /> is not a member expression</para>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MemberInfo? Member { get; }
|
public Action<TLayerProperty, TProperty> Setter { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the display name of the data binding registration
|
||||||
|
/// </summary>
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the data binding created using this registration
|
/// Gets the data binding created using this registration
|
||||||
@ -59,7 +61,7 @@ namespace Artemis.Core
|
|||||||
if (DataBinding != null)
|
if (DataBinding != null)
|
||||||
return DataBinding;
|
return DataBinding;
|
||||||
|
|
||||||
DataBindingEntity? dataBinding = LayerProperty.Entity.DataBindingEntities.FirstOrDefault(e => e.TargetExpression == PropertyExpression.ToString());
|
DataBindingEntity? dataBinding = LayerProperty.Entity.DataBindingEntities.FirstOrDefault(e => e.TargetExpression == Getter.ToString());
|
||||||
if (dataBinding == null)
|
if (dataBinding == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|||||||
@ -393,7 +393,7 @@ namespace Artemis.Core
|
|||||||
throw new ObjectDisposedException("LayerProperty");
|
throw new ObjectDisposedException("LayerProperty");
|
||||||
|
|
||||||
IDataBindingRegistration? match = _dataBindingRegistrations.FirstOrDefault(r => r is DataBindingRegistration<T, TProperty> registration &&
|
IDataBindingRegistration? match = _dataBindingRegistrations.FirstOrDefault(r => r is DataBindingRegistration<T, TProperty> registration &&
|
||||||
registration.PropertyExpression.ToString() == expression);
|
registration.Getter.ToString() == expression);
|
||||||
return (DataBindingRegistration<T, TProperty>?) match;
|
return (DataBindingRegistration<T, TProperty>?) match;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,21 +410,30 @@ namespace Artemis.Core
|
|||||||
/// Registers a data binding property so that is available to the data binding system
|
/// Registers a data binding property so that is available to the data binding system
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TProperty">The type of the layer property</typeparam>
|
/// <typeparam name="TProperty">The type of the layer property</typeparam>
|
||||||
/// <param name="propertyExpression">The expression pointing to the value to register</param>
|
/// <param name="getter">The function to call to get the value of the property</param>
|
||||||
|
/// <param name="setter">The action to call to set the value of the property</param>
|
||||||
/// <param name="converter">The converter to use while applying the data binding</param>
|
/// <param name="converter">The converter to use while applying the data binding</param>
|
||||||
public void RegisterDataBindingProperty<TProperty>(Expression<Func<T, TProperty>> propertyExpression, DataBindingConverter<T, TProperty> converter)
|
/// <param name="displayName">The display name of the data binding property</param>
|
||||||
|
public DataBindingRegistration<T, TProperty> RegisterDataBindingProperty<TProperty>(Func<T, TProperty> getter, Action<T, TProperty> setter, DataBindingConverter<T, TProperty> converter,
|
||||||
|
string displayName)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("LayerProperty");
|
throw new ObjectDisposedException("LayerProperty");
|
||||||
|
|
||||||
if (propertyExpression.Body.NodeType != ExpressionType.MemberAccess && propertyExpression.Body.NodeType != ExpressionType.Parameter)
|
DataBindingRegistration<T, TProperty> registration = new(this, converter, getter, setter, displayName);
|
||||||
throw new ArtemisCoreException("Provided expression is invalid, it must be 'value => value' or 'value => value.Property'");
|
_dataBindingRegistrations.Add(registration);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
if (converter.SupportedType != propertyExpression.ReturnType)
|
/// <summary>
|
||||||
throw new ArtemisCoreException($"Cannot register data binding property for property {PropertyDescription.Name} " +
|
/// Removes all data binding properties so they are no longer available to the data binding system
|
||||||
"because the provided converter does not support the property's type");
|
/// </summary>
|
||||||
|
public void ClearDataBindingProperties()
|
||||||
|
{
|
||||||
|
if (_disposed)
|
||||||
|
throw new ObjectDisposedException("LayerProperty");
|
||||||
|
|
||||||
_dataBindingRegistrations.Add(new DataBindingRegistration<T, TProperty>(this, converter, propertyExpression));
|
_dataBindingRegistrations.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -38,11 +38,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
|||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_dataBindingsVmFactory = dataBindingsVmFactory;
|
_dataBindingsVmFactory = dataBindingsVmFactory;
|
||||||
|
|
||||||
if (Registration.Member != null)
|
DisplayName = Registration.DisplayName.ToUpper();
|
||||||
DisplayName = Registration.Member.Name.ToUpper();
|
|
||||||
else
|
|
||||||
DisplayName = Registration.LayerProperty.PropertyDescription.Name.ToUpper();
|
|
||||||
|
|
||||||
AlwaysApplyDataBindings = settingsService.GetSetting("ProfileEditor.AlwaysApplyDataBindings", true);
|
AlwaysApplyDataBindings = settingsService.GetSetting("ProfileEditor.AlwaysApplyDataBindings", true);
|
||||||
DataBindingModes = new BindableCollection<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(DataBindingModeType)));
|
DataBindingModes = new BindableCollection<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(DataBindingModeType)));
|
||||||
EasingViewModels = new BindableCollection<TimelineEasingViewModel>();
|
EasingViewModels = new BindableCollection<TimelineEasingViewModel>();
|
||||||
|
|||||||
@ -302,7 +302,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
TimeSpan delta = DateTime.Now - _lastUpdate;
|
TimeSpan delta = DateTime.Now - _lastUpdate;
|
||||||
_lastUpdate = DateTime.Now;
|
_lastUpdate = DateTime.Now;
|
||||||
|
|
||||||
if (!AlwaysApplyDataBindings.Value || _profileEditorService.SelectedProfile == null || _profileEditorService.Playing)
|
if (!AlwaysApplyDataBindings.Value || _profileEditorService.SelectedProfile == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (IDataBindingRegistration dataBindingRegistration in _profileEditorService.SelectedProfile.GetAllFolders()
|
foreach (IDataBindingRegistration dataBindingRegistration in _profileEditorService.SelectedProfile.GetAllFolders()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user