1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Databinding modifiers - Redesigned API to leverage generics

Databinding modifiers - Updated default modifiers to use new API
This commit is contained in:
SpoinkyNL 2020-10-20 19:00:41 +02:00
parent 2bb663db15
commit fd9f3afef5
50 changed files with 487 additions and 407 deletions

View File

@ -0,0 +1,60 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodes_005Cconditional/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodes_005Cdirect/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cconditions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cconditions_005Coperators/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cconditions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cconditions_005Coperators/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cconverters/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cmodifiers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cmodifiers_005Ccolors/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cmodifiers_005Cnumbers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cmodifiers_005Cnumbers_005Crounding/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cmodifiers_005Cnumbers_005Ctrigonometric/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cdatabindings_005Cmodifiers_005Cnumbers_005Ctrigonometry/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=defaulttypes_005Cproperties/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events_005Cplugins/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events_005Cprofiles/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events_005Cstores/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=exceptions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=extensions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Ccolors/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cconditions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cconditions_005Cabstract/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cconditions_005Coperators/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cconverters/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cconverters_005Cinternal/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cdatabindingproperties/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cdatabindingproperties_005Cabstract/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodifiers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodifiers_005Cabstract/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatamodel/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Clayerproperties/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Clayerproperties_005Cattributes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Clayerproperties_005Ctypes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Clayershapes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Csurface/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=placeholders/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cdatamodelexpansions_005Cattributes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cdatamodelexpansions_005Cinternal/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Clayerbrushes_005Cinternal/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Clayereffects_005Cinternal/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cmodules_005Cactivationrequirements/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Csettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=rgb_002Enet/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cregistration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cregistration_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cstorage/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cstorage_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=stores/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=stores_005Cregistrations/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=utilities/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,23 +1,17 @@
using System;
using System.Collections.Generic;
using SkiaSharp;
using SkiaSharp;
namespace Artemis.Core.DefaultTypes
{
internal class SKColorBrightenModifierType : DataBindingModifierType
internal class SKColorBrightenModifierType : DataBindingModifierType<SKColor, float>
{
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> {typeof(SKColor)};
public override Type ParameterType => typeof(float);
public override string Name => "Brighten by";
public override string Icon => "CarLightHigh";
public override string Description => "Brightens the color by the amount in percent";
public override object Apply(object currentValue, object parameterValue)
public override SKColor Apply(SKColor currentValue, float parameterValue)
{
((SKColor) currentValue).ToHsl(out float h, out float s, out float l);
l *= (Convert.ToSingle(parameterValue) + 100f) / 100f;
currentValue.ToHsl(out float h, out float s, out float l);
l *= (parameterValue + 100f) / 100f;
return SKColor.FromHsl(h, s, l);
}
}

View File

@ -1,22 +1,17 @@
using System;
using System.Collections.Generic;
using SkiaSharp;
using SkiaSharp;
namespace Artemis.Core.DefaultTypes
{
internal class SKColorDarkenModifierType : DataBindingModifierType
internal class SKColorDarkenModifierType : DataBindingModifierType<SKColor, float>
{
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> {typeof(SKColor)};
public override Type ParameterType => typeof(float);
public override string Name => "Darken by";
public override string Icon => "CarLightDimmed";
public override string Description => "Darkens the color by the amount in percent";
public override object Apply(object currentValue, object parameterValue)
public override SKColor Apply(SKColor currentValue, float parameterValue)
{
((SKColor) currentValue).ToHsl(out float h, out float s, out float l);
l *= (Convert.ToSingle(parameterValue) * -1 + 100f) / 100f;
currentValue.ToHsl(out float h, out float s, out float l);
l *= (parameterValue * -1 + 100f) / 100f;
return SKColor.FromHsl(h, s, l);
}
}

View File

@ -1,24 +1,17 @@
using System;
using System.Collections.Generic;
using SkiaSharp;
using SkiaSharp;
namespace Artemis.Core.DefaultTypes
{
internal class SKColorRotateHueModifierType : DataBindingModifierType
internal class SKColorRotateHueModifierType : DataBindingModifierType<SKColor, float>
{
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> {typeof(SKColor)};
public override Type ParameterType => typeof(float);
public override string Name => "Rotate Hue by";
public override string Icon => "RotateRight";
public override string Description => "Rotates the hue of the color by the amount in degrees";
public override object Apply(object currentValue, object parameterValue)
public override SKColor Apply(SKColor currentValue, float parameterValue)
{
((SKColor) currentValue).ToHsl(out float h, out float s, out float l);
h += (float)parameterValue;
currentValue.ToHsl(out float h, out float s, out float l);
h += parameterValue;
return SKColor.FromHsl(h % 360, s, l);
}
}

View File

@ -1,20 +1,16 @@
using System;
using System.Collections.Generic;
using SkiaSharp;
using SkiaSharp;
namespace Artemis.Core.DefaultTypes
{
internal class SKColorSumModifierType : DataBindingModifierType
internal class SKColorSumModifierType : DataBindingModifierType<SKColor, SKColor>
{
public override IReadOnlyCollection<Type> CompatibleTypes => new List<Type> {typeof(SKColor)};
public override string Name => "Combine with";
public override string Icon => "FormatColorFill";
public override string Description => "Adds the two colors together";
public override object Apply(object currentValue, object parameterValue)
public override SKColor Apply(SKColor currentValue, SKColor parameterValue)
{
return ((SKColor) currentValue).Sum((SKColor) parameterValue);
return currentValue.Sum(parameterValue);
}
}
}

View File

@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class AbsoluteModifierType : DataBindingModifierType
internal class AbsoluteModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Absolute";
public override string Icon => "NumericPositive1";
public override string Category => "Advanced";
public override string Description => "Converts the input value to an absolute value";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
return Math.Abs(Convert.ToSingle(currentValue));
return Math.Abs(currentValue);
}
}
}

View File

@ -1,24 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
namespace Artemis.Core.DefaultTypes
{
internal class DivideModifierType : DataBindingModifierType
internal class DivideModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override Type ParameterType => typeof(float);
public override string Name => "Divide by";
public override string Icon => "Divide";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
float parameter = Convert.ToSingle(parameterValue);
// Ye ye none of that
if (parameter == 0)
if (parameterValue == 0)
return 0;
return Convert.ToSingle(currentValue) / parameter;
return currentValue / parameterValue;
}
}
}

View File

@ -1,20 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class MaxModifierType : DataBindingModifierType
internal class MaxModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override string Name => "Max";
public override string Icon => "ChevronUpBoxOutline";
public override string Category => "Advanced";
public override string Description => "Keeps only the largest of input value and parameter";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
return Math.Max(Convert.ToSingle(currentValue), Convert.ToSingle(parameterValue));
return Math.Max(currentValue, parameterValue);
}
}
}

View File

@ -1,20 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class MinModifierType : DataBindingModifierType
internal class MinModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override string Name => "Min";
public override string Icon => "ChevronDownBoxOutline";
public override string Category => "Advanced";
public override string Description => "Keeps only the smallest of input value and parameter";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
return Math.Min(Convert.ToSingle(currentValue), Convert.ToSingle(parameterValue));
return Math.Min(currentValue, parameterValue);
}
}
}

View File

@ -1,20 +1,15 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
namespace Artemis.Core.DefaultTypes
{
internal class ModuloModifierType : DataBindingModifierType
internal class ModuloModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override string Name => "Modulo";
public override string Icon => "Stairs";
public override string Category => "Advanced";
public override string Description => "Calculates the remained of the division between the input value and the parameter";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
return Convert.ToSingle(currentValue) % Convert.ToSingle(parameterValue);
return currentValue % parameterValue;
}
}
}

View File

@ -1,19 +1,13 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
namespace Artemis.Core.DefaultTypes
{
internal class MultiplicationModifierType : DataBindingModifierType
internal class MultiplicationModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override Type ParameterType => typeof(float);
public override string Name => "Multiply by";
public override string Icon => "Close";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
return Convert.ToSingle(currentValue) * Convert.ToSingle(parameterValue);
return currentValue * parameterValue;
}
}
}

View File

@ -1,25 +1,18 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
namespace Artemis.Core.DefaultTypes
{
internal class PercentageOfModifierType : DataBindingModifierType
internal class PercentageOfModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override Type ParameterType => typeof(float);
public override string Name => "Percentage of";
public override string Icon => "Percent";
public override string Description => "Calculates how much percent the parameter value is of the current value";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
float parameter = Convert.ToSingle(parameterValue);
// Ye ye none of that
if (parameter == 0f)
return 100f;
if (parameterValue == 0d)
return 100d;
return 100f / Convert.ToSingle(parameterValue) * Convert.ToSingle(currentValue);
return 100d / parameterValue * currentValue;
}
}
}

View File

@ -1,20 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class PowerModifierType : DataBindingModifierType
internal class PowerModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override string Name => "Power";
public override string Icon => "Exponent";
public override string Category => "Advanced";
public override string Description => "Raises the input value to the power of the parameter value";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
return Math.Pow(Convert.ToSingle(currentValue), Convert.ToSingle(parameterValue));
return Math.Pow(currentValue, parameterValue);
}
}
}

View File

@ -1,22 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class CeilingModifierType : DataBindingModifierType
internal class CeilingModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Round up";
public override string Icon => "ArrowUp";
public override string Category => "Rounding";
public override string Description => "Ceils the input, rounding it up to the nearest whole number";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
float floatValue = Convert.ToSingle(currentValue);
return Math.Ceiling(floatValue);
return Math.Ceiling(currentValue);
}
}
}

View File

@ -1,22 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class FloorModifierType : DataBindingModifierType
internal class FloorModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Round down";
public override string Icon => "ArrowDown";
public override string Category => "Rounding";
public override string Description => "Floors the input, rounding it down to the nearest whole number";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
float floatValue = Convert.ToSingle(currentValue);
return Math.Floor(floatValue);
return Math.Floor(currentValue);
}
}
}

View File

@ -1,22 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class RoundModifierType : DataBindingModifierType
internal class RoundModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Round";
public override string Icon => "ArrowCollapse";
public override string Category => "Rounding";
public override string Description => "Rounds the input to the nearest whole number";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
float floatValue = Convert.ToSingle(currentValue);
return Math.Round(floatValue, MidpointRounding.AwayFromZero);
return Math.Round(currentValue, MidpointRounding.AwayFromZero);
}
}
}

View File

@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class SquareRootModifierType : DataBindingModifierType
internal class SquareRootModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Square root";
public override string Icon => "SquareRoot";
public override string Category => "Advanced";
public override string Description => "Calculates square root of the input value";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
return Math.Sqrt(Convert.ToSingle(currentValue));
return Math.Sqrt(currentValue);
}
}
}

View File

@ -1,18 +1,13 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
namespace Artemis.Core.DefaultTypes
{
internal class SubtractModifierType : DataBindingModifierType
internal class SubtractModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override string Name => "Subtract";
public override string Icon => "Minus";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
return Convert.ToSingle(currentValue) - Convert.ToSingle(parameterValue);
return currentValue - parameterValue;
}
}
}

View File

@ -1,18 +1,13 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
namespace Artemis.Core.DefaultTypes
{
internal class SumModifierType : DataBindingModifierType
internal class SumModifierType : DataBindingModifierType<double, double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override string Name => "Sum";
public override string Icon => "Plus";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue, double parameterValue)
{
return Convert.ToSingle(currentValue) + Convert.ToSingle(parameterValue);
return currentValue + parameterValue;
}
}
}

View File

@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class CosecantModifierType : DataBindingModifierType
internal class CosecantModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Cosecant";
public override string Icon => null;
public override string Category => "Trigonometry";
public override string Description => "Treats the input as an angle and calculates the cosecant";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
return 1f / Math.Sin(Convert.ToSingle(currentValue));
return 1d / Math.Sin(currentValue);
}
}
}

View File

@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class CosineModifierType : DataBindingModifierType
internal class CosineModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Cosine";
public override string Icon => "MathCos";
public override string Category => "Trigonometry";
public override string Description => "Treats the input as an angle and calculates the cosine";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
return Math.Cos(Convert.ToSingle(currentValue));
return Math.Cos(currentValue);
}
}
}

View File

@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class CotangentModifierType : DataBindingModifierType
internal class CotangentModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Cotangent";
public override string Icon => null;
public override string Category => "Trigonometry";
public override string Description => "Treats the input as an angle and calculates the cotangent";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
return 1f / Math.Tan(Convert.ToSingle(currentValue));
return 1d / Math.Tan(currentValue);
}
}
}

View File

@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class SecantModifierType : DataBindingModifierType
internal class SecantModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Secant";
public override string Icon => null;
public override string Category => "Trigonometry";
public override string Description => "Treats the input as an angle and calculates the secant";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
return 1f / Math.Cos(Convert.ToSingle(currentValue));
return 1d / Math.Cos(currentValue);
}
}
}

View File

@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class SineModifierType : DataBindingModifierType
internal class SineModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Sine";
public override string Icon => "MathSin";
public override string Category => "Trigonometry";
public override string Description => "Treats the input as an angle and calculates the sine";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
return Math.Sin(Convert.ToSingle(currentValue));
return Math.Sin(currentValue);
}
}
}

View File

@ -1,21 +1,17 @@
using System;
using System.Collections.Generic;
namespace Artemis.Core.DefaultTypes
{
internal class TangentModifierType : DataBindingModifierType
internal class TangentModifierType : DataBindingModifierType<double>
{
public override IReadOnlyCollection<Type> CompatibleTypes => Constants.NumberTypes;
public override bool SupportsParameter => false;
public override string Name => "Tangent";
public override string Icon => "MathTan";
public override string Category => "Trigonometry";
public override string Description => "Treats the input as an angle and calculates the tangent";
public override object Apply(object currentValue, object parameterValue)
public override double Apply(double currentValue)
{
return Math.Tan(Convert.ToSingle(currentValue));
return Math.Tan(currentValue);
}
}
}

View File

@ -33,7 +33,7 @@ namespace Artemis.Core
public abstract Type LeftSideType { get; }
/// <summary>
/// Gets the right side type of this condition operator. May be null if the operator does not support a left side type
/// Gets the right side type of this condition operator. May be null if the operator does not support a right side
/// </summary>
public abstract Type? RightSideType { get; }
@ -42,7 +42,14 @@ namespace Artemis.Core
/// </summary>
/// <param name="type">The type to check for, must be either the same or be castable to the target type</param>
/// <param name="side">Which side of the operator to check, left or right</param>
public abstract bool SupportsType(Type type, ConditionParameterSide side);
public bool SupportsType(Type type, ConditionParameterSide side)
{
if (type == null)
return true;
if (side == ConditionParameterSide.Left)
return LeftSideType.IsCastableFrom(type);
return RightSideType != null && RightSideType.IsCastableFrom(type);
}
/// <summary>
/// Evaluates the condition with the input types being provided as objects

View File

@ -13,17 +13,7 @@ namespace Artemis.Core
/// <param name="a">The parameter on the left side of the expression</param>
/// <param name="b">The parameter on the right side of the expression</param>
public abstract bool Evaluate(TLeftSide a, TRightSide b);
/// <inheritdoc />
public override bool SupportsType(Type type, ConditionParameterSide side)
{
if (type == null)
return true;
if (side == ConditionParameterSide.Left)
return LeftSideType.IsCastableFrom(type);
return RightSideType.IsCastableFrom(type);
}
/// <inheritdoc />
internal override bool InternalEvaluate(object? leftSideValue, object? rightSideValue)
{
@ -40,7 +30,7 @@ namespace Artemis.Core
else
rightSide = default;
return Evaluate(leftSide, rightSide);
return Evaluate(leftSide!, rightSide!);
}
/// <inheritdoc />
@ -61,16 +51,6 @@ namespace Artemis.Core
/// <param name="a">The parameter on the left side of the expression</param>
public abstract bool Evaluate(TLeftSide a);
/// <inheritdoc />
public override bool SupportsType(Type type, ConditionParameterSide side)
{
if (type == null)
return true;
if (side == ConditionParameterSide.Left)
return LeftSideType.IsCastableFrom(type);
return false;
}
/// <inheritdoc />
internal override bool InternalEvaluate(object? leftSideValue, object? rightSideValue)
{
@ -81,7 +61,7 @@ namespace Artemis.Core
else
leftSide = default;
return Evaluate(leftSide);
return Evaluate(leftSide!);
}
/// <inheritdoc />

View File

@ -388,7 +388,7 @@ namespace Artemis.Core
return;
if (!Operator.SupportsType(RightStaticValue.GetType(), ConditionParameterSide.Right))
UpdateRightSideDynamic(null);
UpdateRightSideStatic(null);
}
}

View File

@ -144,7 +144,7 @@ namespace Artemis.Core
return;
}
// No need to clear compiled expressions, without a left data model they are already null
// No need to check for compatibility without a left side, when left site does get set it will be checked again
if (LeftPath == null || !LeftPath.IsValid)
{
Operator = conditionOperator;
@ -323,7 +323,7 @@ namespace Artemis.Core
return;
if (!Operator.SupportsType(RightStaticValue.GetType(), ConditionParameterSide.Right))
UpdateRightSideDynamic(null);
UpdateRightSideStatic(null);
}
}

View File

@ -1,79 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Artemis.Core
{
/// <summary>
/// A modifier that changes the source value of a data binding in some way
/// </summary>
public abstract class DataBindingModifierType
{
/// <summary>
/// Gets the plugin info this data binding modifier belongs to
/// <para>Note: Not set until after registering</para>
/// </summary>
public PluginInfo PluginInfo { get; internal set; }
/// <summary>
/// Gets the types this modifier supports
/// </summary>
public abstract IReadOnlyCollection<Type> CompatibleTypes { get; }
/// <summary>
/// Gets the supported parameter type
/// <para>If <c>null</c>, the parameter type will match the source property</para>
/// </summary>
public virtual Type ParameterType => null;
/// <summary>
/// Gets or sets whether this modifier supports a parameter, defaults to <c>true</c>
/// </summary>
public virtual bool SupportsParameter => true;
/// <summary>
/// Gets the name of this modifier
/// </summary>
public abstract string Name { get; }
/// <summary>
/// Gets or sets the icon of this modifier
/// </summary>
public abstract string Icon { get; }
/// <summary>
/// Gets the description of this modifier
/// </summary>
public virtual string Description => null;
/// <summary>
/// Gets the category of this modifier
/// </summary>
public virtual string Category => null;
/// <summary>
/// Returns whether the given type is supported by the modifier
/// </summary>
public bool SupportsType(Type type)
{
if (type == null)
return true;
return CompatibleTypes.Any(t => t.IsCastableFrom(type));
}
/// <summary>
/// Called whenever the modifier must apply to a specific value, must be a value of a type contained in
/// <see cref="CompatibleTypes" />
/// </summary>
/// <param name="currentValue">
/// The current value before modification, is always of a type contained in
/// <see cref="CompatibleTypes" />
/// </param>
/// <param name="parameterValue">
/// The parameter to use for the modification, is always of a type contained in
/// <see cref="CompatibleTypes" />
/// </param>
/// <returns>The modified value, must be a value of a type contained in <see cref="CompatibleTypes" /></returns>
public abstract object Apply(object currentValue, object parameterValue);
}
}

View File

@ -0,0 +1,82 @@
using System;
namespace Artemis.Core
{
/// <summary>
/// A modifier that changes the source value of a data binding in some way
/// <para>
/// To implement your own condition operator, inherit <see cref="DataBindingModifierType{TValue, TParameter}" /> or
/// <see cref="DataBindingModifierType{TValue}" />
/// </para>
/// </summary>
public abstract class BaseDataBindingModifierType
{
/// <summary>
/// Gets the plugin info this data binding modifier belongs to
/// <para>Note: Not set until after registering</para>
/// </summary>
public PluginInfo PluginInfo { get; internal set; }
/// <summary>
/// Gets the value type of this modifier type
/// </summary>
public abstract Type ValueType { get; }
/// <summary>
/// Gets the parameter type of this modifier type. May be null if the modifier type does not support a parameter
/// </summary>
public abstract Type? ParameterType { get; }
/// <summary>
/// Gets the name of this modifier
/// </summary>
public abstract string Name { get; }
/// <summary>
/// Gets or sets the icon of this modifier
/// </summary>
public abstract string Icon { get; }
/// <summary>
/// Gets the description of this modifier
/// </summary>
public virtual string Description => null;
/// <summary>
/// Gets the category of this modifier
/// </summary>
public virtual string Category => null;
/// <summary>
/// Returns whether the given type is supported by the modifier
/// </summary>
/// <param name="type">The type to check for, must be either the same or be castable to the target type</param>
/// <param name="part">Which part of the modifier to check, the value or the parameter</param>
public bool SupportsType(Type type, ModifierTypePart part)
{
if (type == null)
return true;
if (part == ModifierTypePart.Value)
return ValueType.IsCastableFrom(type);
return ParameterType != null && ParameterType.IsCastableFrom(type);
}
/// <summary>
/// Applies the modifier to the provided current value
/// <para>
/// This leaves the caller responsible for the types matching <see cref="ValueType" /> and
/// <see cref="ParameterType" />
/// </para>
/// </summary>
/// <param name="currentValue">The current value before modification, type should match <see cref="ValueType" /></param>
/// <param name="parameterValue">The parameter to use for the modification, type should match <see cref="ParameterType" /></param>
/// <returns>The modified value, with a type of <see cref="ValueType" /></returns>
internal abstract object? InternalApply(object? currentValue, object? parameterValue);
}
public enum ModifierTypePart
{
Value,
Parameter
}
}

View File

@ -30,7 +30,7 @@ namespace Artemis.Core
/// <summary>
/// Gets the type of modifier that is being applied
/// </summary>
public DataBindingModifierType ModifierType { get; private set; }
public BaseDataBindingModifierType? ModifierType { get; private set; }
/// <summary>
/// Gets the direct data binding this modifier is applied to
@ -40,7 +40,7 @@ namespace Artemis.Core
/// <summary>
/// Gets the type of the parameter, can either be dynamic (based on a data model value) or static
/// </summary>
public ProfileRightSideType ParameterType { get; private set; }
public ProfileRightSideType ParameterType { get; set; }
/// <summary>
/// Gets or sets the position at which the modifier appears on the data binding
@ -56,7 +56,7 @@ namespace Artemis.Core
/// Gets the parameter static value, only used it <see cref="ParameterType" /> is
/// <see cref="ProfileRightSideType.Static" />
/// </summary>
public object ParameterStaticValue { get; private set; }
public object? ParameterStaticValue { get; private set; }
internal DataBindingModifierEntity Entity { get; set; }
@ -65,7 +65,7 @@ namespace Artemis.Core
/// </summary>
/// <param name="currentValue">The value to apply the modifier to, should be of the same type as the data binding target</param>
/// <returns>The modified value</returns>
public object Apply(object? currentValue)
public object? Apply(object? currentValue)
{
if (_disposed)
throw new ObjectDisposedException("DataBindingModifier");
@ -73,17 +73,17 @@ namespace Artemis.Core
if (ModifierType == null)
return currentValue;
if (!ModifierType.SupportsParameter)
return ModifierType.Apply(currentValue, null);
if (ModifierType.ParameterType == null)
return ModifierType.InternalApply(currentValue, null);
if (ParameterType == ProfileRightSideType.Dynamic && ParameterPath != null && ParameterPath.IsValid)
{
object? value = ParameterPath.GetValue();
return ModifierType.Apply(currentValue, value);
return ModifierType.InternalApply(currentValue, value);
}
if (ParameterType == ProfileRightSideType.Static)
return ModifierType.Apply(currentValue, ParameterStaticValue);
return ModifierType.InternalApply(currentValue, ParameterStaticValue);
return currentValue;
}
@ -92,12 +92,11 @@ namespace Artemis.Core
/// Updates the modifier type of the modifier and re-compiles the expression
/// </summary>
/// <param name="modifierType"></param>
public void UpdateModifierType(DataBindingModifierType modifierType)
public void UpdateModifierType(BaseDataBindingModifierType? modifierType)
{
if (_disposed)
throw new ObjectDisposedException("DataBindingModifier");
// Calling CreateExpression will clear compiled expressions
if (modifierType == null)
{
ModifierType = null;
@ -105,11 +104,36 @@ namespace Artemis.Core
}
Type targetType = DirectDataBinding.DataBinding.GetTargetType();
if (!modifierType.SupportsType(targetType))
if (!modifierType.SupportsType(targetType, ModifierTypePart.Value))
throw new ArtemisCoreException($"Cannot apply modifier type {modifierType.GetType().Name} to this modifier because " +
$"it does not support this data binding's type {targetType.Name}");
ModifierType = modifierType;
ValidateParameter();
}
private void ValidateParameter()
{
if (ModifierType == null)
return;
if (ParameterType == ProfileRightSideType.Dynamic)
{
if (ParameterPath == null || !ParameterPath.IsValid)
return;
Type parameterType = ParameterPath.GetPropertyType()!;
if (!ModifierType.SupportsType(parameterType, ModifierTypePart.Parameter))
UpdateParameterDynamic(null);
}
else
{
if (ParameterStaticValue == null)
return;
if (!ModifierType.SupportsType(ParameterStaticValue.GetType(), ModifierTypePart.Parameter))
UpdateParameterStatic(null);
}
}
/// <summary>
@ -165,7 +189,7 @@ namespace Artemis.Core
// Modifier type
if (Entity.ModifierTypePluginGuid != null && ModifierType == null)
{
DataBindingModifierType modifierType = DataBindingModifierTypeStore.Get(Entity.ModifierTypePluginGuid.Value, Entity.ModifierType)?.DataBindingModifierType;
BaseDataBindingModifierType modifierType = DataBindingModifierTypeStore.Get(Entity.ModifierTypePluginGuid.Value, Entity.ModifierType)?.DataBindingModifierType;
if (modifierType != null)
UpdateModifierType(modifierType);
}
@ -261,7 +285,7 @@ namespace Artemis.Core
if (ModifierType != null)
return;
DataBindingModifierType modifierType = e.TypeRegistration.DataBindingModifierType;
BaseDataBindingModifierType modifierType = e.TypeRegistration.DataBindingModifierType;
if (modifierType.PluginInfo.Guid == Entity.ModifierTypePluginGuid && modifierType.GetType().Name == Entity.ModifierType)
UpdateModifierType(modifierType);
}

View File

@ -0,0 +1,81 @@
using System;
namespace Artemis.Core
{
/// <summary>
/// A modifier that changes the source value of a data binding in some way using a parameter
/// </summary>
public abstract class DataBindingModifierType<TValue, TParameter> : BaseDataBindingModifierType
{
/// <inheritdoc />
public override Type ValueType => typeof(TValue);
/// <inheritdoc />
public override Type ParameterType => typeof(TParameter);
/// <summary>
/// Called whenever the modifier must apply to a specific value
/// </summary>
/// <param name="currentValue">
/// The current value before modification
/// </param>
/// <param name="parameterValue">
/// The parameter to use for the modification
/// </param>
/// <returns>The modified value></returns>
public abstract TValue Apply(TValue currentValue, TParameter parameterValue);
/// <inheritdoc />
internal override object? InternalApply(object? currentValue, object? parameterValue)
{
// TODO: Can we avoid boxing/unboxing?
TValue current;
if (currentValue != null)
current = (TValue) Convert.ChangeType(currentValue, typeof(TValue));
else
current = default;
TParameter parameter;
if (parameterValue != null)
parameter = (TParameter) Convert.ChangeType(parameterValue, typeof(TParameter));
else
parameter = default;
return Apply(current!, parameter!);
}
}
/// <summary>
/// A modifier that changes the source value of a data binding in some way
/// </summary>
public abstract class DataBindingModifierType<TValue> : BaseDataBindingModifierType
{
/// <inheritdoc />
public override Type ValueType => typeof(TValue);
/// <inheritdoc />
public override Type? ParameterType => null;
/// <summary>
/// Called whenever the modifier must apply to a specific value
/// </summary>
/// <param name="currentValue">
/// The current value before modification
/// </param>
/// <returns>The modified value</returns>
public abstract TValue Apply(TValue currentValue);
/// <inheritdoc />
internal override object? InternalApply(object? currentValue, object? parameterValue)
{
// TODO: Can we avoid boxing/unboxing?
TValue current;
if (currentValue != null)
current = (TValue) Convert.ChangeType(currentValue, typeof(TValue));
else
current = default;
return Apply(current!);
}
}
}

View File

@ -12,7 +12,7 @@ namespace Artemis.Core.Services
RegisterBuiltInModifiers();
}
public DataBindingModifierTypeRegistration RegisterModifierType(PluginInfo pluginInfo, DataBindingModifierType dataBindingModifierType)
public DataBindingModifierTypeRegistration RegisterModifierType(PluginInfo pluginInfo, BaseDataBindingModifierType dataBindingModifierType)
{
if (pluginInfo == null)
throw new ArgumentNullException(nameof(pluginInfo));
@ -30,12 +30,12 @@ namespace Artemis.Core.Services
DataBindingModifierTypeStore.Remove(registration);
}
public List<DataBindingModifierType> GetCompatibleModifierTypes(Type type)
public List<BaseDataBindingModifierType> GetCompatibleModifierTypes(Type type, ModifierTypePart part)
{
return DataBindingModifierTypeStore.GetForType(type).Select(r => r.DataBindingModifierType).ToList();
return DataBindingModifierTypeStore.GetForType(type, part).Select(r => r.DataBindingModifierType).ToList();
}
public DataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType)
public BaseDataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType)
{
return DataBindingModifierTypeStore.Get(modifierTypePluginGuid, modifierType)?.DataBindingModifierType;
}

View File

@ -14,7 +14,7 @@ namespace Artemis.Core.Services
/// </summary>
/// <param name="pluginInfo">The PluginInfo of the plugin this modifier type belongs to</param>
/// <param name="dataBindingModifierType">The modifier type to register</param>
DataBindingModifierTypeRegistration RegisterModifierType([NotNull] PluginInfo pluginInfo, [NotNull] DataBindingModifierType dataBindingModifierType);
DataBindingModifierTypeRegistration RegisterModifierType([NotNull] PluginInfo pluginInfo, [NotNull] BaseDataBindingModifierType dataBindingModifierType);
/// <summary>
/// Removes a modifier type so it is no longer available for use in data bindings
@ -25,7 +25,7 @@ namespace Artemis.Core.Services
/// <summary>
/// Returns all the data binding modifier types compatible with the provided type
/// </summary>
List<DataBindingModifierType> GetCompatibleModifierTypes(Type type);
List<BaseDataBindingModifierType> GetCompatibleModifierTypes(Type type, ModifierTypePart part);
/// <summary>
/// Gets a modifier type by its plugin GUID and type name
@ -33,6 +33,6 @@ namespace Artemis.Core.Services
/// <param name="modifierTypePluginGuid">The modifier type's plugin GUID</param>
/// <param name="modifierType">The type name of the modifier type</param>
/// <returns></returns>
DataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType);
BaseDataBindingModifierType GetModifierType(Guid modifierTypePluginGuid, string modifierType);
}
}

View File

@ -8,7 +8,7 @@ namespace Artemis.Core
{
private static readonly List<DataBindingModifierTypeRegistration> Registrations = new List<DataBindingModifierTypeRegistration>();
public static DataBindingModifierTypeRegistration Add(DataBindingModifierType modifierType)
public static DataBindingModifierTypeRegistration Add(BaseDataBindingModifierType modifierType)
{
DataBindingModifierTypeRegistration typeRegistration;
lock (Registrations)
@ -46,19 +46,21 @@ namespace Artemis.Core
}
}
public static List<DataBindingModifierTypeRegistration> GetForType(Type type)
public static List<DataBindingModifierTypeRegistration> GetForType(Type type, ModifierTypePart part)
{
lock (Registrations)
{
if (type == null)
return new List<DataBindingModifierTypeRegistration>(Registrations);
List<DataBindingModifierTypeRegistration> candidates = Registrations.Where(r => r.DataBindingModifierType.CompatibleTypes.Any(t => t == type)).ToList();
List<DataBindingModifierTypeRegistration> candidates = Registrations.Where(r => r.DataBindingModifierType.SupportsType(type, part)).ToList();
// If there are multiple operators with the same description, use the closest match
// If there are multiple modifiers with the same description, use the closest match
foreach (IGrouping<string, DataBindingModifierTypeRegistration> displayDataBindingModifiers in candidates.GroupBy(r => r.DataBindingModifierType.Name).Where(g => g.Count() > 1).ToList())
{
DataBindingModifierTypeRegistration closest = displayDataBindingModifiers.OrderByDescending(r => r.DataBindingModifierType.CompatibleTypes.Contains(type)).FirstOrDefault();
DataBindingModifierTypeRegistration closest = part == ModifierTypePart.Value
? displayDataBindingModifiers.OrderByDescending(r => r.DataBindingModifierType.ValueType.ScoreCastability(type)).First()
: displayDataBindingModifiers.OrderByDescending(r => r.DataBindingModifierType.ParameterType!.ScoreCastability(type)).First();
foreach (DataBindingModifierTypeRegistration displayDataBindingModifier in displayDataBindingModifiers)
{
if (displayDataBindingModifier != closest)

View File

@ -7,7 +7,7 @@ namespace Artemis.Core
/// </summary>
public class DataBindingModifierTypeRegistration
{
internal DataBindingModifierTypeRegistration(DataBindingModifierType dataBindingModifierType, Plugin plugin)
internal DataBindingModifierTypeRegistration(BaseDataBindingModifierType dataBindingModifierType, Plugin plugin)
{
DataBindingModifierType = dataBindingModifierType;
Plugin = plugin;
@ -18,7 +18,7 @@ namespace Artemis.Core
/// <summary>
/// Gets the data binding modifier that has been registered
/// </summary>
public DataBindingModifierType DataBindingModifierType { get; }
public BaseDataBindingModifierType DataBindingModifierType { get; }
/// <summary>
/// Gets the plugin the data binding modifier is associated with

View File

@ -41,6 +41,8 @@
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource MaterialDesignFlatDarkBgButton}"
Background="{Binding SwitchButtonBrush}"
BorderBrush="{Binding SwitchButtonBrush}"
Height="22"
Padding="0"
Width="22"

View File

@ -7,6 +7,7 @@ using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Artemis.UI.Shared.Services;
using MaterialDesignColors.ColorManipulation;
using Stylet;
// Remove, annoying while working on it
@ -19,7 +20,7 @@ namespace Artemis.UI.Shared.Input
private readonly IDataModelUIService _dataModelUIService;
private readonly Module _module;
private readonly Timer _updateTimer;
private Brush _buttonBrush = new SolidColorBrush(Color.FromRgb(171, 71, 188));
private SolidColorBrush _buttonBrush = new SolidColorBrush(Color.FromRgb(171, 71, 188));
private DataModelPath _dataModelPath;
private DataModelPropertiesViewModel _dataModelViewModel;
private bool _displaySwitchButton;
@ -41,12 +42,18 @@ namespace Artemis.UI.Shared.Input
Initialize();
}
public Brush ButtonBrush
public SolidColorBrush ButtonBrush
{
get => _buttonBrush;
set => SetAndNotify(ref _buttonBrush, value);
set
{
if (!SetAndNotify(ref _buttonBrush, value)) return;
NotifyOfPropertyChange(nameof(SwitchButtonBrush));
}
}
public SolidColorBrush SwitchButtonBrush => new SolidColorBrush(ButtonBrush.Color.Darken());
public string Placeholder
{
get => _placeholder;

View File

@ -24,6 +24,8 @@
<Grid Margin="3 -4">
<StackPanel Orientation="Horizontal" Visibility="{Binding InputViewModel, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}">
<Button Style="{StaticResource MaterialDesignFlatDarkBgButton}"
Background="{Binding SwitchButtonBrush}"
BorderBrush="{Binding SwitchButtonBrush}"
Height="22"
Padding="0"
Width="22"
@ -32,7 +34,8 @@
Margin="0 0 -3 0"
HorizontalAlignment="Left"
ToolTip="Switch to data model value"
Command="{s:Action SwitchToDynamic}">
Command="{s:Action SwitchToDynamic}"
Visibility="{Binding DisplaySwitchButton, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<materialDesign:PackIcon Kind="SwapHorizontal" />
</Button>
<Button Style="{StaticResource DataModelConditionButton}"

View File

@ -6,6 +6,7 @@ using System.Windows.Media;
using Artemis.Core;
using Artemis.Core.DataModelExpansions;
using Artemis.UI.Shared.Services;
using MaterialDesignColors.ColorManipulation;
using Stylet;
namespace Artemis.UI.Shared.Input
@ -14,7 +15,7 @@ namespace Artemis.UI.Shared.Input
{
private readonly IDataModelUIService _dataModelUIService;
private readonly Window _rootView;
private Brush _buttonBrush = new SolidColorBrush(Color.FromRgb(171, 71, 188));
private SolidColorBrush _buttonBrush = new SolidColorBrush(Color.FromRgb(171, 71, 188));
private DataModelDisplayViewModel _displayViewModel;
private DataModelInputViewModel _inputViewModel;
private bool _isEnabled;
@ -22,6 +23,7 @@ namespace Artemis.UI.Shared.Input
private DataModelPropertyAttribute _targetDescription;
private Type _targetType;
private object _value;
private bool _displaySwitchButton;
internal DataModelStaticViewModel(Type targetType, DataModelPropertyAttribute targetDescription, IDataModelUIService dataModelUIService)
{
@ -40,12 +42,18 @@ namespace Artemis.UI.Shared.Input
}
}
public Brush ButtonBrush
public SolidColorBrush ButtonBrush
{
get => _buttonBrush;
set => SetAndNotify(ref _buttonBrush, value);
set
{
if (!SetAndNotify(ref _buttonBrush, value)) return;
NotifyOfPropertyChange(nameof(SwitchButtonBrush));
}
}
public SolidColorBrush SwitchButtonBrush => new SolidColorBrush(ButtonBrush.Color.Darken());
public DataModelDisplayViewModel DisplayViewModel
{
get => _displayViewModel;
@ -92,6 +100,12 @@ namespace Artemis.UI.Shared.Input
private set => SetAndNotify(ref _isEnabled, value);
}
public bool DisplaySwitchButton
{
get => _displaySwitchButton;
set => SetAndNotify(ref _displaySwitchButton, value);
}
public void ActivateInputViewModel()
{
InputViewModel = _dataModelUIService.GetDataModelInputViewModel(

View File

@ -275,7 +275,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
private void CreateRightSideSelectionViewModel()
{
RightSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
RightSideSelectionViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
RightSideSelectionViewModel.ButtonBrush = (SolidColorBrush) Application.Current.FindResource("PrimaryHueMidBrush");
RightSideSelectionViewModel.DisplaySwitchButton = true;
RightSideSelectionViewModel.PropertySelected += RightSideOnPropertySelected;
RightSideSelectionViewModel.SwitchToStaticRequested += RightSideSelectionViewModelOnSwitchToStaticRequested;
@ -289,7 +289,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
private void CreateRightSideInputViewModel(Type leftSideType)
{
RightSideInputViewModel = _dataModelUIService.GetStaticInputViewModel(leftSideType, LeftSideSelectionViewModel.DataModelPath?.GetPropertyDescription());
RightSideInputViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
RightSideInputViewModel.ButtonBrush = (SolidColorBrush) Application.Current.FindResource("PrimaryHueMidBrush");
RightSideInputViewModel.DisplaySwitchButton = true;
RightSideInputViewModel.ValueUpdated += RightSideOnValueEntered;
RightSideInputViewModel.SwitchToDynamicRequested += RightSideInputViewModelOnSwitchToDynamicRequested;
}

View File

@ -218,7 +218,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
private void CreateRightSideSelectionViewModel()
{
RightSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
RightSideSelectionViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
RightSideSelectionViewModel.ButtonBrush = (SolidColorBrush) Application.Current.FindResource("PrimaryHueMidBrush");
RightSideSelectionViewModel.DisplaySwitchButton = true;
RightSideSelectionViewModel.PropertySelected += RightSideOnPropertySelected;
RightSideSelectionViewModel.SwitchToStaticRequested += RightSideSelectionViewModelOnSwitchToStaticRequested;
@ -227,7 +227,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
private void CreateRightSideInputViewModel(Type leftSideType)
{
RightSideInputViewModel = _dataModelUIService.GetStaticInputViewModel(leftSideType, LeftSideSelectionViewModel.DataModelPath?.GetPropertyDescription());
RightSideInputViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
RightSideInputViewModel.ButtonBrush = (SolidColorBrush) Application.Current.FindResource("PrimaryHueMidBrush");
RightSideInputViewModel.DisplaySwitchButton = true;
RightSideInputViewModel.ValueUpdated += RightSideOnValueEntered;
RightSideInputViewModel.SwitchToDynamicRequested += RightSideInputViewModelOnSwitchToDynamicRequested;
}

View File

@ -24,7 +24,6 @@
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
@ -39,18 +38,8 @@
Command="{s:Action Delete}">
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
</Button>
<Button Grid.Column="1"
ToolTip="Swap modifier type to static/dynamic"
Style="{StaticResource MaterialDesignIconForegroundButton}"
HorizontalAlignment="Left"
Foreground="{StaticResource SecondaryAccentBrush}"
Width="25"
Height="25"
Command="{s:Action SwapType}">
<materialDesign:PackIcon Kind="SwapHorizontalVariant" Width="18" Height="18" />
</Button>
<Button Grid.Column="2"
Style="{StaticResource DataModelConditionButtonLeftClickMenu}"
Background="#7B7B7B"
BorderBrush="#7B7B7B"
@ -101,7 +90,7 @@
</Button>
<ContentControl Grid.Column="3" s:View.Model="{Binding DynamicSelectionViewModel}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
<ContentControl Grid.Column="3" s:View.Model="{Binding StaticInputViewModel}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
<ContentControl Grid.Column="2" s:View.Model="{Binding DynamicSelectionViewModel}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
<ContentControl Grid.Column="2" s:View.Model="{Binding StaticInputViewModel}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
</Grid>
</UserControl>

View File

@ -19,7 +19,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
private readonly IProfileEditorService _profileEditorService;
private DataModelDynamicViewModel _dynamicSelectionViewModel;
private ModifierTypeCategoryViewModel _modifierTypeViewModels;
private DataBindingModifierType _selectedModifierType;
private BaseDataBindingModifierType _selectedModifierType;
private DataModelStaticViewModel _staticInputViewModel;
public DataBindingModifierViewModel(DataBindingModifier<TLayerProperty, TProperty> modifier,
@ -50,7 +50,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
set => SetAndNotify(ref _modifierTypeViewModels, value);
}
public DataBindingModifierType SelectedModifierType
public BaseDataBindingModifierType SelectedModifierType
{
get => _selectedModifierType;
set => SetAndNotify(ref _selectedModifierType, value);
@ -68,41 +68,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
private set => SetAndNotify(ref _staticInputViewModel, value);
}
public void Dispose()
{
if (DynamicSelectionViewModel != null)
{
DynamicSelectionViewModel.Dispose();
DynamicSelectionViewModel.PropertySelected -= ParameterSelectionViewModelOnPropertySelected;
}
if (StaticInputViewModel != null)
{
StaticInputViewModel.Dispose();
StaticInputViewModel.ValueUpdated -= StaticInputViewModelOnValueUpdated;
}
}
public void Delete()
{
Modifier.DirectDataBinding.RemoveModifier(Modifier);
_profileEditorService.UpdateSelectedProfileElement();
}
public void SwapType()
{
if (Modifier.ParameterType == ProfileRightSideType.Dynamic)
{
Type sourceType = Modifier.DirectDataBinding.GetSourceType();
Modifier.UpdateParameterStatic((Modifier.ModifierType.ParameterType ?? sourceType).GetDefault());
}
else
Modifier.UpdateParameterDynamic(null);
Update();
_profileEditorService.UpdateSelectedProfileElement();
}
private void ParameterSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
{
Modifier.UpdateParameterDynamic(e.DataModelPath);
@ -121,39 +92,39 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
if (sourceType == null)
throw new ArtemisUIException("Cannot use a data binding modifier VM for a data binding without a source");
if (DynamicSelectionViewModel != null)
if (Modifier.ModifierType == null || Modifier.ModifierType.ParameterType == null)
{
DynamicSelectionViewModel.Dispose();
DynamicSelectionViewModel.PropertySelected -= ParameterSelectionViewModelOnPropertySelected;
}
if (Modifier.ModifierType == null || !Modifier.ModifierType.SupportsParameter)
{
StaticInputViewModel = null;
DynamicSelectionViewModel = null;
DisposeDynamicSelectionViewModel();
DisposeStaticInputViewModel();
}
else if (Modifier.ParameterType == ProfileRightSideType.Dynamic)
{
StaticInputViewModel = null;
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
{
DynamicSelectionViewModel = null;
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 ModifierTypeCategoryViewModel(null, null);
IEnumerable<IGrouping<string, DataBindingModifierType>> modifierTypes = _dataBindingService.GetCompatibleModifierTypes(sourceType).GroupBy(t => t.Category);
foreach (IGrouping<string, DataBindingModifierType> dataBindingModifierTypes in modifierTypes)
IEnumerable<IGrouping<string, BaseDataBindingModifierType>> modifierTypes = _dataBindingService.GetCompatibleModifierTypes(sourceType, ModifierTypePart.Value).GroupBy(t => t.Category);
foreach (IGrouping<string, BaseDataBindingModifierType> dataBindingModifierTypes in modifierTypes)
{
IEnumerable<ModifierTypeViewModel> viewModels = dataBindingModifierTypes.Select(t => new ModifierTypeViewModel(t));
if (dataBindingModifierTypes.Key == null)
@ -182,5 +153,53 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
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;
Update();
}
private void StaticInputViewModelOnSwitchToDynamicRequested(object? sender, EventArgs e)
{
Modifier.ParameterType = ProfileRightSideType.Dynamic;
Update();
}
#endregion
}
}

View File

@ -4,11 +4,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDa
{
public class ModifierTypeViewModel : IModifierTypeViewModel
{
public ModifierTypeViewModel(DataBindingModifierType modifierType)
public ModifierTypeViewModel(BaseDataBindingModifierType modifierType)
{
ModifierType = modifierType;
}
public DataBindingModifierType ModifierType { get; set; }
public BaseDataBindingModifierType ModifierType { get; set; }
}
}