diff --git a/src/Artemis.Core/Constants.cs b/src/Artemis.Core/Constants.cs index c95a2be2e..f6226c541 100644 --- a/src/Artemis.Core/Constants.cs +++ b/src/Artemis.Core/Constants.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using Artemis.Core.Plugins.Models; @@ -6,9 +7,42 @@ namespace Artemis.Core { public static class Constants { + /// + /// The full path to the Artemis application folder + /// public static readonly string ApplicationFolder = Path.GetDirectoryName(typeof(Constants).Assembly.Location); + + /// + /// The full path to the Artemis data folder + /// public static readonly string DataFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Artemis\\"; + + /// + /// The connection string used to connect to the database + /// public static readonly string ConnectionString = $"FileName={DataFolder}\\database.db"; + + /// + /// The plugin info used by core components of Artemis + /// public static readonly PluginInfo CorePluginInfo = new PluginInfo {Guid = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), Name = "Artemis Core"}; + + /// + /// A read-only collection containing all primitive number types + /// + public static IReadOnlyCollection NumberTypes = new List + { + typeof(sbyte), + typeof(byte), + typeof(short), + typeof(ushort), + typeof(int), + typeof(uint), + typeof(long), + typeof(ulong), + typeof(float), + typeof(double), + typeof(decimal) + }; } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionOperator.cs b/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionOperator.cs index 895da9a24..e8eeb4ee5 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionOperator.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionOperator.cs @@ -10,24 +10,6 @@ namespace Artemis.Core.Models.Profile.Conditions { public abstract class DisplayConditionOperator { - /// - /// A read-only collection containing all primitive number types - /// - protected static IReadOnlyCollection NumberTypes = new List - { - typeof(sbyte), - typeof(byte), - typeof(short), - typeof(ushort), - typeof(int), - typeof(uint), - typeof(long), - typeof(ulong), - typeof(float), - typeof(double), - typeof(decimal) - }; - private IDataModelService _dataModelService; private bool _registered; diff --git a/src/Artemis.Core/Models/Profile/Conditions/Operators/GreaterThanConditionOperator.cs b/src/Artemis.Core/Models/Profile/Conditions/Operators/GreaterThanConditionOperator.cs index 058305ab7..a8fa3adb4 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/Operators/GreaterThanConditionOperator.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/Operators/GreaterThanConditionOperator.cs @@ -6,7 +6,7 @@ namespace Artemis.Core.Models.Profile.Conditions.Operators { public class GreaterThanConditionOperator : DisplayConditionOperator { - public override IReadOnlyCollection CompatibleTypes => NumberTypes; + public override IReadOnlyCollection CompatibleTypes => Constants.NumberTypes; public override string Description => "Is greater than"; public override string Icon => "GreaterThan"; diff --git a/src/Artemis.Core/Models/Profile/Conditions/Operators/GreaterThanOrEqualConditionOperator.cs b/src/Artemis.Core/Models/Profile/Conditions/Operators/GreaterThanOrEqualConditionOperator.cs index a40aefcbc..9b428c0cf 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/Operators/GreaterThanOrEqualConditionOperator.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/Operators/GreaterThanOrEqualConditionOperator.cs @@ -6,7 +6,7 @@ namespace Artemis.Core.Models.Profile.Conditions.Operators { public class GreaterThanOrEqualConditionOperator : DisplayConditionOperator { - public override IReadOnlyCollection CompatibleTypes => NumberTypes; + public override IReadOnlyCollection CompatibleTypes => Constants.NumberTypes; public override string Description => "Is greater than or equal to"; public override string Icon => "GreaterThanOrEqual"; diff --git a/src/Artemis.Core/Models/Profile/Conditions/Operators/LessThanConditionOperator.cs b/src/Artemis.Core/Models/Profile/Conditions/Operators/LessThanConditionOperator.cs index 1ce2f1e3c..2a9ba1310 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/Operators/LessThanConditionOperator.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/Operators/LessThanConditionOperator.cs @@ -6,7 +6,7 @@ namespace Artemis.Core.Models.Profile.Conditions.Operators { public class LessThanConditionOperator : DisplayConditionOperator { - public override IReadOnlyCollection CompatibleTypes => NumberTypes; + public override IReadOnlyCollection CompatibleTypes => Constants.NumberTypes; public override string Description => "Is less than"; public override string Icon => "LessThan"; diff --git a/src/Artemis.Core/Models/Profile/Conditions/Operators/LessThanOrEqualConditionOperator.cs b/src/Artemis.Core/Models/Profile/Conditions/Operators/LessThanOrEqualConditionOperator.cs index cd2d75ccb..d01fe5d1b 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/Operators/LessThanOrEqualConditionOperator.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/Operators/LessThanOrEqualConditionOperator.cs @@ -6,7 +6,7 @@ namespace Artemis.Core.Models.Profile.Conditions.Operators { public class LessThanOrEqualConditionOperator : DisplayConditionOperator { - public override IReadOnlyCollection CompatibleTypes => NumberTypes; + public override IReadOnlyCollection CompatibleTypes => Constants.NumberTypes; public override string Description => "Is less than or equal to"; public override string Icon => "LessThanOrEqual"; diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs index 216cb829a..fd4fe4b38 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs @@ -1,9 +1,12 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Data; using System.Windows.Input; using Artemis.Core.Plugins.Abstract.DataModels.Attributes; +using Artemis.UI.Shared.Exceptions; using Stylet; namespace Artemis.UI.Shared.DataModelVisualization @@ -38,11 +41,29 @@ namespace Artemis.UI.Shared.DataModelVisualization } /// - public sealed override void Cancel() + public sealed override void Cancel() { OnCancel(); UpdateCallback(InputValue, false); } + + /// + /// May be called to convert an object to one of the types defined in CompatibleConversionTypes + /// + /// The object to convert, will always be of a type contained in CompatibleConversionTypes + /// The converted value + protected virtual T ConvertToSupportedType(object source) + { + return default; + } + + internal override object InternalConvertToSupportedType(object source) + { + if (CompatibleConversionTypes != null && CompatibleConversionTypes.Contains(source.GetType())) + return ConvertToSupportedType(source); + + throw new ArtemisSharedUIException($"Cannot convert source of type {source.GetType().Name} because the data model input view model does not support it."); + } } /// @@ -58,6 +79,11 @@ namespace Artemis.UI.Shared.DataModelVisualization internal Action UpdateCallback { get; set; } + /// + /// Gets the types this input view model can support through type conversion + /// + internal IReadOnlyCollection CompatibleConversionTypes { get; set; } + public void AttachView(UIElement view) { if (View != null) @@ -98,5 +124,7 @@ namespace Artemis.UI.Shared.DataModelVisualization protected virtual void OnCancel() { } + + internal abstract object InternalConvertToSupportedType(object source); } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelVisualizationRegistration.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelVisualizationRegistration.cs index 6aa9c65f1..2b5b3b9cf 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelVisualizationRegistration.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelVisualizationRegistration.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Artemis.Core; using Artemis.Core.Plugins.Models; using Artemis.UI.Shared.Services; @@ -30,6 +31,8 @@ namespace Artemis.UI.Shared.DataModelVisualization public Type SupportedType { get; } public Type ViewModelType { get; } + public IReadOnlyCollection CompatibleConversionTypes { get; internal set; } + internal void Unsubscribe() { if (PluginInfo != Constants.CorePluginInfo) diff --git a/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs b/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs index 3623a5631..af9ba6a06 100644 --- a/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs +++ b/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs @@ -64,7 +64,7 @@ namespace Artemis.UI.Shared.Services return _dataModelService.GetPluginExtendsDataModel(plugin); } - public DataModelVisualizationRegistration RegisterDataModelInput(PluginInfo pluginInfo) where T : DataModelInputViewModel + public DataModelVisualizationRegistration RegisterDataModelInput(PluginInfo pluginInfo, IReadOnlyCollection compatibleConversionTypes) where T : DataModelInputViewModel { var viewModelType = typeof(T); lock (_registeredDataModelEditors) @@ -80,7 +80,14 @@ namespace Artemis.UI.Shared.Services } _kernel.Bind(viewModelType).ToSelf(); - var registration = new DataModelVisualizationRegistration(this, RegistrationType.Input, pluginInfo, supportedType, viewModelType); + + // Create the registration + var registration = new DataModelVisualizationRegistration(this, RegistrationType.Input, pluginInfo, supportedType, viewModelType) + { + // Apply the compatible conversion types to the registration + CompatibleConversionTypes = compatibleConversionTypes + }; + _registeredDataModelEditors.Add(registration); return registration; } @@ -154,16 +161,7 @@ namespace Artemis.UI.Shared.Services var match = _registeredDataModelEditors.FirstOrDefault(d => d.SupportedType == propertyType); if (match != null) { - // The view models expecting value types shouldn't be given null, avoid that - if (initialValue == null && propertyType.IsValueType) - initialValue = Activator.CreateInstance(propertyType); - - var parameters = new IParameter[] - { - new ConstructorArgument("description", description), - new ConstructorArgument("initialValue", initialValue) - }; - var viewModel = (DataModelInputViewModel) _kernel.Get(match.ViewModelType, parameters); + var viewModel = InstantiateDataModelInputViewModel(match, description, initialValue); viewModel.UpdateCallback = updateCallback; return viewModel; } @@ -171,6 +169,22 @@ namespace Artemis.UI.Shared.Services return null; } } + + private DataModelInputViewModel InstantiateDataModelInputViewModel(DataModelVisualizationRegistration registration, DataModelPropertyAttribute description, object initialValue) + { + // The view models expecting value types shouldn't be given null, avoid that + if (initialValue == null && registration.SupportedType.IsValueType) + initialValue = Activator.CreateInstance(registration.SupportedType); + + var parameters = new IParameter[] + { + new ConstructorArgument("description", description), + new ConstructorArgument("initialValue", initialValue) + }; + var viewModel = (DataModelInputViewModel) _kernel.Get(registration.ViewModelType, parameters); + viewModel.CompatibleConversionTypes = registration.CompatibleConversionTypes; + return viewModel; + } } public interface IDataModelVisualizationService : IArtemisSharedUIService @@ -185,7 +199,7 @@ namespace Artemis.UI.Shared.Services /// bool GetPluginExtendsDataModel(Plugin plugin); - DataModelVisualizationRegistration RegisterDataModelInput(PluginInfo pluginInfo) where T : DataModelInputViewModel; + DataModelVisualizationRegistration RegisterDataModelInput(PluginInfo pluginInfo, IReadOnlyCollection compatibleConversionTypes) where T : DataModelInputViewModel; DataModelVisualizationRegistration RegisterDataModelDisplay(PluginInfo pluginInfo) where T : DataModelDisplayViewModel; void RemoveDataModelInput(DataModelVisualizationRegistration registration); void RemoveDataModelDisplay(DataModelVisualizationRegistration registration); diff --git a/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputView.xaml b/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputView.xaml index 0fef737eb..5f8a5dce0 100644 --- a/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputView.xaml +++ b/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputView.xaml @@ -3,8 +3,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:local="clr-namespace:Artemis.UI.DataModelVisualization.Input" - xmlns:System="clr-namespace:System;assembly=System.Runtime" xmlns:b="http://schemas.microsoft.com/xaml/behaviors" xmlns:behaviors="clr-namespace:Artemis.UI.Shared.Behaviors;assembly=Artemis.UI.Shared" xmlns:s="https://github.com/canton7/Stylet" diff --git a/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputViewModel.cs b/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputViewModel.cs index 5b9548213..e93d731c4 100644 --- a/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputViewModel.cs +++ b/src/Artemis.UI/DataModelVisualization/Input/DoubleDataModelInputViewModel.cs @@ -2,6 +2,7 @@ using System.Windows.Input; using Artemis.Core.Plugins.Abstract.DataModels.Attributes; using Artemis.UI.Shared.DataModelVisualization; +using FluentValidation.TestHelper; namespace Artemis.UI.DataModelVisualization.Input { diff --git a/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputView.xaml b/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputView.xaml index f7062c072..6f36a7116 100644 --- a/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputView.xaml +++ b/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputView.xaml @@ -3,8 +3,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:local="clr-namespace:Artemis.UI.DataModelVisualization.Input" - xmlns:System="clr-namespace:System;assembly=System.Runtime" xmlns:b="http://schemas.microsoft.com/xaml/behaviors" xmlns:behaviors="clr-namespace:Artemis.UI.Shared.Behaviors;assembly=Artemis.UI.Shared" xmlns:s="https://github.com/canton7/Stylet" diff --git a/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputViewModel.cs b/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputViewModel.cs index ccd780489..170244d4f 100644 --- a/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputViewModel.cs +++ b/src/Artemis.UI/DataModelVisualization/Input/IntDataModelInputViewModel.cs @@ -1,4 +1,5 @@ -using System.Text.RegularExpressions; +using System; +using System.Text.RegularExpressions; using System.Windows.Input; using Artemis.Core.Plugins.Abstract.DataModels.Attributes; using Artemis.UI.Shared.DataModelVisualization; @@ -16,5 +17,10 @@ namespace Artemis.UI.DataModelVisualization.Input var regex = new Regex("[^0-9]+"); e.Handled = regex.IsMatch(e.Text); } + + protected override int ConvertToSupportedType(object source) + { + return Convert.ToInt32(source); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/DataModelVisualization/Input/StringDataModelInputView.xaml b/src/Artemis.UI/DataModelVisualization/Input/StringDataModelInputView.xaml index 406a9d5dc..a184aad11 100644 --- a/src/Artemis.UI/DataModelVisualization/Input/StringDataModelInputView.xaml +++ b/src/Artemis.UI/DataModelVisualization/Input/StringDataModelInputView.xaml @@ -3,8 +3,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:local="clr-namespace:Artemis.UI.DataModelVisualization.Input" - xmlns:System="clr-namespace:System;assembly=System.Runtime" xmlns:b="http://schemas.microsoft.com/xaml/behaviors" xmlns:behaviors="clr-namespace:Artemis.UI.Shared.Behaviors;assembly=Artemis.UI.Shared" mc:Ignorable="d" diff --git a/src/Artemis.UI/Services/RegistrationService.cs b/src/Artemis.UI/Services/RegistrationService.cs index af85d07a4..878dcc776 100644 --- a/src/Artemis.UI/Services/RegistrationService.cs +++ b/src/Artemis.UI/Services/RegistrationService.cs @@ -37,9 +37,9 @@ namespace Artemis.UI.Services if (_registeredBuiltInDataModelInputs) return; - _dataModelVisualizationService.RegisterDataModelInput(Constants.CorePluginInfo); - _dataModelVisualizationService.RegisterDataModelInput(Constants.CorePluginInfo); - _dataModelVisualizationService.RegisterDataModelInput(Constants.CorePluginInfo); + _dataModelVisualizationService.RegisterDataModelInput(Constants.CorePluginInfo, Constants.NumberTypes); + _dataModelVisualizationService.RegisterDataModelInput(Constants.CorePluginInfo, Constants.NumberTypes); + _dataModelVisualizationService.RegisterDataModelInput(Constants.CorePluginInfo, Constants.NumberTypes); _registeredBuiltInDataModelInputs = true; } diff --git a/src/Artemis.UI/Utilities/WindowState.cs b/src/Artemis.UI/Utilities/WindowState.cs index cde656696..4e92badcb 100644 --- a/src/Artemis.UI/Utilities/WindowState.cs +++ b/src/Artemis.UI/Utilities/WindowState.cs @@ -1,4 +1,5 @@ -using System.Windows; +using System; +using System.Windows; using MaterialDesignExtensions.Controls; namespace Artemis.UI.Utilities @@ -22,8 +23,8 @@ namespace Artemis.UI.Utilities public void ApplyToWindow(MaterialWindow window) { - window.Top = Top; - window.Left = Left; + window.Top = Math.Max(0, Top); + window.Left = Math.Max(0, Left); window.Height = Height; window.Width = Width; window.WindowState = IsMaximized ? WindowState.Maximized : WindowState.Normal;