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

Core - Fixed a lot of compiler warnings

Scripting - Added script renaming/deleting
This commit is contained in:
Robert 2021-06-21 19:34:34 +02:00
parent 4a69baebb7
commit 5367027471
36 changed files with 434 additions and 96 deletions

View File

@ -46,7 +46,7 @@ namespace Artemis.Core
/// </param> /// </param>
/// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns> /// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns>
[NotifyPropertyChangedInvocator] [NotifyPropertyChangedInvocator]
protected virtual bool SetAndNotify<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) protected virtual bool SetAndNotify<T>(ref T storage, T value, [CallerMemberName] string? propertyName = null)
{ {
if (!RequiresUpdate(ref storage, value)) return false; if (!RequiresUpdate(ref storage, value)) return false;
@ -64,7 +64,7 @@ namespace Artemis.Core
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute" /> /// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute" />
/// . /// .
/// </param> /// </param>
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{ {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }

View File

@ -9,6 +9,9 @@ namespace Artemis.Core
/// </summary> /// </summary>
public class CategoryAdaptionHint : IAdaptionHint public class CategoryAdaptionHint : IAdaptionHint
{ {
/// <summary>
/// Creates a new instance of the <see cref="CategoryAdaptionHint" /> class
/// </summary>
public CategoryAdaptionHint() public CategoryAdaptionHint()
{ {
} }
@ -41,6 +44,12 @@ namespace Artemis.Core
/// </summary> /// </summary>
public int Amount { get; set; } public int Amount { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"Category adaption - {nameof(Category)}: {Category}, {nameof(Skip)}: {Skip}, {nameof(LimitAmount)}: {LimitAmount}, {nameof(Amount)}: {Amount}";
}
#region Implementation of IAdaptionHint #region Implementation of IAdaptionHint
/// <inheritdoc /> /// <inheritdoc />
@ -65,11 +74,5 @@ namespace Artemis.Core
} }
#endregion #endregion
/// <inheritdoc />
public override string ToString()
{
return $"Category adaption - {nameof(Category)}: {Category}, {nameof(Skip)}: {Skip}, {nameof(LimitAmount)}: {LimitAmount}, {nameof(Amount)}: {Amount}";
}
} }
} }

View File

@ -10,6 +10,9 @@ namespace Artemis.Core
/// </summary> /// </summary>
public class DeviceAdaptionHint : IAdaptionHint public class DeviceAdaptionHint : IAdaptionHint
{ {
/// <summary>
/// Creates a new instance of the <see cref="DeviceAdaptionHint" /> class
/// </summary>
public DeviceAdaptionHint() public DeviceAdaptionHint()
{ {
} }

View File

@ -18,6 +18,9 @@ namespace Artemis.Core
{KeyboardSection.Extra, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_Custom1 && l <= LedId.Keyboard_Custom64).ToList()} {KeyboardSection.Extra, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_Custom1 && l <= LedId.Keyboard_Custom64).ToList()}
}; };
/// <summary>
/// Creates a new instance of the <see cref="KeyboardSectionAdaptionHint" /> class
/// </summary>
public KeyboardSectionAdaptionHint() public KeyboardSectionAdaptionHint()
{ {
} }

View File

@ -421,7 +421,7 @@ namespace Artemis.Core
{ {
if (keyframeEntity.Position > ProfileElement.Timeline.Length) if (keyframeEntity.Position > ProfileElement.Timeline.Length)
return null; return null;
T value = CoreJson.DeserializeObject<T>(keyframeEntity.Value); T? value = CoreJson.DeserializeObject<T>(keyframeEntity.Value);
if (value == null) if (value == null)
return null; return null;

View File

@ -28,6 +28,7 @@ namespace Artemis.Core
internal ProfileCategory(ProfileCategoryEntity entity) internal ProfileCategory(ProfileCategoryEntity entity)
{ {
_name = null!;
Entity = entity; Entity = entity;
Load(); Load();
} }

View File

@ -1,7 +1,4 @@
using System; using System.IO;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.Storage; using Artemis.Storage;
using Artemis.Storage.Migrations.Interfaces; using Artemis.Storage.Migrations.Interfaces;

View File

@ -15,7 +15,7 @@ namespace Artemis.Core.Modules
/// <summary> /// <summary>
/// Gets or sets the current value of the dynamic child /// Gets or sets the current value of the dynamic child
/// </summary> /// </summary>
public new T Value { get; set; } public T Value { get; set; }
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetValue() protected override object? GetValue()

View File

@ -66,6 +66,9 @@ namespace Artemis.Core
/// </summary> /// </summary>
public ReadOnlyCollection<PluginFeatureInfo> Features => _features.AsReadOnly(); public ReadOnlyCollection<PluginFeatureInfo> Features => _features.AsReadOnly();
/// <summary>
/// Gets a read-only collection of profiles running on the plugin
/// </summary>
public ReadOnlyCollection<Profiler> Profilers => _profilers.AsReadOnly(); public ReadOnlyCollection<Profiler> Profilers => _profilers.AsReadOnly();
/// <summary> /// <summary>

View File

@ -51,6 +51,7 @@ namespace Artemis.Core
if (instance == null) throw new ArgumentNullException(nameof(instance)); if (instance == null) throw new ArgumentNullException(nameof(instance));
Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin)); Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin));
FeatureType = instance.GetType(); FeatureType = instance.GetType();
Entity = new PluginFeatureEntity();
Name = attribute?.Name ?? instance.GetType().Name.Humanize(LetterCasing.Title); Name = attribute?.Name ?? instance.GetType().Name.Humanize(LetterCasing.Title);
Description = attribute?.Description; Description = attribute?.Description;

View File

@ -9,10 +9,10 @@ namespace Artemis.Core
{ {
private long _current; private long _current;
private DateTime _lastReport; private DateTime _lastReport;
private long _lastReportValue;
private double _percentage; private double _percentage;
private double _progressPerSecond; private double _progressPerSecond;
private long _total; private long _total;
private long _lastReportValue;
/// <summary> /// <summary>
/// The current amount /// The current amount
@ -81,6 +81,9 @@ namespace Artemis.Core
/// </summary> /// </summary>
public event EventHandler? ProgressReported; public event EventHandler? ProgressReported;
/// <summary>
/// Invokes the <see cref="ProgressReported" /> event
/// </summary>
protected virtual void OnProgressReported() protected virtual void OnProgressReported()
{ {
ProgressReported?.Invoke(this, EventArgs.Empty); ProgressReported?.Invoke(this, EventArgs.Empty);

View File

@ -1,4 +1,5 @@
using Artemis.Storage.Entities.General; using System;
using Artemis.Storage.Entities.General;
namespace Artemis.Core.ScriptingProviders namespace Artemis.Core.ScriptingProviders
{ {
@ -7,24 +8,26 @@ namespace Artemis.Core.ScriptingProviders
/// </summary> /// </summary>
public class ScriptConfiguration : CorePropertyChanged, IStorageModel public class ScriptConfiguration : CorePropertyChanged, IStorageModel
{ {
private string _scriptingProviderId; private bool _hasChanges;
private string _name; private string _name;
private string? _pendingScriptContent;
private string? _scriptContent; private string? _scriptContent;
private string _scriptingProviderId;
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ScriptConfiguration" /> class /// Creates a new instance of the <see cref="ScriptConfiguration" /> class
/// </summary> /// </summary>
public ScriptConfiguration(ScriptingProvider provider, string name) public ScriptConfiguration(ScriptingProvider provider, string name)
{ {
ScriptingProviderId = provider.Id; _scriptingProviderId = provider.Id;
Name = name; _name = name;
Entity = new ScriptConfigurationEntity(); Entity = new ScriptConfigurationEntity();
} }
internal ScriptConfiguration(ScriptConfigurationEntity entity) internal ScriptConfiguration(ScriptConfigurationEntity entity)
{ {
ScriptingProviderId = null!; _scriptingProviderId = null!;
Name = null!; _name = null!;
Entity = entity; Entity = entity;
Load(); Load();
@ -54,7 +57,36 @@ namespace Artemis.Core.ScriptingProviders
public string? ScriptContent public string? ScriptContent
{ {
get => _scriptContent; get => _scriptContent;
set => SetAndNotify(ref _scriptContent, value); private set
{
if (!SetAndNotify(ref _scriptContent, value)) return;
OnScriptContentChanged();
}
}
/// <summary>
/// Gets or sets the pending changes to the script's content
/// </summary>
public string? PendingScriptContent
{
get => _pendingScriptContent;
set
{
if (string.IsNullOrWhiteSpace(value))
value = null;
if (!SetAndNotify(ref _pendingScriptContent, value)) return;
HasChanges = ScriptContent != PendingScriptContent;
}
}
/// <summary>
/// Gets or sets a boolean indicating whether this configuration has pending changes to it's
/// <see cref="ScriptContent" />
/// </summary>
public bool HasChanges
{
get => _hasChanges;
set => SetAndNotify(ref _hasChanges, value);
} }
/// <summary> /// <summary>
@ -64,6 +96,24 @@ namespace Artemis.Core.ScriptingProviders
internal ScriptConfigurationEntity Entity { get; } internal ScriptConfigurationEntity Entity { get; }
/// <summary>
/// Applies the <see cref="PendingScriptContent" /> to the <see cref="ScriptContent" />
/// </summary>
public void ApplyPendingChanges()
{
ScriptContent = PendingScriptContent;
HasChanges = false;
}
/// <summary>
/// Discards the <see cref="PendingScriptContent" />
/// </summary>
public void DiscardPendingChanges()
{
PendingScriptContent = ScriptContent;
HasChanges = false;
}
#region Implementation of IStorageModel #region Implementation of IStorageModel
/// <inheritdoc /> /// <inheritdoc />
@ -71,6 +121,7 @@ namespace Artemis.Core.ScriptingProviders
{ {
ScriptingProviderId = Entity.ScriptingProviderId; ScriptingProviderId = Entity.ScriptingProviderId;
ScriptContent = Entity.ScriptContent; ScriptContent = Entity.ScriptContent;
PendingScriptContent = Entity.ScriptContent;
Name = Entity.Name; Name = Entity.Name;
} }
@ -79,6 +130,24 @@ namespace Artemis.Core.ScriptingProviders
{ {
Entity.ScriptingProviderId = ScriptingProviderId; Entity.ScriptingProviderId = ScriptingProviderId;
Entity.ScriptContent = ScriptContent; Entity.ScriptContent = ScriptContent;
Entity.Name = Name;
}
#endregion
#region Events
/// <summary>
/// Occurs whenever the contents of the script have changed
/// </summary>
public event EventHandler? ScriptContentChanged;
/// <summary>
/// Invokes the <see cref="ScriptContentChanged" /> event
/// </summary>
protected virtual void OnScriptContentChanged()
{
ScriptContentChanged?.Invoke(this, EventArgs.Empty);
} }
#endregion #endregion

View File

@ -37,6 +37,19 @@ namespace Artemis.Core.ScriptingProviders
/// <param name="script">The script the editor must edit</param> /// <param name="script">The script the editor must edit</param>
public abstract IScriptEditorViewModel CreatePropertyScriptEditor(TPropertyScript script); public abstract IScriptEditorViewModel CreatePropertyScriptEditor(TPropertyScript script);
#region Overrides of PluginFeature
/// <inheritdoc />
internal override void InternalDisable()
{
base.InternalDisable();
while (Scripts.Count > 0)
Scripts[0].Dispose();
}
#endregion
#region Overrides of ScriptingProvider #region Overrides of ScriptingProvider
/// <inheritdoc /> /// <inheritdoc />
@ -104,19 +117,6 @@ namespace Artemis.Core.ScriptingProviders
} }
#endregion #endregion
#region Overrides of PluginFeature
/// <inheritdoc />
internal override void InternalDisable()
{
base.InternalDisable();
while (Scripts.Count > 0)
Scripts[0].Dispose();
}
#endregion
} }
/// <summary> /// <summary>
@ -128,17 +128,22 @@ namespace Artemis.Core.ScriptingProviders
/// </summary> /// </summary>
public abstract class ScriptingProvider : PluginFeature public abstract class ScriptingProvider : PluginFeature
{ {
internal abstract Type GlobalScriptType { get; } /// <summary>
internal abstract Type PropertyScriptType { get; } /// Gets the name of the scripting language this provider provides
internal abstract Type LayerScriptType { get; } /// </summary>
internal abstract Type ProfileScriptType { get; } public abstract string LanguageName { get; }
internal List<Script> InternalScripts { get; } = new();
/// <summary> /// <summary>
/// Gets a list of all active scripts belonging to this scripting provider /// Gets a list of all active scripts belonging to this scripting provider
/// </summary> /// </summary>
public ReadOnlyCollection<Script> Scripts => InternalScripts.AsReadOnly(); public ReadOnlyCollection<Script> Scripts => InternalScripts.AsReadOnly();
internal abstract Type GlobalScriptType { get; }
internal abstract Type PropertyScriptType { get; }
internal abstract Type LayerScriptType { get; }
internal abstract Type ProfileScriptType { get; }
internal List<Script> InternalScripts { get; } = new();
/// <summary> /// <summary>
/// Called when the UI needs a script editor for a <see cref="GlobalScript" /> /// Called when the UI needs a script editor for a <see cref="GlobalScript" />
/// </summary> /// </summary>

View File

@ -12,7 +12,7 @@ namespace Artemis.Core.ScriptingProviders
{ {
} }
internal ScriptingService ScriptingService { get; set; } internal ScriptingService? ScriptingService { get; set; }
/// <summary> /// <summary>
/// Called whenever the Artemis Core is about to update /// Called whenever the Artemis Core is about to update
@ -35,7 +35,7 @@ namespace Artemis.Core.ScriptingProviders
/// <inheritdoc /> /// <inheritdoc />
internal override void InternalCleanup() internal override void InternalCleanup()
{ {
ScriptingService.InternalGlobalScripts.Remove(this); ScriptingService?.InternalGlobalScripts.Remove(this);
} }
#endregion #endregion

View File

@ -35,7 +35,7 @@ namespace Artemis.Core
/// <param name="name">The name of the setting</param> /// <param name="name">The name of the setting</param>
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param> /// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
/// <returns></returns> /// <returns></returns>
public PluginSetting<T> GetSetting<T>(string name, T defaultValue = default) public PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default)
{ {
lock (_settingEntities) lock (_settingEntities)
{ {

View File

@ -0,0 +1,64 @@
using System.Collections.ObjectModel;
using Artemis.Core.ScriptingProviders;
namespace Artemis.Core.Services
{
/// <summary>
/// A service that allows you to manage various types of <see cref="Script" /> instances
/// </summary>
public interface IScriptingService : IArtemisService
{
/// <summary>
/// Gets a list of all currently active global scripts
/// </summary>
ReadOnlyCollection<GlobalScript> GlobalScripts { get; }
/// <summary>
/// Creates a <see cref="GlobalScript" /> instance for the given <paramref name="scriptConfiguration" />
/// </summary>
/// <param name="scriptConfiguration">The script configuration of the script</param>
/// <returns>
/// If the <see cref="ScriptingProvider" /> was found an instance of the script; otherwise <see langword="null" />
/// .
/// </returns>
GlobalScript? CreateScriptInstance(ScriptConfiguration scriptConfiguration);
/// <summary>
/// Creates a <see cref="ProfileScript" /> instance for the given <paramref name="scriptConfiguration" />
/// </summary>
/// <param name="profile">The profile the script configuration is configured for</param>
/// <param name="scriptConfiguration">The script configuration of the script</param>
/// <returns>
/// If the <see cref="ScriptingProvider" /> was found an instance of the script; otherwise <see langword="null" />
/// .
/// </returns>
ProfileScript? CreateScriptInstance(Profile profile, ScriptConfiguration scriptConfiguration);
/// <summary>
/// Creates a <see cref="LayerScript" /> instance for the given <paramref name="scriptConfiguration" />
/// </summary>
/// <param name="layer">The layer the script configuration is configured fo</param>
/// <param name="scriptConfiguration">The script configuration of the script</param>
/// <returns>
/// If the <see cref="ScriptingProvider" /> was found an instance of the script; otherwise <see langword="null" />
/// .
/// </returns>
LayerScript? CreateScriptInstance(Layer layer, ScriptConfiguration scriptConfiguration);
/// <summary>
/// Creates a <see cref="PropertyScript" /> instance for the given <paramref name="scriptConfiguration" />
/// </summary>
/// <param name="layerProperty">The layer property the script configuration is configured fo</param>
/// <param name="scriptConfiguration">The script configuration of the script</param>
/// <returns>
/// If the <see cref="ScriptingProvider" /> was found an instance of the script; otherwise <see langword="null" />
/// .
/// </returns>
PropertyScript? CreateScriptInstance(ILayerProperty layerProperty, ScriptConfiguration scriptConfiguration);
/// <summary>
/// Deletes the provided global script by it's configuration
/// </summary>
void DeleteScript(ScriptConfiguration scriptConfiguration);
}
}

View File

@ -175,14 +175,10 @@ namespace Artemis.Core.Services
provider.InternalScripts.Add(script); provider.InternalScripts.Add(script);
return script; return script;
} }
}
public interface IScriptingService : IArtemisService /// <inheritdoc />
public void DeleteScript(ScriptConfiguration scriptConfiguration)
{ {
ReadOnlyCollection<GlobalScript> GlobalScripts { get; } }
GlobalScript? CreateScriptInstance(ScriptConfiguration scriptConfiguration);
ProfileScript? CreateScriptInstance(Profile profile, ScriptConfiguration scriptConfiguration);
LayerScript? CreateScriptInstance(Layer layer, ScriptConfiguration scriptConfiguration);
PropertyScript? CreateScriptInstance(ILayerProperty layerProperty, ScriptConfiguration scriptConfiguration);
} }
} }

View File

@ -12,9 +12,9 @@ namespace Artemis.Core.Services
_pluginSettings = new PluginSettings(Constants.CorePlugin, pluginRepository); _pluginSettings = new PluginSettings(Constants.CorePlugin, pluginRepository);
} }
public PluginSetting<T> GetSetting<T>(string name, T defaultValue = default) public PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default)
{ {
return _pluginSettings.GetSetting(name, defaultValue!); return _pluginSettings.GetSetting(name, defaultValue);
} }
} }
@ -31,6 +31,6 @@ namespace Artemis.Core.Services
/// <param name="name">The name of the setting</param> /// <param name="name">The name of the setting</param>
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param> /// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
/// <returns></returns> /// <returns></returns>
PluginSetting<T> GetSetting<T>(string name, T defaultValue = default); PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default);
} }
} }

View File

@ -52,7 +52,9 @@ namespace Artemis.Core.Services
object? response = null; object? response = null;
try try
{ {
T deserialized = JsonConvert.DeserializeObject<T>(await reader.ReadToEndAsync()); T? deserialized = JsonConvert.DeserializeObject<T>(await reader.ReadToEndAsync());
if (deserialized == null)
throw new JsonException("Deserialization returned null");
if (_requestHandler != null) if (_requestHandler != null)
{ {

View File

@ -13,7 +13,7 @@ namespace Artemis.Storage.Migrations
{ {
ILiteCollection<ProfileCategoryEntity> profileCategories = repository.Database.GetCollection<ProfileCategoryEntity>(); ILiteCollection<ProfileCategoryEntity> profileCategories = repository.Database.GetCollection<ProfileCategoryEntity>();
profileCategories.EnsureIndex(s => s.Name, true); profileCategories.EnsureIndex(s => s.Name, true);
ProfileCategoryEntity? profileCategoryEntity = profileCategories.Find(c => c.Name == "Converted").FirstOrDefault(); ProfileCategoryEntity profileCategoryEntity = profileCategories.Find(c => c.Name == "Converted").FirstOrDefault();
if (profileCategoryEntity == null) if (profileCategoryEntity == null)
{ {
profileCategoryEntity = new ProfileCategoryEntity {Name = "Imported"}; profileCategoryEntity = new ProfileCategoryEntity {Name = "Imported"};

View File

@ -1,6 +1,5 @@
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using MaterialDesignThemes.Wpf;
namespace Artemis.UI.Shared namespace Artemis.UI.Shared
@ -11,16 +10,22 @@ namespace Artemis.UI.Shared
public partial class ProfileConfigurationIcon : UserControl public partial class ProfileConfigurationIcon : UserControl
{ {
/// <summary> /// <summary>
/// Gets or sets the <see cref="PackIconKind" /> /// Gets or sets the <see cref="Core.ProfileConfigurationIcon" /> to display
/// </summary> /// </summary>
public static readonly DependencyProperty ConfigurationIconProperty = public static readonly DependencyProperty ConfigurationIconProperty =
DependencyProperty.Register(nameof(ConfigurationIcon), typeof(Core.ProfileConfigurationIcon), typeof(ProfileConfigurationIcon)); DependencyProperty.Register(nameof(ConfigurationIcon), typeof(Core.ProfileConfigurationIcon), typeof(ProfileConfigurationIcon));
/// <summary>
/// Creates a new instance of the <see cref="ProfileConfigurationIcon" /> class
/// </summary>
public ProfileConfigurationIcon() public ProfileConfigurationIcon()
{ {
InitializeComponent(); InitializeComponent();
} }
/// <summary>
/// Gets or sets the <see cref="Core.ProfileConfigurationIcon" /> to display
/// </summary>
public Core.ProfileConfigurationIcon ConfigurationIcon public Core.ProfileConfigurationIcon ConfigurationIcon
{ {
get => (Core.ProfileConfigurationIcon) GetValue(ConfigurationIconProperty); get => (Core.ProfileConfigurationIcon) GetValue(ConfigurationIconProperty);

View File

@ -17,7 +17,7 @@ namespace Artemis.UI.Shared
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if (value is not Stream stream) if (value is not Stream stream)
return null; return Binding.DoNothing;
stream.Position = 0; stream.Position = 0;

View File

@ -19,7 +19,7 @@ namespace Artemis.UI.Shared
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if (value is not Stream stream) if (value is not Stream stream)
return null; return Binding.DoNothing;
stream.Position = 0; stream.Position = 0;

View File

@ -2,12 +2,21 @@
namespace Artemis.UI.Shared namespace Artemis.UI.Shared
{ {
/// <summary>
/// Providers a proxy between data contexts
/// </summary>
public class BindingProxy : Freezable public class BindingProxy : Freezable
{ {
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc... // Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
/// <summary>
/// Gets or sets the data that was proxied
/// </summary>
public static readonly DependencyProperty DataProperty = public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
/// <summary>
/// Gets or sets the data that was proxied
/// </summary>
public object Data public object Data
{ {
get => GetValue(DataProperty); get => GetValue(DataProperty);
@ -16,6 +25,7 @@ namespace Artemis.UI.Shared
#region Overrides of Freezable #region Overrides of Freezable
/// <inheritdoc />
protected override Freezable CreateInstanceCore() protected override Freezable CreateInstanceCore()
{ {
return new BindingProxy(); return new BindingProxy();

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Modules; using Artemis.Core.Modules;
using Artemis.Core.ScriptingProviders;
using Artemis.UI.Screens.Header; using Artemis.UI.Screens.Header;
using Artemis.UI.Screens.Plugins; using Artemis.UI.Screens.Plugins;
using Artemis.UI.Screens.ProfileEditor.Conditions; using Artemis.UI.Screens.ProfileEditor.Conditions;
@ -114,6 +115,7 @@ namespace Artemis.UI.Ninject.Factories
ScriptsDialogViewModel ScriptsDialogViewModel(Profile profile); ScriptsDialogViewModel ScriptsDialogViewModel(Profile profile);
ScriptsDialogViewModel ScriptsDialogViewModel(Layer layer); ScriptsDialogViewModel ScriptsDialogViewModel(Layer layer);
ScriptsDialogViewModel ScriptsDialogViewModel(ILayerProperty layerProperty); ScriptsDialogViewModel ScriptsDialogViewModel(ILayerProperty layerProperty);
ScriptConfigurationViewModel ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration);
} }
public interface ISidebarVmFactory : IVmFactory public interface ISidebarVmFactory : IVmFactory

View File

@ -217,7 +217,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
Update(); Update();
} }
private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e) private void CoreServiceOnFrameRendered(object sender, FrameRenderedEventArgs e)
{ {
if (IsRootGroup) if (IsRootGroup)
Evaluate(); Evaluate();

View File

@ -139,7 +139,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
RenderProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged; RenderProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged;
} }
private void TimelineOnPropertyChanged(object? sender, PropertyChangedEventArgs e) private void TimelineOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
NotifyOfPropertyChange(nameof(DisplayContinuously)); NotifyOfPropertyChange(nameof(DisplayContinuously));
NotifyOfPropertyChange(nameof(AlwaysFinishTimeline)); NotifyOfPropertyChange(nameof(AlwaysFinishTimeline));

View File

@ -115,7 +115,7 @@ namespace Artemis.UI.Screens
_eventAggregator.Publish(new MainWindowMouseEvent(sender, false, e)); _eventAggregator.Publish(new MainWindowMouseEvent(sender, false, e));
} }
private void SidebarViewModelOnSelectedScreenChanged(object? sender, EventArgs e) private void SidebarViewModelOnSelectedScreenChanged(object sender, EventArgs e)
{ {
ActiveItem = SidebarViewModel.SelectedScreen; ActiveItem = SidebarViewModel.SelectedScreen;
} }

View File

@ -43,7 +43,7 @@
<DataTemplate DataType="{x:Type scriptingProviders:ScriptingProvider}"> <DataTemplate DataType="{x:Type scriptingProviders:ScriptingProvider}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<shared:ArtemisIcon Icon="{Binding Info.ResolvedIcon}" Width="18 " Height="18" Margin="0 0 5 0" VerticalAlignment="Center" /> <shared:ArtemisIcon Icon="{Binding Info.ResolvedIcon}" Width="18 " Height="18" Margin="0 0 5 0" VerticalAlignment="Center" />
<TextBlock Text="{Binding Info.Name}" VerticalAlignment="Center" /> <TextBlock Text="{Binding LanguageName}" VerticalAlignment="Center" />
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</ComboBox.ItemTemplate> </ComboBox.ItemTemplate>

View File

@ -0,0 +1,46 @@
<UserControl x:Class="Artemis.UI.Screens.Scripting.Dialogs.ScriptConfigurationEditView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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.Screens.Scripting.Dialogs"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:scriptingProviders="clr-namespace:Artemis.Core.ScriptingProviders;assembly=Artemis.Core"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:ScriptConfigurationEditViewModel}">
<StackPanel Margin="16">
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}">
Edit script
</TextBlock>
<TextBox materialDesign:HintAssist.Hint="Script name"
Margin="0 8 0 16"
Width="300"
Style="{StaticResource MaterialDesignFilledTextBox}"
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
<Grid Margin="0 8 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0"
HorizontalAlignment="Left"
Style="{StaticResource MaterialDesignFlatAccentButton}"
Command="{s:Action Delete}">
DELETE
</Button>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Command="{s:Action Cancel}">
CANCEL
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Command="{s:Action Accept}">
ACCEPT
</Button>
</StackPanel>
</Grid>
</StackPanel>
</UserControl>

View File

@ -0,0 +1,53 @@
using System.Threading.Tasks;
using Artemis.Core.ScriptingProviders;
using Artemis.UI.Shared.Services;
using FluentValidation;
using Stylet;
namespace Artemis.UI.Screens.Scripting.Dialogs
{
public class ScriptConfigurationEditViewModel : DialogViewModelBase
{
private string _name;
public ScriptConfigurationEditViewModel(IModelValidator<ScriptConfigurationEditViewModel> validator, ScriptConfiguration scriptConfiguration) : base(validator)
{
ScriptConfiguration = scriptConfiguration;
_name = ScriptConfiguration.Name;
}
public ScriptConfiguration ScriptConfiguration { get; }
public string Name
{
get => _name;
set => SetAndNotify(ref _name, value);
}
public async Task Accept()
{
await ValidateAsync();
if (HasErrors)
return;
ScriptConfiguration.Name = Name;
if (Session is {IsEnded: false})
Session.Close(nameof(Accept));
}
public void Delete()
{
if (Session is {IsEnded: false})
Session.Close(nameof(Delete));
}
}
public class ProfileElementScriptConfigurationEditViewModelValidator : AbstractValidator<ScriptConfigurationEditViewModel>
{
public ProfileElementScriptConfigurationEditViewModelValidator()
{
RuleFor(m => m.Name).NotEmpty().WithMessage("Script name may not be empty");
}
}
}

View File

@ -1,25 +1,26 @@
using Artemis.Core.ScriptingProviders; using System.Collections.Generic;
using System.Threading.Tasks;
using Artemis.Core.ScriptingProviders;
using Artemis.Core.Services;
using Artemis.UI.Screens.Scripting.Dialogs;
using Artemis.UI.Shared.ScriptingProviders; using Artemis.UI.Shared.ScriptingProviders;
using Artemis.UI.Shared.Services;
using Stylet; using Stylet;
namespace Artemis.UI.Screens.Scripting namespace Artemis.UI.Screens.Scripting
{ {
public class ScriptConfigurationViewModel : Conductor<IScriptEditorViewModel> public class ScriptConfigurationViewModel : Conductor<IScriptEditorViewModel>
{ {
public ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration) private readonly IScriptingService _scriptingService;
private readonly IDialogService _dialogService;
public ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration, IScriptingService scriptingService, IDialogService dialogService)
{ {
_scriptingService = scriptingService;
_dialogService = dialogService;
ScriptConfiguration = scriptConfiguration; ScriptConfiguration = scriptConfiguration;
Script = ScriptConfiguration.Script; Script = ScriptConfiguration.Script;
}
public Script Script { get; set; }
public ScriptConfiguration ScriptConfiguration { get; }
#region Overrides of Screen
/// <inheritdoc />
protected override void OnActivate()
{
ActiveItem = Script switch ActiveItem = Script switch
{ {
GlobalScript globalScript => Script.ScriptingProvider.CreateGlobalScriptEditor(globalScript), GlobalScript globalScript => Script.ScriptingProvider.CreateGlobalScriptEditor(globalScript),
@ -28,18 +29,47 @@ namespace Artemis.UI.Screens.Scripting
PropertyScript propertyScript => Script.ScriptingProvider.CreatePropertyScriptEditor(propertyScript), PropertyScript propertyScript => Script.ScriptingProvider.CreatePropertyScriptEditor(propertyScript),
_ => new UnknownScriptEditorViewModel(null) _ => new UnknownScriptEditorViewModel(null)
}; };
base.OnActivate();
} }
/// <inheritdoc /> public Script Script { get; set; }
protected override void OnClose() public ScriptConfiguration ScriptConfiguration { get; }
public async Task ViewProperties()
{ {
ActiveItem = null; object result = await _dialogService.ShowDialog<ScriptConfigurationEditViewModel>(new Dictionary<string, object>
base.OnClose(); {
{"scriptConfiguration", ScriptConfiguration}
});
if (result is nameof(ScriptConfigurationEditViewModel.Delete))
await Delete();
} }
#endregion private async Task Delete()
{
bool result = await _dialogService.ShowConfirmDialogAt("ScriptsDialog", "Delete script", $"Are you sure you want to delete '{ScriptConfiguration.Name}'?");
if (!result)
return;
switch (Script)
{
case GlobalScript globalScript:
_scriptingService.DeleteScript(ScriptConfiguration);
break;
case LayerScript layerScript:
layerScript.Layer.ScriptConfigurations.Remove(ScriptConfiguration);
break;
case ProfileScript profileScript:
profileScript.Profile.ScriptConfigurations.Remove(ScriptConfiguration);
break;
case PropertyScript propertyScript:
propertyScript.LayerProperty.ScriptConfigurations.Remove(ScriptConfiguration);
break;
}
ScriptConfiguration.DiscardPendingChanges();
RequestClose();
}
} }
public class UnknownScriptEditorViewModel : ScriptEditorViewModel public class UnknownScriptEditorViewModel : ScriptEditorViewModel

View File

@ -44,6 +44,7 @@
<ListBox Grid.Row="0" <ListBox Grid.Row="0"
Margin="0 10 0 0" Margin="0 10 0 0"
ItemContainerStyle="{StaticResource SidebarListBoxItem}" ItemContainerStyle="{StaticResource SidebarListBoxItem}"
HorizontalContentAlignment="Stretch"
ItemsSource="{Binding Items}" ItemsSource="{Binding Items}"
SelectedItem="{Binding ActiveItem}"> SelectedItem="{Binding ActiveItem}">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
@ -52,6 +53,8 @@
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
@ -65,20 +68,56 @@
Height="18" Height="18"
Margin="0 0 10 0" Margin="0 0 10 0"
VerticalAlignment="Center" /> VerticalAlignment="Center" />
<TextBlock Grid.Row="0" <TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Text="{Binding ScriptConfiguration.Name}"
Grid.Column="1" Visibility="{Binding ScriptConfiguration.HasChanges, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}"/>
Text="{Binding ScriptConfiguration.Name}" VerticalAlignment="Center" /> <TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"
Visibility="{Binding ScriptConfiguration.HasChanges, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<Run Text="{Binding ScriptConfiguration.Name}" FontWeight="Bold" />
<Run Text="*" />
</TextBlock>
<TextBlock Grid.Row="1" <TextBlock Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Text="{Binding ScriptConfiguration.Script.ScriptingProvider.Info.Name, FallbackValue='Unknown scripting provider'}" Text="{Binding ScriptConfiguration.Script.ScriptingProvider.LanguageName, FallbackValue='Unknown scripting provider'}"
Foreground="{DynamicResource MaterialDesignBodyLight}" Foreground="{DynamicResource MaterialDesignBodyLight}"
VerticalAlignment="Center" /> VerticalAlignment="Center" />
<Button Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" ToolTip="View properties" Width="20" Height="20" Command="{s:Action ViewProperties}" s:View.ActionTarget="{Binding}" HorizontalAlignment="Right">
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignIconForegroundButton}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}, Mode=FindAncestor}}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<materialDesign:PackIcon Kind="Cog" Width="16" Height="16" />
</Button>
<ToggleButton Grid.Row="0" Grid.RowSpan="2" Grid.Column="3" ToolTip="Suspend profile" Width="18" Height="18" Margin="2 0 0 0" IsChecked="{Binding ScriptConfiguration.IsSuspended}">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MaterialDesignFlatToggleButton}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}, Mode=FindAncestor}}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
<materialDesign:PackIcon Kind="Pause" Height="14" Width="14" />
</ToggleButton>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
</ListBox> </ListBox>
<Button Grid.Row="1" Style="{StaticResource MaterialDesignOutlinedButton}" Content="ADD NEW SCRIPT" Margin="10 10 10 0" Command="{s:Action AddScriptConfiguration}" <Button Grid.Row="1"
Style="{StaticResource MaterialDesignOutlinedButton}"
Content="ADD NEW SCRIPT"
Margin="10 10 10 0"
Command="{s:Action AddScriptConfiguration}"
VerticalAlignment="Top" /> VerticalAlignment="Top" />
</Grid> </Grid>
</Border> </Border>

View File

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.ScriptingProviders; using Artemis.Core.ScriptingProviders;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Scripting.Dialogs; using Artemis.UI.Screens.Scripting.Dialogs;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using Stylet; using Stylet;
@ -14,19 +15,21 @@ namespace Artemis.UI.Screens.Scripting
{ {
private readonly IScriptingService _scriptingService; private readonly IScriptingService _scriptingService;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly IScriptVmFactory _scriptVmFactory;
public Profile Profile { get; } public Profile Profile { get; }
public Layer Layer { get; } public Layer Layer { get; }
public ILayerProperty LayerProperty { get; } public ILayerProperty LayerProperty { get; }
public ScriptsDialogViewModel(Profile profile, IScriptingService scriptingService, IDialogService dialogService) public ScriptsDialogViewModel(Profile profile, IScriptingService scriptingService, IDialogService dialogService, IScriptVmFactory scriptVmFactory)
{ {
_scriptingService = scriptingService; _scriptingService = scriptingService;
_dialogService = dialogService; _dialogService = dialogService;
_scriptVmFactory = scriptVmFactory;
DisplayName = "Artemins | Profile Scripts"; DisplayName = "Artemis | Profile Scripts";
Profile = profile ?? throw new ArgumentNullException(nameof(profile)); Profile = profile ?? throw new ArgumentNullException(nameof(profile));
Items.AddRange(Profile.ScriptConfigurations.Select(s => new ScriptConfigurationViewModel(s))); Items.AddRange(Profile.ScriptConfigurations.Select(scriptVmFactory.ScriptConfigurationViewModel));
} }
public ScriptsDialogViewModel(Layer layer, IDialogService dialogService) public ScriptsDialogViewModel(Layer layer, IDialogService dialogService)
@ -35,7 +38,7 @@ namespace Artemis.UI.Screens.Scripting
DisplayName = "Artemins | Layer Scripts"; DisplayName = "Artemins | Layer Scripts";
Layer = layer ?? throw new ArgumentNullException(nameof(layer)); Layer = layer ?? throw new ArgumentNullException(nameof(layer));
Items.AddRange(Layer.ScriptConfigurations.Select(s => new ScriptConfigurationViewModel(s))); Items.AddRange(Layer.ScriptConfigurations.Select(_scriptVmFactory.ScriptConfigurationViewModel));
} }
public ScriptsDialogViewModel(ILayerProperty layerProperty, IDialogService dialogService) public ScriptsDialogViewModel(ILayerProperty layerProperty, IDialogService dialogService)
@ -44,7 +47,7 @@ namespace Artemis.UI.Screens.Scripting
DisplayName = "Artemins | Layer Property Scripts"; DisplayName = "Artemins | Layer Property Scripts";
LayerProperty = layerProperty ?? throw new ArgumentNullException(nameof(layerProperty)); LayerProperty = layerProperty ?? throw new ArgumentNullException(nameof(layerProperty));
Items.AddRange(LayerProperty.ScriptConfigurations.Select(s => new ScriptConfigurationViewModel(s))); Items.AddRange(Layer.ScriptConfigurations.Select(_scriptVmFactory.ScriptConfigurationViewModel));
} }
public async Task AddScriptConfiguration() public async Task AddScriptConfiguration()
@ -69,7 +72,7 @@ namespace Artemis.UI.Screens.Scripting
_scriptingService.CreateScriptInstance(LayerProperty, scriptConfiguration); _scriptingService.CreateScriptInstance(LayerProperty, scriptConfiguration);
} }
Items.Add(new ScriptConfigurationViewModel(scriptConfiguration)); Items.Add(_scriptVmFactory.ScriptConfigurationViewModel(scriptConfiguration));
} }
} }
} }

View File

@ -26,13 +26,13 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs.Performance
viewModel.Update(); viewModel.Update();
} }
private void FeatureToggled(object? sender, PluginFeatureEventArgs e) private void FeatureToggled(object sender, PluginFeatureEventArgs e)
{ {
Items.Clear(); Items.Clear();
PopulateItems(); PopulateItems();
} }
private void PluginToggled(object? sender, PluginEventArgs e) private void PluginToggled(object sender, PluginEventArgs e)
{ {
Items.Clear(); Items.Clear();
PopulateItems(); PopulateItems();

View File

@ -221,7 +221,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
Core.Utilities.OpenUrl(uri.ToString()); Core.Utilities.OpenUrl(uri.ToString());
} }
private void PluginManagementServiceOnPluginToggled(object? sender, PluginEventArgs e) private void PluginManagementServiceOnPluginToggled(object sender, PluginEventArgs e)
{ {
NotifyOfPropertyChange(nameof(IsEnabled)); NotifyOfPropertyChange(nameof(IsEnabled));
NotifyOfPropertyChange(nameof(CanOpenSettings)); NotifyOfPropertyChange(nameof(CanOpenSettings));