Merge branch 'feature/events' into master

This commit is contained in:
Robert Beekman authored and GitHub committed 2020-11-05 21:12:56 +01:00
commit 143dea4c4c
111 files changed
+3994 -2150

No files matched your search

@@ -1,2 +1,15 @@
<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/=behaviors/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=controls/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=converters/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=datamodelvisualization/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=datamodelvisualization_005Cshared/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=dependencyproperties/@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/=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/=propertyinput/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cdatamodelvisualization/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cdialog/@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/=utilities/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
@@ -97,7 +97,11 @@ namespace Artemis.UI.Shared.Input
public bool IsDataModelViewModelOpen
{
get => _isDataModelViewModelOpen;
set => SetAndNotify(ref _isDataModelViewModelOpen, value);
set
{
if (!SetAndNotify(ref _isDataModelViewModelOpen, value)) return;
if (value) UpdateDataModelVisualization();
}
}
public DataModelPath DataModelPath
@@ -127,6 +131,8 @@ namespace Artemis.UI.Shared.Input
}
}
public bool LoadEventChildren { get; set; } = true;
public void ChangeDataModel(DataModelPropertiesViewModel dataModel)
{
if (DataModelViewModel != null)
@@ -197,10 +203,15 @@ namespace Artemis.UI.Shared.Input
{
if (!IsDataModelViewModelOpen)
return;
UpdateDataModelVisualization();
}
DataModelViewModel.Update(_dataModelUIService);
private void UpdateDataModelVisualization()
{
DataModelViewModel.Update(_dataModelUIService, new DataModelUpdateConfiguration(LoadEventChildren));
foreach (DataModelPropertiesViewModel extraDataModelViewModel in ExtraDataModelViewModels)
extraDataModelViewModel.Update(_dataModelUIService);
extraDataModelViewModel.Update(_dataModelUIService, new DataModelUpdateConfiguration(LoadEventChildren));
}
#endregion
@@ -16,12 +16,21 @@
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DataModelConditions.xaml" />
<ResourceDictionary>
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<Style x:Key="DataModelConditionButtonCornerToggle" BasedOn="{StaticResource DataModelConditionButton}" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding DisplaySwitchButton}" Value="True">
<Setter Property="materialDesign:ButtonAssist.CornerRadius" Value="0 2 2 0" />
</DataTrigger>
<DataTrigger Binding="{Binding DisplaySwitchButton}" Value="False">
<Setter Property="materialDesign:ButtonAssist.CornerRadius" Value="2" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid Margin="3 -4">
<Grid>
<StackPanel Orientation="Horizontal" Visibility="{Binding InputViewModel, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}">
<Button Style="{StaticResource MaterialDesignFlatDarkBgButton}"
Background="{Binding SwitchButtonBrush}"
@@ -31,15 +40,14 @@
Width="22"
FontSize="12"
materialDesign:ButtonAssist.CornerRadius="2 0 0 2"
Margin="0 0 -3 0"
Margin="3 0 -3 0"
HorizontalAlignment="Left"
ToolTip="Switch to data model value"
Command="{s:Action SwitchToDynamic}"
Visibility="{Binding DisplaySwitchButton, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<materialDesign:PackIcon Kind="SwapHorizontal" />
</Button>
<Button Style="{StaticResource DataModelConditionButton}"
materialDesign:ButtonAssist.CornerRadius="0 2 2 0"
<Button Style="{StaticResource DataModelConditionButtonCornerToggle}"
Background="{Binding ButtonBrush}"
BorderBrush="{Binding ButtonBrush}"
Command="{s:Action ActivateInputViewModel}"
@@ -63,6 +71,7 @@
Visibility="{Binding InputViewModel, Converter={StaticResource NullToVisibilityConverter}}"
CornerRadius="3"
Padding="3"
Margin="0 -3"
HorizontalAlignment="Left"
MinWidth="140">
<ContentControl s:View.Model="{Binding InputViewModel}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
@@ -69,7 +69,7 @@ namespace Artemis.UI.Shared.Input
public Type TargetType
{
get => _targetType;
set => SetAndNotify(ref _targetType, value);
private set => SetAndNotify(ref _targetType, value);
}
public DataModelPropertyAttribute TargetDescription
@@ -0,0 +1,59 @@
using System;
using System.Linq;
using Artemis.Core;
using Artemis.Core.DataModelExpansions;
using Artemis.UI.Shared.Services;
namespace Artemis.UI.Shared
{
public class DataModelEventViewModel : DataModelVisualizationViewModel
{
private Type _displayValueType;
internal DataModelEventViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath)
{
}
public Type DisplayValueType
{
get => _displayValueType;
set => SetAndNotify(ref _displayValueType, value);
}
public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
DisplayValueType = DataModelPath?.GetPropertyType();
if (configuration != null)
{
if (configuration.CreateEventChildren)
PopulateProperties(dataModelUIService, configuration);
else if (Children.Any())
Children.Clear();
}
// Only update children if the parent is expanded
if (Parent != null && !Parent.IsRootViewModel && !Parent.IsVisualizationExpanded)
return;
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
dataModelVisualizationViewModel.Update(dataModelUIService, configuration);
}
public override object GetCurrentValue()
{
return null;
}
/// <inheritdoc />
public override string ToString()
{
return DisplayPath ?? Path;
}
internal override int GetChildDepth()
{
return PropertyDescription != null && !PropertyDescription.ResetsDepth ? Depth + 1 : 1;
}
}
}
@@ -15,8 +15,6 @@ namespace Artemis.UI.Shared
{
DataModel = ListPredicateWrapperDataModel.Create(listType);
ListType = listType;
IsRootViewModel = false;
}
public int Index
@@ -41,17 +39,17 @@ namespace Artemis.UI.Shared
public override string DisplayPath => null;
public override void Update(IDataModelUIService dataModelUIService)
public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
((ListPredicateWrapperDataModel) DataModel).UntypedValue = DisplayValue;
PopulateProperties(dataModelUIService);
PopulateProperties(dataModelUIService, configuration);
if (DisplayViewModel == null)
return;
if (IsVisualizationExpanded && !DisplayViewModel.IsVisualizationExpanded)
DisplayViewModel.IsVisualizationExpanded = IsVisualizationExpanded;
DisplayViewModel.Update(dataModelUIService);
DisplayViewModel.Update(dataModelUIService, null);
}
public override object GetCurrentValue()
@@ -39,7 +39,7 @@ namespace Artemis.UI.Shared
return DisplayValue;
}
public override void Update(IDataModelUIService dataModelUIService)
public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
// Display value gets updated by parent, don't do anything if it is null
if (DisplayValue == null)
@@ -44,32 +44,8 @@ namespace Artemis.UI.Shared
}
public BindableCollection<DataModelVisualizationViewModel> ListChildren { get; set; }
public DataModelPropertiesViewModel GetListTypeViewModel(IDataModelUIService dataModelUIService)
{
Type listType = DataModelPath.GetPropertyType()?.GetGenericEnumerableType();
if (listType == null)
return null;
// Create a property VM describing the type of the list
DataModelVisualizationViewModel viewModel = CreateListChild(dataModelUIService, listType);
viewModel.Update(dataModelUIService);
// Put an empty value into the list type property view model
if (viewModel is DataModelListPropertiesViewModel dataModelListClassViewModel) return dataModelListClassViewModel;
if (viewModel is DataModelListPropertyViewModel dataModelListPropertyViewModel)
{
dataModelListPropertyViewModel.DisplayValue = Activator.CreateInstance(dataModelListPropertyViewModel.ListType);
DataModelPropertiesViewModel wrapper = new DataModelPropertiesViewModel(null, null, null);
wrapper.Children.Add(dataModelListPropertyViewModel);
return wrapper;
}
return null;
}
public override void Update(IDataModelUIService dataModelUIService)
public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
if (Parent != null && !Parent.IsVisualizationExpanded)
return;
@@ -107,7 +83,7 @@ namespace Artemis.UI.Shared
dataModelListPropertyViewModel.Index = index;
}
child.Update(dataModelUIService);
child.Update(dataModelUIService, configuration);
index++;
}
@@ -7,8 +7,8 @@ namespace Artemis.UI.Shared
{
public class DataModelPropertiesViewModel : DataModelVisualizationViewModel
{
private Type _displayValueType;
private object _displayValue;
private Type _displayValueType;
internal DataModelPropertiesViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath)
{
@@ -26,7 +26,7 @@ namespace Artemis.UI.Shared
set => SetAndNotify(ref _displayValue, value);
}
public override void Update(IDataModelUIService dataModelUIService)
public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
DisplayValueType = DataModelPath?.GetPropertyType();
@@ -37,22 +37,22 @@ namespace Artemis.UI.Shared
else
DisplayValue = null;
// Always populate properties
PopulateProperties(dataModelUIService);
// Always populate properties
PopulateProperties(dataModelUIService, configuration);
// Only update children if the parent is expanded
if (Parent != null && !Parent.IsVisualizationExpanded && !Parent.IsRootViewModel)
if (Parent != null && !Parent.IsRootViewModel && !Parent.IsVisualizationExpanded)
return;
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
dataModelVisualizationViewModel.Update(dataModelUIService);
dataModelVisualizationViewModel.Update(dataModelUIService, configuration);
}
public override object GetCurrentValue()
{
if (Parent == null)
return null;
return Parent.IsRootViewModel ? DataModel : base.GetCurrentValue();
if (Parent == null || Parent.IsRootViewModel || IsRootViewModel)
return DataModel;
return base.GetCurrentValue();
}
/// <inheritdoc />
@@ -33,7 +33,7 @@ namespace Artemis.UI.Shared
set => SetAndNotify(ref _displayViewModel, value);
}
public override void Update(IDataModelUIService dataModelUIService)
public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
if (Parent != null && !Parent.IsVisualizationExpanded && !Parent.IsRootViewModel)
return;
@@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
@@ -29,7 +28,7 @@ namespace Artemis.UI.Shared
Children = new BindableCollection<DataModelVisualizationViewModel>();
IsMatchingFilteredTypes = true;
if (dataModel == null && parent == null && dataModelPath == null)
if (parent == null)
IsRootViewModel = true;
else
PropertyDescription = DataModelPath?.GetPropertyDescription() ?? DataModel.DataModelDescription;
@@ -88,8 +87,9 @@ namespace Artemis.UI.Shared
/// <summary>
/// Updates the datamodel and if in an parent, any children
/// </summary>
/// <param name="dataModelUIService"></param>
public abstract void Update(IDataModelUIService dataModelUIService);
/// <param name="dataModelUIService">The data model UI service used during update</param>
/// <param name="configuration">The configuration to apply while updating</param>
public abstract void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration);
public virtual object GetCurrentValue()
{
@@ -137,58 +137,24 @@ namespace Artemis.UI.Shared
if (looseMatch)
IsMatchingFilteredTypes = filteredTypes.Any(t => t.IsCastableFrom(type) ||
t == typeof(Enum) && type.IsEnum ||
t == typeof(IEnumerable<>) && type.IsGenericEnumerable());
t == typeof(IEnumerable<>) && type.IsGenericEnumerable() ||
type.IsGenericType && t == type.GetGenericTypeDefinition());
else
IsMatchingFilteredTypes = filteredTypes.Any(t => t == type || t == typeof(Enum) && type.IsEnum);
}
public DataModelVisualizationViewModel GetChildByPath(Guid dataModelGuid, string propertyPath)
{
if (!IsRootViewModel)
{
if (DataModel.PluginInfo.Guid != dataModelGuid)
return null;
if (propertyPath == null)
return null;
if (Path != null && Path.StartsWith(propertyPath, StringComparison.OrdinalIgnoreCase))
return null;
}
// Ensure children are populated by requesting an update
if (!IsVisualizationExpanded)
{
IsVisualizationExpanded = true;
RequestUpdate();
IsVisualizationExpanded = false;
}
foreach (DataModelVisualizationViewModel child in Children)
{
// Try the child itself first
if (child.Path == propertyPath)
return child;
// Try a child on the child next, this will go recursive
DataModelVisualizationViewModel match = child.GetChildByPath(dataModelGuid, propertyPath);
if (match != null)
return match;
}
return null;
}
internal virtual int GetChildDepth()
{
return 0;
}
internal void PopulateProperties(IDataModelUIService dataModelUIService)
internal void PopulateProperties(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration dataModelUpdateConfiguration)
{
if (IsRootViewModel)
if (IsRootViewModel && DataModel == null)
return;
Type modelType = Parent == null || Parent.IsRootViewModel ? DataModel.GetType() : DataModelPath.GetPropertyType();
Type modelType = IsRootViewModel ? DataModel.GetType() : DataModelPath.GetPropertyType();
// Add missing static children
foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(t => t.MetadataToken))
{
@@ -219,7 +185,6 @@ namespace Artemis.UI.Shared
// Add missing dynamic children
object value = Parent == null || Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue();
if (value is DataModel dataModel)
{
foreach (KeyValuePair<string, DataModel> kvp in dataModel.DynamicDataModels)
{
string childPath = AppendToPath(kvp.Key);
@@ -230,7 +195,6 @@ namespace Artemis.UI.Shared
if (child != null)
Children.Add(child);
}
}
// Remove dynamic children that have been removed from the data model
List<DataModelVisualizationViewModel> toRemoveDynamic = Children.Where(c => !c.DataModelPath.IsValid).ToList();
@@ -266,6 +230,8 @@ namespace Artemis.UI.Shared
return new DataModelPropertyViewModel(DataModel, this, dataModelPath) {Depth = depth};
if (propertyType.IsGenericEnumerable())
return new DataModelListViewModel(DataModel, this, dataModelPath) {Depth = depth};
if (propertyType == typeof(DataModelEvent) || propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(DataModelEvent<>))
return new DataModelEventViewModel(DataModel, this, dataModelPath) {Depth = depth};
// For other value types create a child view model
if (propertyType.IsClass || propertyType.IsStruct())
return new DataModelPropertiesViewModel(DataModel, this, dataModelPath) {Depth = depth};
@@ -295,4 +261,14 @@ namespace Artemis.UI.Shared
#endregion
}
public class DataModelUpdateConfiguration
{
public bool CreateEventChildren { get; }
public DataModelUpdateConfiguration(bool createEventChildren)
{
CreateEventChildren = createEventChildren;
}
}
}
@@ -0,0 +1,29 @@
using System.Linq;
using Artemis.Core;
using Artemis.UI.Shared.Services;
namespace Artemis.UI.Shared
{
public static class DataModelWrapperExtensions
{
public static DataModelPropertiesViewModel CreateViewModel(this EventPredicateWrapperDataModel wrapper, IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
DataModelPropertiesViewModel viewModel = new DataModelPropertiesViewModel(wrapper, null, new DataModelPath(wrapper));
viewModel.Update(dataModelUIService, configuration);
viewModel.UpdateRequested += (sender, args) => viewModel.Update(dataModelUIService, configuration);
viewModel.Children.First().IsVisualizationExpanded = true;
return viewModel;
}
public static DataModelPropertiesViewModel CreateViewModel(this ListPredicateWrapperDataModel wrapper, IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
DataModelPropertiesViewModel viewModel = new DataModelPropertiesViewModel(wrapper, null, new DataModelPath(wrapper));
viewModel.Update(dataModelUIService, configuration);
viewModel.UpdateRequested += (sender, args) => viewModel.Update(dataModelUIService, configuration);
viewModel.Children.First().IsVisualizationExpanded = true;
return viewModel;
}
}
}
@@ -39,6 +39,12 @@
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" ToolTipService.ShowOnDisabled="True" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelEventViewModel}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="LightningBolt" VerticalAlignment="Center" Margin="0 0 5 0" />
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="Trigger layer on event" ToolTipService.ShowOnDisabled="True" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
<Grid>
<!-- Value description -->
@@ -73,6 +79,12 @@
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" ToolTipService.ShowOnDisabled="True" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelEventViewModel}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="LightningBolt" VerticalAlignment="Center" Margin="0 0 5 0" />
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" ToolTipService.ShowOnDisabled="True" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
<Grid ToolTip="{Binding PropertyDescription.Description}">
<Grid.ColumnDefinitions>
@@ -37,8 +37,8 @@ namespace Artemis.UI.Shared.Services
viewModel.Children.Add(new DataModelPropertiesViewModel(dataModelExpansion, viewModel, new DataModelPath(dataModelExpansion)));
// Update to populate children
viewModel.Update(this);
viewModel.UpdateRequested += (sender, args) => viewModel.Update(this);
viewModel.Update(this, null);
viewModel.UpdateRequested += (sender, args) => viewModel.Update(this, null);
return viewModel;
}
@@ -67,8 +67,8 @@ namespace Artemis.UI.Shared.Services
viewModel.Children.Add(new DataModelPropertiesViewModel(dataModel, viewModel, null));
// Update to populate children
viewModel.Update(this);
viewModel.UpdateRequested += (sender, args) => viewModel.Update(this);
viewModel.Update(this, null);
viewModel.UpdateRequested += (sender, args) => viewModel.Update(this, null);
return viewModel;
}
@@ -173,7 +173,7 @@ namespace Artemis.UI.Shared.Services
else
result = _kernel.Get<DefaultDataModelDisplayViewModel>();
if (result != null)
if (result != null)
result.PropertyDescription = description;
return result;
@@ -220,8 +220,7 @@ namespace Artemis.UI.Shared.Services
if (initialValue != null && initialValue.GetType() != registration.SupportedType)
initialValue = Convert.ChangeType(initialValue, registration.SupportedType);
IParameter[] parameters = new IParameter[]
{
IParameter[] parameters = {
new ConstructorArgument("targetDescription", description),
new ConstructorArgument("initialValue", initialValue)
};
@@ -57,8 +57,7 @@ namespace Artemis.UI.Shared.Services
public async Task<bool> ShowConfirmDialog(string header, string text, string confirmText = "Confirm", string cancelText = "Cancel")
{
IParameter[] arguments =
{
IParameter[] arguments = {
new ConstructorArgument("header", header),
new ConstructorArgument("text", text),
new ConstructorArgument("confirmText", confirmText.ToUpper()),
@@ -70,8 +69,7 @@ namespace Artemis.UI.Shared.Services
public async Task<bool> ShowConfirmDialogAt(string identifier, string header, string text, string confirmText = "Confirm", string cancelText = "Cancel")
{
IParameter[] arguments =
{
IParameter[] arguments = {
new ConstructorArgument("header", header),
new ConstructorArgument("text", text),
new ConstructorArgument("confirmText", confirmText.ToUpper()),
@@ -15,6 +15,7 @@ namespace Artemis.UI.Shared.Services
internal class ProfileEditorService : IProfileEditorService
{
private readonly ILogger _logger;
private readonly ICoreService _coreService;
private readonly IProfileService _profileService;
private readonly List<PropertyInputRegistration> _registeredPropertyEditors;
private readonly object _selectedProfileElementLock = new object();
@@ -22,16 +23,23 @@ namespace Artemis.UI.Shared.Services
private TimeSpan _currentTime;
private int _pixelsPerSecond;
public ProfileEditorService(IProfileService profileService, IKernel kernel, ILogger logger)
public ProfileEditorService(IProfileService profileService, IKernel kernel, ILogger logger, ICoreService coreService)
{
_profileService = profileService;
_logger = logger;
_coreService = coreService;
_registeredPropertyEditors = new List<PropertyInputRegistration>();
Kernel = kernel;
PixelsPerSecond = 100;
}
private void CoreServiceOnFrameRendered(object? sender, FrameRenderedEventArgs e)
{
_coreService.FrameRendered -= CoreServiceOnFrameRendered;
Execute.PostToUIThread(OnProfilePreviewUpdated);
}
public IKernel Kernel { get; }
public ReadOnlyCollection<PropertyInputRegistration> RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly();
public Profile SelectedProfile { get; private set; }
@@ -44,8 +52,8 @@ namespace Artemis.UI.Shared.Services
set
{
if (_currentTime.Equals(value)) return;
if (SelectedProfileElement != null && value > SelectedProfileElement.TimelineLength)
_currentTime = SelectedProfileElement.TimelineLength;
if (SelectedProfileElement != null && value > SelectedProfileElement.Timeline.Length)
_currentTime = SelectedProfileElement.Timeline.Length;
else
_currentTime = value;
UpdateProfilePreview();
@@ -142,11 +150,11 @@ namespace Artemis.UI.Shared.Services
// Stick to the main segment for any element that is not currently selected
foreach (Folder folder in SelectedProfile.GetAllFolders())
folder.OverrideProgress(CurrentTime, folder != SelectedProfileElement);
folder.Timeline.Override(CurrentTime, folder != SelectedProfileElement && folder.Timeline.PlayMode == TimelinePlayMode.Repeat);
foreach (Layer layer in SelectedProfile.GetAllLayers())
layer.OverrideProgress(CurrentTime, layer != SelectedProfileElement);
layer.Timeline.Override(CurrentTime, layer != SelectedProfileElement && layer.Timeline.PlayMode == TimelinePlayMode.Repeat);
OnProfilePreviewUpdated();
_coreService.FrameRendered += CoreServiceOnFrameRendered;
}
public bool UndoUpdateProfile()
@@ -224,24 +232,23 @@ namespace Artemis.UI.Shared.Services
if (snapToSegments)
{
// Snap to the end of the start segment
if (Math.Abs(time.TotalMilliseconds - SelectedProfileElement.StartSegmentLength.TotalMilliseconds) < tolerance.TotalMilliseconds)
return SelectedProfileElement.StartSegmentLength;
if (Math.Abs(time.TotalMilliseconds - SelectedProfileElement.Timeline.StartSegmentEndPosition.TotalMilliseconds) < tolerance.TotalMilliseconds)
return SelectedProfileElement.Timeline.StartSegmentEndPosition;
// Snap to the end of the main segment
TimeSpan mainSegmentEnd = SelectedProfileElement.StartSegmentLength + SelectedProfileElement.MainSegmentLength;
if (Math.Abs(time.TotalMilliseconds - mainSegmentEnd.TotalMilliseconds) < tolerance.TotalMilliseconds)
return mainSegmentEnd;
if (Math.Abs(time.TotalMilliseconds - SelectedProfileElement.Timeline.MainSegmentEndPosition.TotalMilliseconds) < tolerance.TotalMilliseconds)
return SelectedProfileElement.Timeline.MainSegmentEndPosition;
// Snap to the end of the end segment (end of the timeline)
if (Math.Abs(time.TotalMilliseconds - SelectedProfileElement.TimelineLength.TotalMilliseconds) < tolerance.TotalMilliseconds)
return SelectedProfileElement.TimelineLength;
if (Math.Abs(time.TotalMilliseconds - SelectedProfileElement.Timeline.EndSegmentEndPosition.TotalMilliseconds) < tolerance.TotalMilliseconds)
return SelectedProfileElement.Timeline.EndSegmentEndPosition;
}
if (snapToCurrentTime)
{
// Snap to the current time
if (Math.Abs(time.TotalMilliseconds - CurrentTime.TotalMilliseconds) < tolerance.TotalMilliseconds)
return SelectedProfileElement.StartSegmentLength;
return CurrentTime;
}
if (snapTimes != null)