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

Profile elements - Simplified class hierarchy

Profile editor - Seperated event types and avoid a lot of type checking
Profile editor - Avoid changing profiles/layers if the new equals the old
Color picker - Fixed binding error
Profile tree - Select first element by default
Profile editor - Adjusted initialization order
This commit is contained in:
Robert 2020-07-09 19:10:04 +02:00
parent a4282006de
commit 94f3d84530
25 changed files with 303 additions and 195 deletions

View File

@ -34,7 +34,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Ben.Demystifier" Version="0.1.6" /> <PackageReference Include="Ben.Demystifier" Version="0.1.6" />
<PackageReference Include="Castle.Core" Version="4.4.1" />
<PackageReference Include="HidSharp" Version="2.1.0" /> <PackageReference Include="HidSharp" Version="2.1.0" />
<PackageReference Include="LiteDB" Version="5.0.8" /> <PackageReference Include="LiteDB" Version="5.0.8" />
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.3.0" /> <PackageReference Include="McMaster.NETCore.Plugins" Version="1.3.0" />

View File

@ -32,5 +32,7 @@ namespace Artemis.Core.Models.Profile.Conditions.Abstract
_children.Remove(displayConditionPart); _children.Remove(displayConditionPart);
} }
} }
public abstract void ApplyToEntity();
} }
} }

View File

@ -5,6 +5,12 @@ namespace Artemis.Core.Models.Profile.Conditions
public class DisplayConditionGroup : DisplayConditionPart public class DisplayConditionGroup : DisplayConditionPart
{ {
public BooleanOperator BooleanOperator { get; set; } public BooleanOperator BooleanOperator { get; set; }
public override void ApplyToEntity()
{
foreach (var child in Children)
child.ApplyToEntity();
}
} }
public enum BooleanOperator public enum BooleanOperator

View File

@ -7,7 +7,7 @@ using SkiaSharp;
namespace Artemis.Core.Models.Profile namespace Artemis.Core.Models.Profile
{ {
public sealed class Folder : EffectProfileElement public sealed class Folder : RenderProfileElement
{ {
private SKBitmap _folderBitmap; private SKBitmap _folderBitmap;
@ -159,7 +159,7 @@ namespace Artemis.Core.Models.Profile
var path = new SKPath {FillType = SKPathFillType.Winding}; var path = new SKPath {FillType = SKPathFillType.Winding};
foreach (var child in Children) foreach (var child in Children)
{ {
if (child is EffectProfileElement effectChild && effectChild.Path != null) if (child is RenderProfileElement effectChild && effectChild.Path != null)
path.AddPath(effectChild.Path); path.AddPath(effectChild.Path);
} }
@ -182,10 +182,13 @@ namespace Artemis.Core.Models.Profile
FolderEntity.Enabled = Enabled; FolderEntity.Enabled = Enabled;
FolderEntity.ProfileId = Profile.EntityId; FolderEntity.ProfileId = Profile.EntityId;
FolderEntity.ExpandedPropertyGroups.Clear();
FolderEntity.ExpandedPropertyGroups.AddRange(_expandedPropertyGroups);
ApplyLayerEffectsToEntity(); ApplyLayerEffectsToEntity();
// TODO: conditions // Conditions
DisplayConditionGroup?.ApplyToEntity();
} }
#region Events #region Events

View File

@ -21,9 +21,8 @@ namespace Artemis.Core.Models.Profile
/// Represents a layer on a profile. To create new layers use the <see cref="LayerService" /> by injecting /// Represents a layer on a profile. To create new layers use the <see cref="LayerService" /> by injecting
/// <see cref="ILayerService" /> into your code /// <see cref="ILayerService" /> into your code
/// </summary> /// </summary>
public sealed class Layer : EffectProfileElement public sealed class Layer : RenderProfileElement
{ {
private DisplayConditionGroup _displayConditionGroup;
private LayerGeneralProperties _general; private LayerGeneralProperties _general;
private SKBitmap _layerBitmap; private SKBitmap _layerBitmap;
private BaseLayerBrush _layerBrush; private BaseLayerBrush _layerBrush;
@ -117,14 +116,7 @@ namespace Artemis.Core.Models.Profile
internal set => SetAndNotify(ref _layerBrush, value); internal set => SetAndNotify(ref _layerBrush, value);
} }
/// <summary>
/// Gets or sets the root display condition group
/// </summary>
public DisplayConditionGroup DisplayConditionGroup
{
get => _displayConditionGroup;
set => SetAndNotify(ref _displayConditionGroup, value);
}
public override string ToString() public override string ToString()
{ {
@ -164,8 +156,8 @@ namespace Artemis.Core.Models.Profile
LayerEntity.Leds.Add(ledEntity); LayerEntity.Leds.Add(ledEntity);
} }
// Conditions TODO // Conditions
LayerEntity.Conditions.Clear(); DisplayConditionGroup?.ApplyToEntity();
} }
#endregion #endregion

View File

@ -20,7 +20,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties
/// <summary> /// <summary>
/// Gets the profile element (such as layer or folder) this effect is applied to /// Gets the profile element (such as layer or folder) this effect is applied to
/// </summary> /// </summary>
public PropertiesProfileElement ProfileElement { get; internal set; } public RenderProfileElement ProfileElement { get; internal set; }
/// <summary> /// <summary>
/// The parent group of this layer property, set after construction /// The parent group of this layer property, set after construction

View File

@ -31,7 +31,7 @@ namespace Artemis.Core.Models.Profile
/// <summary> /// <summary>
/// Gets the profile element (such as layer or folder) this effect is applied to /// Gets the profile element (such as layer or folder) this effect is applied to
/// </summary> /// </summary>
public PropertiesProfileElement ProfileElement { get; internal set; } public RenderProfileElement ProfileElement { get; internal set; }
/// <summary> /// <summary>
/// The path of this property group /// The path of this property group
@ -129,7 +129,7 @@ namespace Artemis.Core.Models.Profile
PropertyGroupInitialized?.Invoke(this, EventArgs.Empty); PropertyGroupInitialized?.Invoke(this, EventArgs.Empty);
} }
internal void InitializeProperties(ILayerService layerService, PropertiesProfileElement profileElement, [NotNull] string path) internal void InitializeProperties(ILayerService layerService, RenderProfileElement profileElement, [NotNull] string path)
{ {
if (path == null) if (path == null)
throw new ArgumentNullException(nameof(path)); throw new ArgumentNullException(nameof(path));
@ -236,7 +236,7 @@ namespace Artemis.Core.Models.Profile
OnPropertyGroupOverriding(new PropertyGroupUpdatingEventArgs(overrideTime)); OnPropertyGroupOverriding(new PropertyGroupUpdatingEventArgs(overrideTime));
} }
private void InitializeProperty(PropertiesProfileElement profileElement, string path, BaseLayerProperty instance) private void InitializeProperty(RenderProfileElement profileElement, string path, BaseLayerProperty instance)
{ {
Guid pluginGuid; Guid pluginGuid;
if (IsCorePropertyGroup || instance.IsCoreProperty) if (IsCorePropertyGroup || instance.IsCoreProperty)

View File

@ -6,52 +6,6 @@ namespace Artemis.Core.Models.Profile
{ {
public abstract class PropertiesProfileElement : ProfileElement public abstract class PropertiesProfileElement : ProfileElement
{ {
private SKPath _path;
internal abstract PropertiesEntity PropertiesEntity { get; }
/// <summary>
/// Gets the path containing all the LEDs this entity is applied to, any rendering outside the entity Path is
/// clipped.
/// </summary>
public SKPath Path
{
get => _path;
protected set
{
SetAndNotify(ref _path, value);
// I can't really be sure about the performance impact of calling Bounds often but
// SkiaSharp calls SkiaApi.sk_path_get_bounds (Handle, &rect); which sounds expensive
Bounds = value?.Bounds ?? SKRect.Empty;
}
}
/// <summary>
/// The bounds of this entity
/// </summary>
public SKRect Bounds
{
get => _bounds;
private set => SetAndNotify(ref _bounds, value);
}
#region Property group expansion
protected List<string> _expandedPropertyGroups;
private SKRect _bounds;
public bool IsPropertyGroupExpanded(LayerPropertyGroup layerPropertyGroup)
{
return _expandedPropertyGroups.Contains(layerPropertyGroup.Path);
}
public void SetPropertyGroupExpanded(LayerPropertyGroup layerPropertyGroup, bool expanded)
{
if (!expanded && IsPropertyGroupExpanded(layerPropertyGroup))
_expandedPropertyGroups.Remove(layerPropertyGroup.Path);
else if (expanded && !IsPropertyGroupExpanded(layerPropertyGroup))
_expandedPropertyGroups.Add(layerPropertyGroup.Path);
}
#endregion
} }
} }

View File

@ -3,13 +3,69 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Artemis.Core.Annotations; using Artemis.Core.Annotations;
using Artemis.Core.Models.Profile.Conditions;
using Artemis.Core.Plugins.LayerEffect.Abstract; using Artemis.Core.Plugins.LayerEffect.Abstract;
using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile;
using SkiaSharp;
namespace Artemis.Core.Models.Profile namespace Artemis.Core.Models.Profile
{ {
public abstract class EffectProfileElement : PropertiesProfileElement public abstract class RenderProfileElement : ProfileElement
{ {
#region Properties
private SKPath _path;
internal abstract PropertiesEntity PropertiesEntity { get; }
/// <summary>
/// Gets the path containing all the LEDs this entity is applied to, any rendering outside the entity Path is
/// clipped.
/// </summary>
public SKPath Path
{
get => _path;
protected set
{
SetAndNotify(ref _path, value);
// I can't really be sure about the performance impact of calling Bounds often but
// SkiaSharp calls SkiaApi.sk_path_get_bounds (Handle, &rect); which sounds expensive
Bounds = value?.Bounds ?? SKRect.Empty;
}
}
/// <summary>
/// The bounds of this entity
/// </summary>
public SKRect Bounds
{
get => _bounds;
private set => SetAndNotify(ref _bounds, value);
}
#region Property group expansion
protected List<string> _expandedPropertyGroups;
private SKRect _bounds;
public bool IsPropertyGroupExpanded(LayerPropertyGroup layerPropertyGroup)
{
return _expandedPropertyGroups.Contains(layerPropertyGroup.Path);
}
public void SetPropertyGroupExpanded(LayerPropertyGroup layerPropertyGroup, bool expanded)
{
if (!expanded && IsPropertyGroupExpanded(layerPropertyGroup))
_expandedPropertyGroups.Remove(layerPropertyGroup.Path);
else if (expanded && !IsPropertyGroupExpanded(layerPropertyGroup))
_expandedPropertyGroups.Add(layerPropertyGroup.Path);
}
#endregion
#endregion
#region Effects
protected List<BaseLayerEffect> _layerEffects; protected List<BaseLayerEffect> _layerEffects;
internal abstract EffectsEntity EffectsEntity { get; } internal abstract EffectsEntity EffectsEntity { get; }
@ -71,6 +127,23 @@ namespace Artemis.Core.Models.Profile
effect.Dispose(); effect.Dispose();
} }
#endregion
#region Conditions
private DisplayConditionGroup _displayConditionGroup;
/// <summary>
/// Gets or sets the root display condition group
/// </summary>
public DisplayConditionGroup DisplayConditionGroup
{
get => _displayConditionGroup;
set => SetAndNotify(ref _displayConditionGroup, value);
}
#endregion
#region Events #region Events
public event EventHandler LayerEffectsUpdated; public event EventHandler LayerEffectsUpdated;

View File

@ -14,7 +14,7 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract
public abstract class BaseLayerEffect : PropertyChangedBase, IDisposable public abstract class BaseLayerEffect : PropertyChangedBase, IDisposable
{ {
private Guid _entityId; private Guid _entityId;
private EffectProfileElement _profileElement; private RenderProfileElement _profileElement;
private string _name; private string _name;
private bool _enabled; private bool _enabled;
private bool _hasBeenRenamed; private bool _hasBeenRenamed;
@ -33,7 +33,7 @@ namespace Artemis.Core.Plugins.LayerEffect.Abstract
/// <summary> /// <summary>
/// Gets the profile element (such as layer or folder) this effect is applied to /// Gets the profile element (such as layer or folder) this effect is applied to
/// </summary> /// </summary>
public EffectProfileElement ProfileElement public RenderProfileElement ProfileElement
{ {
get => _profileElement; get => _profileElement;
internal set => SetAndNotify(ref _profileElement, value); internal set => SetAndNotify(ref _profileElement, value);

View File

@ -42,17 +42,17 @@ namespace Artemis.Core.Services.Interfaces
/// Instantiates and adds the <see cref="BaseLayerEffect" /> described by the provided /// Instantiates and adds the <see cref="BaseLayerEffect" /> described by the provided
/// <see cref="LayerEffectDescriptor" /> to the <see cref="Layer" />. /// <see cref="LayerEffectDescriptor" /> to the <see cref="Layer" />.
/// </summary> /// </summary>
/// <param name="effectProfileElement">The layer/folder to instantiate the effect for</param> /// <param name="renderProfileElement">The layer/folder to instantiate the effect for</param>
void InstantiateLayerEffects(EffectProfileElement effectProfileElement); void InstantiateLayerEffects(RenderProfileElement renderProfileElement);
/// <summary> /// <summary>
/// Adds the <see cref="BaseLayerEffect" /> described by the provided <see cref="LayerEffectDescriptor" /> to the /// Adds the <see cref="BaseLayerEffect" /> described by the provided <see cref="LayerEffectDescriptor" /> to the
/// <see cref="Layer" />. /// <see cref="Layer" />.
/// </summary> /// </summary>
/// <param name="effectProfileElement">The layer/folder to instantiate the effect for</param> /// <param name="renderProfileElement">The layer/folder to instantiate the effect for</param>
/// <param name="layerEffectDescriptor"></param> /// <param name="layerEffectDescriptor"></param>
/// <returns></returns> /// <returns></returns>
BaseLayerEffect AddLayerEffect(EffectProfileElement effectProfileElement, LayerEffectDescriptor layerEffectDescriptor); BaseLayerEffect AddLayerEffect(RenderProfileElement renderProfileElement, LayerEffectDescriptor layerEffectDescriptor);
void RemoveLayerEffect(BaseLayerEffect layerEffect); void RemoveLayerEffect(BaseLayerEffect layerEffect);
} }

View File

@ -20,7 +20,7 @@ namespace Artemis.Core.Services
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IPluginService _pluginService; private readonly IPluginService _pluginService;
public LayerService(IKernel kernel, ILogger logger, IPluginService pluginService) public LayerService(IKernel kernel, ILogger logger, IPluginService pluginService, IDataModelService dataModelService)
{ {
_kernel = kernel; _kernel = kernel;
_logger = logger; _logger = logger;
@ -39,7 +39,6 @@ namespace Artemis.Core.Services
// With the properties loaded, the layer brush and effect can be instantiated // With the properties loaded, the layer brush and effect can be instantiated
InstantiateLayerBrush(layer); InstantiateLayerBrush(layer);
InstantiateLayerEffects(layer); InstantiateLayerEffects(layer);
return layer; return layer;
} }
@ -85,21 +84,21 @@ namespace Artemis.Core.Services
return brush; return brush;
} }
public BaseLayerEffect AddLayerEffect(EffectProfileElement effectElement, LayerEffectDescriptor layerEffectDescriptor) public BaseLayerEffect AddLayerEffect(RenderProfileElement renderElement, LayerEffectDescriptor layerEffectDescriptor)
{ {
// Create the effect with dependency injection // Create the effect with dependency injection
var effect = (BaseLayerEffect) _kernel.Get(layerEffectDescriptor.LayerEffectType); var effect = (BaseLayerEffect) _kernel.Get(layerEffectDescriptor.LayerEffectType);
effect.ProfileElement = effectElement; effect.ProfileElement = renderElement;
effect.EntityId = Guid.NewGuid(); effect.EntityId = Guid.NewGuid();
effect.Enabled = true; effect.Enabled = true;
effect.Order = effectElement.LayerEffects.Count + 1; effect.Order = renderElement.LayerEffects.Count + 1;
effect.Descriptor = layerEffectDescriptor; effect.Descriptor = layerEffectDescriptor;
effect.Initialize(this); effect.Initialize(this);
effect.Update(0); effect.Update(0);
effectElement.AddLayerEffect(effect); renderElement.AddLayerEffect(effect);
_logger.Debug("Added layer effect with root path {rootPath}", effect.PropertyRootPath); _logger.Debug("Added layer effect with root path {rootPath}", effect.PropertyRootPath);
return effect; return effect;
} }
@ -109,16 +108,16 @@ namespace Artemis.Core.Services
layerEffect.ProfileElement.RemoveLayerEffect(layerEffect); layerEffect.ProfileElement.RemoveLayerEffect(layerEffect);
} }
public void InstantiateLayerEffects(EffectProfileElement effectElement) public void InstantiateLayerEffects(RenderProfileElement renderElement)
{ {
var layerEffectProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>(); var layerEffectProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
var descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList(); var descriptors = layerEffectProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
var entities = effectElement.EffectsEntity.LayerEffects.OrderByDescending(e => e.Order).ToList(); var entities = renderElement.EffectsEntity.LayerEffects.OrderByDescending(e => e.Order).ToList();
foreach (var layerEffectEntity in entities) foreach (var layerEffectEntity in entities)
{ {
// Skip effects already on the element // Skip effects already on the element
if (effectElement.LayerEffects.Any(e => e.EntityId == layerEffectEntity.Id)) if (renderElement.LayerEffects.Any(e => e.EntityId == layerEffectEntity.Id))
continue; continue;
// Get a matching descriptor // Get a matching descriptor
@ -130,7 +129,7 @@ namespace Artemis.Core.Services
// Create the effect with dependency injection // Create the effect with dependency injection
var effect = (BaseLayerEffect) _kernel.Get(descriptor.LayerEffectType); var effect = (BaseLayerEffect) _kernel.Get(descriptor.LayerEffectType);
effect.ProfileElement = effectElement; effect.ProfileElement = renderElement;
effect.EntityId = layerEffectEntity.Id; effect.EntityId = layerEffectEntity.Id;
effect.Order = layerEffectEntity.Order; effect.Order = layerEffectEntity.Order;
effect.Name = layerEffectEntity.Name; effect.Name = layerEffectEntity.Name;
@ -140,9 +139,14 @@ namespace Artemis.Core.Services
effect.Initialize(this); effect.Initialize(this);
effect.Update(0); effect.Update(0);
effectElement.AddLayerEffect(effect); renderElement.AddLayerEffect(effect);
_logger.Debug("Instantiated layer effect with root path {rootPath}", effect.PropertyRootPath); _logger.Debug("Instantiated layer effect with root path {rootPath}", effect.PropertyRootPath);
} }
} }
public void InstantiateDisplayConditions(RenderProfileElement renderElement)
{
}
} }
} }

View File

@ -4,7 +4,6 @@ namespace Artemis.Storage.Entities.Profile
{ {
public abstract class PropertiesEntity public abstract class PropertiesEntity
{ {
public List<ProfileConditionEntity> Conditions { get; set; }
public List<PropertyEntity> PropertyEntities { get; set; } public List<PropertyEntity> PropertyEntities { get; set; }
public List<string> ExpandedPropertyGroups { get; set; } public List<string> ExpandedPropertyGroups { get; set; }
} }

View File

@ -90,7 +90,7 @@
<Popup AllowsTransparency="True" <Popup AllowsTransparency="True"
Placement="Bottom" Placement="Bottom"
CustomPopupPlacementCallback="{x:Static materialDesign:CustomPopupPlacementCallbackHelper.LargePopupCallback}" CustomPopupPlacementCallback="{x:Static materialDesign:CustomPopupPlacementCallbackHelper.LargePopupCallback}"
PlacementTarget="{Binding ElementName=PART_TextBox}" PlacementTarget="{Binding ElementName=ColorCodeTextBox}"
StaysOpen="False" StaysOpen="False"
PopupAnimation="Fade" PopupAnimation="Fade"
IsOpen="{Binding PopupOpen, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"> IsOpen="{Binding PopupOpen, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">

View File

@ -1,22 +0,0 @@
using System;
using Artemis.Core.Models.Profile;
namespace Artemis.UI.Shared.Events
{
public class ProfileElementEventArgs : EventArgs
{
public ProfileElementEventArgs(ProfileElement profileElement)
{
ProfileElement = profileElement;
}
public ProfileElementEventArgs(ProfileElement profileElement, ProfileElement previousProfileElement)
{
ProfileElement = profileElement;
PreviousProfileElement = previousProfileElement;
}
public ProfileElement ProfileElement { get; }
public ProfileElement PreviousProfileElement { get; }
}
}

View File

@ -0,0 +1,22 @@
using System;
using Artemis.Core.Models.Profile;
namespace Artemis.UI.Shared.Events
{
public class ProfileEventArgs : EventArgs
{
public ProfileEventArgs(Profile profile)
{
Profile = profile;
}
public ProfileEventArgs(Profile profile, Profile previousProfile)
{
Profile = profile;
PreviousProfile = previousProfile;
}
public Profile Profile { get; }
public Profile PreviousProfile { get; }
}
}

View File

@ -0,0 +1,22 @@
using System;
using Artemis.Core.Models.Profile;
namespace Artemis.UI.Shared.Events
{
public class RenderProfileElementEventArgs : EventArgs
{
public RenderProfileElementEventArgs(RenderProfileElement renderProfileElement)
{
RenderProfileElement = renderProfileElement;
}
public RenderProfileElementEventArgs(RenderProfileElement renderProfileElement, RenderProfileElement previousRenderProfileElement)
{
RenderProfileElement = renderProfileElement;
PreviousRenderProfileElement = previousRenderProfileElement;
}
public RenderProfileElement RenderProfileElement { get; }
public RenderProfileElement PreviousRenderProfileElement { get; }
}
}

View File

@ -12,7 +12,7 @@ namespace Artemis.UI.Shared.Services.Interfaces
public interface IProfileEditorService : IArtemisSharedUIService public interface IProfileEditorService : IArtemisSharedUIService
{ {
Profile SelectedProfile { get; } Profile SelectedProfile { get; }
ProfileElement SelectedProfileElement { get; } RenderProfileElement SelectedProfileElement { get; }
TimeSpan CurrentTime { get; set; } TimeSpan CurrentTime { get; set; }
int PixelsPerSecond { get; set; } int PixelsPerSecond { get; set; }
IReadOnlyList<PropertyInputRegistration> RegisteredPropertyEditors { get; } IReadOnlyList<PropertyInputRegistration> RegisteredPropertyEditors { get; }
@ -20,7 +20,7 @@ namespace Artemis.UI.Shared.Services.Interfaces
void ChangeSelectedProfile(Profile profile); void ChangeSelectedProfile(Profile profile);
void UpdateSelectedProfile(); void UpdateSelectedProfile();
void ChangeSelectedProfileElement(ProfileElement profileElement); void ChangeSelectedProfileElement(RenderProfileElement profileElement);
void UpdateSelectedProfileElement(); void UpdateSelectedProfileElement();
void UpdateProfilePreview(); void UpdateProfilePreview();
void UndoUpdateProfile(ProfileModule module); void UndoUpdateProfile(ProfileModule module);
@ -32,22 +32,22 @@ namespace Artemis.UI.Shared.Services.Interfaces
/// <summary> /// <summary>
/// Occurs when a new profile is selected /// Occurs when a new profile is selected
/// </summary> /// </summary>
event EventHandler<ProfileElementEventArgs> ProfileSelected; event EventHandler<ProfileEventArgs> ProfileSelected;
/// <summary> /// <summary>
/// Occurs then the currently selected profile is updated /// Occurs then the currently selected profile is updated
/// </summary> /// </summary>
event EventHandler<ProfileElementEventArgs> SelectedProfileUpdated; event EventHandler<ProfileEventArgs> SelectedProfileUpdated;
/// <summary> /// <summary>
/// Occurs when a new profile element is selected /// Occurs when a new profile element is selected
/// </summary> /// </summary>
event EventHandler<ProfileElementEventArgs> ProfileElementSelected; event EventHandler<RenderProfileElementEventArgs> ProfileElementSelected;
/// <summary> /// <summary>
/// Occurs when the currently selected profile element is updated /// Occurs when the currently selected profile element is updated
/// </summary> /// </summary>
event EventHandler<ProfileElementEventArgs> SelectedProfileElementUpdated; event EventHandler<RenderProfileElementEventArgs> SelectedProfileElementUpdated;
/// <summary> /// <summary>
/// Occurs when the current editor time is changed /// Occurs when the current editor time is changed

View File

@ -11,6 +11,7 @@ using Artemis.UI.Shared.Events;
using Artemis.UI.Shared.PropertyInput; using Artemis.UI.Shared.PropertyInput;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;
using Ninject; using Ninject;
using Serilog;
namespace Artemis.UI.Shared.Services namespace Artemis.UI.Shared.Services
{ {
@ -18,15 +19,17 @@ namespace Artemis.UI.Shared.Services
{ {
private readonly ICoreService _coreService; private readonly ICoreService _coreService;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private readonly ILogger _logger;
private readonly List<PropertyInputRegistration> _registeredPropertyEditors; private readonly List<PropertyInputRegistration> _registeredPropertyEditors;
private TimeSpan _currentTime; private TimeSpan _currentTime;
private TimeSpan _lastUpdateTime; private TimeSpan _lastUpdateTime;
private int _pixelsPerSecond; private int _pixelsPerSecond;
public ProfileEditorService(ICoreService coreService, IProfileService profileService, IKernel kernel) public ProfileEditorService(ICoreService coreService, IProfileService profileService, IKernel kernel, ILogger logger)
{ {
_coreService = coreService; _coreService = coreService;
_profileService = profileService; _profileService = profileService;
_logger = logger;
_registeredPropertyEditors = new List<PropertyInputRegistration>(); _registeredPropertyEditors = new List<PropertyInputRegistration>();
Kernel = kernel; Kernel = kernel;
@ -36,7 +39,7 @@ namespace Artemis.UI.Shared.Services
public IKernel Kernel { get; } public IKernel Kernel { get; }
public IReadOnlyList<PropertyInputRegistration> RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly(); public IReadOnlyList<PropertyInputRegistration> RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly();
public Profile SelectedProfile { get; private set; } public Profile SelectedProfile { get; private set; }
public ProfileElement SelectedProfileElement { get; private set; } public RenderProfileElement SelectedProfileElement { get; private set; }
public TimeSpan CurrentTime public TimeSpan CurrentTime
{ {
@ -63,9 +66,13 @@ namespace Artemis.UI.Shared.Services
public void ChangeSelectedProfile(Profile profile) public void ChangeSelectedProfile(Profile profile)
{ {
if (SelectedProfile == profile)
return;
_logger.Verbose("ChangeSelectedProfile {profile}", profile);
ChangeSelectedProfileElement(null); ChangeSelectedProfileElement(null);
var profileElementEvent = new ProfileElementEventArgs(profile, SelectedProfile); var profileElementEvent = new ProfileEventArgs(profile, SelectedProfile);
SelectedProfile = profile; SelectedProfile = profile;
UpdateProfilePreview(); UpdateProfilePreview();
OnSelectedProfileChanged(profileElementEvent); OnSelectedProfileChanged(profileElementEvent);
@ -73,23 +80,29 @@ namespace Artemis.UI.Shared.Services
public void UpdateSelectedProfile() public void UpdateSelectedProfile()
{ {
_logger.Verbose("UpdateSelectedProfile {profile}", SelectedProfile);
_profileService.UpdateProfile(SelectedProfile, true); _profileService.UpdateProfile(SelectedProfile, true);
UpdateProfilePreview(); UpdateProfilePreview();
OnSelectedProfileElementUpdated(new ProfileElementEventArgs(SelectedProfile)); OnSelectedProfileChanged(new ProfileEventArgs(SelectedProfile));
} }
public void ChangeSelectedProfileElement(ProfileElement profileElement) public void ChangeSelectedProfileElement(RenderProfileElement profileElement)
{ {
var profileElementEvent = new ProfileElementEventArgs(profileElement, SelectedProfileElement); if (SelectedProfileElement == profileElement)
return;
_logger.Verbose("ChangeSelectedProfileElement {profile}", profileElement);
var profileElementEvent = new RenderProfileElementEventArgs(profileElement, SelectedProfileElement);
SelectedProfileElement = profileElement; SelectedProfileElement = profileElement;
OnSelectedProfileElementChanged(profileElementEvent); OnSelectedProfileElementChanged(profileElementEvent);
} }
public void UpdateSelectedProfileElement() public void UpdateSelectedProfileElement()
{ {
_logger.Verbose("UpdateSelectedProfileElement {profile}", SelectedProfileElement);
_profileService.UpdateProfile(SelectedProfile, true); _profileService.UpdateProfile(SelectedProfile, true);
UpdateProfilePreview(); UpdateProfilePreview();
OnSelectedProfileElementUpdated(new ProfileElementEventArgs(SelectedProfileElement)); OnSelectedProfileElementUpdated(new RenderProfileElementEventArgs(SelectedProfileElement));
} }
public void UpdateProfilePreview() public void UpdateProfilePreview()
@ -122,11 +135,11 @@ namespace Artemis.UI.Shared.Services
if (!undid) if (!undid)
return; return;
OnSelectedProfileChanged(new ProfileElementEventArgs(SelectedProfile, SelectedProfile)); OnSelectedProfileChanged(new ProfileEventArgs(SelectedProfile, SelectedProfile));
if (SelectedProfileElement != null) if (SelectedProfileElement != null)
{ {
var elements = SelectedProfile.GetAllLayers().Cast<ProfileElement>().ToList(); var elements = SelectedProfile.GetAllLayers().Cast<RenderProfileElement>().ToList();
elements.AddRange(SelectedProfile.GetAllFolders()); elements.AddRange(SelectedProfile.GetAllFolders());
var element = elements.FirstOrDefault(l => l.EntityId == SelectedProfileElement.EntityId); var element = elements.FirstOrDefault(l => l.EntityId == SelectedProfileElement.EntityId);
ChangeSelectedProfileElement(element); ChangeSelectedProfileElement(element);
@ -141,11 +154,11 @@ namespace Artemis.UI.Shared.Services
if (!redid) if (!redid)
return; return;
OnSelectedProfileChanged(new ProfileElementEventArgs(SelectedProfile, SelectedProfile)); OnSelectedProfileChanged(new ProfileEventArgs(SelectedProfile, SelectedProfile));
if (SelectedProfileElement != null) if (SelectedProfileElement != null)
{ {
var elements = SelectedProfile.GetAllLayers().Cast<ProfileElement>().ToList(); var elements = SelectedProfile.GetAllLayers().Cast<RenderProfileElement>().ToList();
elements.AddRange(SelectedProfile.GetAllFolders()); elements.AddRange(SelectedProfile.GetAllFolders());
var element = elements.FirstOrDefault(l => l.EntityId == SelectedProfileElement.EntityId); var element = elements.FirstOrDefault(l => l.EntityId == SelectedProfileElement.EntityId);
ChangeSelectedProfileElement(element); ChangeSelectedProfileElement(element);
@ -194,10 +207,10 @@ namespace Artemis.UI.Shared.Services
return (Module) SelectedProfile?.PluginInfo.Instance; return (Module) SelectedProfile?.PluginInfo.Instance;
} }
public event EventHandler<ProfileElementEventArgs> ProfileSelected; public event EventHandler<ProfileEventArgs> ProfileSelected;
public event EventHandler<ProfileElementEventArgs> SelectedProfileUpdated; public event EventHandler<ProfileEventArgs> SelectedProfileUpdated;
public event EventHandler<ProfileElementEventArgs> ProfileElementSelected; public event EventHandler<RenderProfileElementEventArgs> ProfileElementSelected;
public event EventHandler<ProfileElementEventArgs> SelectedProfileElementUpdated; public event EventHandler<RenderProfileElementEventArgs> SelectedProfileElementUpdated;
public event EventHandler CurrentTimeChanged; public event EventHandler CurrentTimeChanged;
public event EventHandler PixelsPerSecondChanged; public event EventHandler PixelsPerSecondChanged;
public event EventHandler ProfilePreviewUpdated; public event EventHandler ProfilePreviewUpdated;
@ -212,22 +225,22 @@ namespace Artemis.UI.Shared.Services
_coreService.PluginUpdatingDisabled = false; _coreService.PluginUpdatingDisabled = false;
} }
protected virtual void OnSelectedProfileChanged(ProfileElementEventArgs e) protected virtual void OnSelectedProfileChanged(ProfileEventArgs e)
{ {
ProfileSelected?.Invoke(this, e); ProfileSelected?.Invoke(this, e);
} }
protected virtual void OnSelectedProfileUpdated(ProfileElementEventArgs e) protected virtual void OnSelectedProfileUpdated(ProfileEventArgs e)
{ {
SelectedProfileUpdated?.Invoke(this, e); SelectedProfileUpdated?.Invoke(this, e);
} }
protected virtual void OnSelectedProfileElementChanged(ProfileElementEventArgs e) protected virtual void OnSelectedProfileElementChanged(RenderProfileElementEventArgs e)
{ {
ProfileElementSelected?.Invoke(this, e); ProfileElementSelected?.Invoke(this, e);
} }
protected virtual void OnSelectedProfileElementUpdated(ProfileElementEventArgs e) protected virtual void OnSelectedProfileElementUpdated(RenderProfileElementEventArgs e)
{ {
SelectedProfileElementUpdated?.Invoke(this, e); SelectedProfileElementUpdated?.Invoke(this, e);
} }

View File

@ -123,7 +123,6 @@
<Resource Include="Resources\Cursors\aero_rotate.cur" /> <Resource Include="Resources\Cursors\aero_rotate.cur" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Castle.Core" Version="4.4.1" />
<PackageReference Include="FluentValidation" Version="8.6.2" /> <PackageReference Include="FluentValidation" Version="8.6.2" />
<PackageReference Include="gong-wpf-dragdrop" Version="2.2.0" /> <PackageReference Include="gong-wpf-dragdrop" Version="2.2.0" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.11" /> <PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.11" />

View File

@ -1,5 +1,4 @@
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.Conditions;
using Artemis.Core.Models.Profile.Conditions;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Events; using Artemis.UI.Shared.Events;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;
@ -23,20 +22,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
set => SetAndNotify(ref _rootGroup, value); set => SetAndNotify(ref _rootGroup, value);
} }
private void ProfileEditorServiceOnProfileElementSelected(object sender, ProfileElementEventArgs e) private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
{ {
if (e.ProfileElement is Layer layer) if (e.RenderProfileElement == null)
{ {
// Ensure the layer has a root display condition group
if (layer.DisplayConditionGroup == null)
layer.DisplayConditionGroup = new DisplayConditionGroup();
RootGroup = _displayConditionsVmFactory.DisplayConditionGroupViewModel(layer.DisplayConditionGroup, null);
RootGroup.IsRootGroup = true;
RootGroup.Update();
}
else
RootGroup = null; RootGroup = null;
return;
}
// Ensure the layer has a root display condition group
if (e.RenderProfileElement.DisplayConditionGroup == null)
e.RenderProfileElement.DisplayConditionGroup = new DisplayConditionGroup();
RootGroup = _displayConditionsVmFactory.DisplayConditionGroupViewModel(e.RenderProfileElement.DisplayConditionGroup, null);
RootGroup.IsRootGroup = true;
RootGroup.Update();
} }
} }
} }

View File

@ -56,11 +56,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerEffects
private void HandleSelectedLayerEffectChanged(object sender, PropertyChangedEventArgs e) private void HandleSelectedLayerEffectChanged(object sender, PropertyChangedEventArgs e)
{ {
EffectProfileElement effectElement; RenderProfileElement renderElement;
if (LayerPropertiesViewModel.SelectedLayer != null) if (LayerPropertiesViewModel.SelectedLayer != null)
effectElement = LayerPropertiesViewModel.SelectedLayer; renderElement = LayerPropertiesViewModel.SelectedLayer;
else if (LayerPropertiesViewModel.SelectedFolder != null) else if (LayerPropertiesViewModel.SelectedFolder != null)
effectElement = LayerPropertiesViewModel.SelectedFolder; renderElement = LayerPropertiesViewModel.SelectedFolder;
else else
return; return;
@ -70,7 +70,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.LayerEffects
Execute.PostToUIThread(async () => Execute.PostToUIThread(async () =>
{ {
await Task.Delay(500); await Task.Delay(500);
_layerService.AddLayerEffect(effectElement, SelectedLayerEffectDescriptor); _layerService.AddLayerEffect(renderElement, SelectedLayerEffectDescriptor);
_profileEditorService.UpdateSelectedProfileElement(); _profileEditorService.UpdateSelectedProfileElement();
}); });
} }

View File

@ -29,7 +29,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
private LayerPropertyGroupViewModel _brushPropertyGroup; private LayerPropertyGroupViewModel _brushPropertyGroup;
private bool _repeatAfterLastKeyframe; private bool _repeatAfterLastKeyframe;
private int _propertyTreeIndex; private int _propertyTreeIndex;
private PropertiesProfileElement _selectedPropertiesElement; private RenderProfileElement _selectedProfileElement;
private BindableCollection<LayerPropertyGroupViewModel> _layerPropertyGroups; private BindableCollection<LayerPropertyGroupViewModel> _layerPropertyGroups;
private TreeViewModel _treeViewModel; private TreeViewModel _treeViewModel;
private EffectsViewModel _effectsViewModel; private EffectsViewModel _effectsViewModel;
@ -86,19 +86,19 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public bool PropertyTreeVisible => PropertyTreeIndex == 0; public bool PropertyTreeVisible => PropertyTreeIndex == 0;
public PropertiesProfileElement SelectedPropertiesElement public RenderProfileElement SelectedProfileElement
{ {
get => _selectedPropertiesElement; get => _selectedProfileElement;
set set
{ {
if (!SetAndNotify(ref _selectedPropertiesElement, value)) return; if (!SetAndNotify(ref _selectedProfileElement, value)) return;
NotifyOfPropertyChange(nameof(SelectedLayer)); NotifyOfPropertyChange(nameof(SelectedLayer));
NotifyOfPropertyChange(nameof(SelectedFolder)); NotifyOfPropertyChange(nameof(SelectedFolder));
} }
} }
public Layer SelectedLayer => SelectedPropertiesElement as Layer; public Layer SelectedLayer => SelectedProfileElement as Layer;
public Folder SelectedFolder => SelectedPropertiesElement as Folder; public Folder SelectedFolder => SelectedProfileElement as Folder;
public BindableCollection<LayerPropertyGroupViewModel> LayerPropertyGroups public BindableCollection<LayerPropertyGroupViewModel> LayerPropertyGroups
{ {
@ -126,8 +126,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
protected override void OnInitialActivate() protected override void OnInitialActivate()
{ {
if (ProfileEditorService.SelectedProfileElement is PropertiesProfileElement propertiesElement) PopulateProperties(ProfileEditorService.SelectedProfileElement);
PopulateProperties(propertiesElement);
ProfileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected; ProfileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected;
ProfileEditorService.CurrentTimeChanged += ProfileEditorServiceOnCurrentTimeChanged; ProfileEditorService.CurrentTimeChanged += ProfileEditorServiceOnCurrentTimeChanged;
@ -146,12 +145,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
base.OnClose(); base.OnClose();
} }
protected override void OnActivate()
{
PopulateProperties(ProfileEditorService.SelectedProfileElement as PropertiesProfileElement);
base.OnActivate();
}
protected override void OnDeactivate() protected override void OnDeactivate()
{ {
Pause(); Pause();
@ -164,12 +157,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
EffectsViewModel.PopulateDescriptors(); EffectsViewModel.PopulateDescriptors();
} }
private void ProfileEditorServiceOnProfileElementSelected(object sender, ProfileElementEventArgs e) private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
{ {
PopulateProperties(e.ProfileElement as PropertiesProfileElement); PopulateProperties(e.RenderProfileElement);
} }
private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e) private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e)
{ {
NotifyOfPropertyChange(nameof(FormattedCurrentTime)); NotifyOfPropertyChange(nameof(FormattedCurrentTime));
@ -190,23 +182,27 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
return groups; return groups;
} }
private void PopulateProperties(PropertiesProfileElement profileElement) private void PopulateProperties(RenderProfileElement profileElement)
{ {
if (SelectedPropertiesElement != null && SelectedPropertiesElement is EffectProfileElement effectElement) // Unsubscribe from old selected element
effectElement.LayerEffectsUpdated -= SelectedElementOnLayerEffectsUpdated; if (SelectedProfileElement != null)
SelectedProfileElement.LayerEffectsUpdated -= SelectedElementOnLayerEffectsUpdated;
if (SelectedLayer != null) if (SelectedLayer != null)
SelectedLayer.LayerBrushUpdated -= SelectedLayerOnLayerBrushUpdated; SelectedLayer.LayerBrushUpdated -= SelectedLayerOnLayerBrushUpdated;
// Clear old properties
foreach (var layerPropertyGroupViewModel in LayerPropertyGroups) foreach (var layerPropertyGroupViewModel in LayerPropertyGroups)
layerPropertyGroupViewModel.Dispose(); layerPropertyGroupViewModel.Dispose();
LayerPropertyGroups.Clear(); LayerPropertyGroups.Clear();
_brushPropertyGroup = null; _brushPropertyGroup = null;
SelectedPropertiesElement = profileElement; if (profileElement == null)
if (SelectedPropertiesElement is EffectProfileElement newEffectElement) return;
newEffectElement.LayerEffectsUpdated += SelectedElementOnLayerEffectsUpdated;
// Subscribe to new element
SelectedProfileElement = profileElement;
SelectedProfileElement.LayerEffectsUpdated += SelectedElementOnLayerEffectsUpdated;
// Apply layer properties
if (SelectedLayer != null) if (SelectedLayer != null)
{ {
SelectedLayer.LayerBrushUpdated += SelectedLayerOnLayerBrushUpdated; SelectedLayer.LayerBrushUpdated += SelectedLayerOnLayerBrushUpdated;
@ -278,21 +274,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
private void ApplyEffects() private void ApplyEffects()
{ {
EffectProfileElement effectElement; RenderProfileElement renderElement;
if (SelectedLayer != null) if (SelectedLayer != null)
effectElement = SelectedLayer; renderElement = SelectedLayer;
else if (SelectedFolder != null) else if (SelectedFolder != null)
effectElement = SelectedFolder; renderElement = SelectedFolder;
else else
return; return;
// Remove VMs of effects no longer applied on the layer // Remove VMs of effects no longer applied on the layer
var toRemove = LayerPropertyGroups.Where(l => l.LayerPropertyGroup.LayerEffect != null && !effectElement.LayerEffects.Contains(l.LayerPropertyGroup.LayerEffect)).ToList(); var toRemove = LayerPropertyGroups.Where(l => l.LayerPropertyGroup.LayerEffect != null && !renderElement.LayerEffects.Contains(l.LayerPropertyGroup.LayerEffect)).ToList();
LayerPropertyGroups.RemoveRange(toRemove); LayerPropertyGroups.RemoveRange(toRemove);
foreach (var layerPropertyGroupViewModel in toRemove) foreach (var layerPropertyGroupViewModel in toRemove)
layerPropertyGroupViewModel.Dispose(); layerPropertyGroupViewModel.Dispose();
foreach (var layerEffect in effectElement.LayerEffects) foreach (var layerEffect in renderElement.LayerEffects)
{ {
if (LayerPropertyGroups.Any(l => l.LayerPropertyGroup.LayerEffect == layerEffect)) if (LayerPropertyGroups.Any(l => l.LayerPropertyGroup.LayerEffect == layerEffect))
continue; continue;

View File

@ -28,6 +28,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
private PluginSetting<GridLength> _displayConditionsHeight; private PluginSetting<GridLength> _displayConditionsHeight;
private PluginSetting<GridLength> _bottomPanelsHeight; private PluginSetting<GridLength> _bottomPanelsHeight;
private PluginSetting<GridLength> _elementPropertiesWidth; private PluginSetting<GridLength> _elementPropertiesWidth;
private ProfileViewModel _profileViewModel;
private ProfileTreeViewModel _profileTreeViewModel;
private LayerPropertiesViewModel _layerPropertiesViewModel;
private DisplayConditionsViewModel _displayConditionsViewModel;
public ProfileEditorViewModel(ProfileModule module, public ProfileEditorViewModel(ProfileModule module,
ICollection<ProfileEditorPanelViewModel> viewModels, ICollection<ProfileEditorPanelViewModel> viewModels,
@ -44,21 +48,44 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
Module = module; Module = module;
DialogService = dialogService; DialogService = dialogService;
DisplayConditionsViewModel = (DisplayConditionsViewModel) viewModels.First(vm => vm is DisplayConditionsViewModel);
LayerPropertiesViewModel = (LayerPropertiesViewModel) viewModels.First(vm => vm is LayerPropertiesViewModel);
ProfileTreeViewModel = (ProfileTreeViewModel) viewModels.First(vm => vm is ProfileTreeViewModel);
ProfileViewModel = (ProfileViewModel) viewModels.First(vm => vm is ProfileViewModel);
Profiles = new BindableCollection<Profile>(); Profiles = new BindableCollection<Profile>();
// Run this first to let VMs activate without causing constant UI updates
Items.AddRange(viewModels); Items.AddRange(viewModels);
// Populate the panels
ProfileViewModel = (ProfileViewModel) viewModels.First(vm => vm is ProfileViewModel);
ProfileTreeViewModel = (ProfileTreeViewModel) viewModels.First(vm => vm is ProfileTreeViewModel);
DisplayConditionsViewModel = (DisplayConditionsViewModel) viewModels.First(vm => vm is DisplayConditionsViewModel);
LayerPropertiesViewModel = (LayerPropertiesViewModel) viewModels.First(vm => vm is LayerPropertiesViewModel);
} }
public ProfileModule Module { get; } public ProfileModule Module { get; }
public IDialogService DialogService { get; } public IDialogService DialogService { get; }
public DisplayConditionsViewModel DisplayConditionsViewModel { get; }
public LayerPropertiesViewModel LayerPropertiesViewModel { get; } public DisplayConditionsViewModel DisplayConditionsViewModel
public ProfileTreeViewModel ProfileTreeViewModel { get; } {
public ProfileViewModel ProfileViewModel { get; } get => _displayConditionsViewModel;
set => SetAndNotify(ref _displayConditionsViewModel, value);
}
public LayerPropertiesViewModel LayerPropertiesViewModel
{
get => _layerPropertiesViewModel;
set => SetAndNotify(ref _layerPropertiesViewModel, value);
}
public ProfileTreeViewModel ProfileTreeViewModel
{
get => _profileTreeViewModel;
set => SetAndNotify(ref _profileTreeViewModel, value);
}
public ProfileViewModel ProfileViewModel
{
get => _profileViewModel;
set => SetAndNotify(ref _profileViewModel, value);
}
public BindableCollection<Profile> Profiles public BindableCollection<Profile> Profiles
{ {

View File

@ -1,11 +1,13 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem; using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem;
using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Shared.Services.Interfaces;
using GongSolutions.Wpf.DragDrop; using GongSolutions.Wpf.DragDrop;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
{ {
@ -21,10 +23,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_folderVmFactory = folderVmFactory; _folderVmFactory = folderVmFactory;
CreateRootFolderViewModel();
_profileEditorService.ProfileSelected += OnProfileSelected;
_profileEditorService.ProfileElementSelected += OnProfileElementSelected;
} }
public FolderViewModel RootFolder public FolderViewModel RootFolder
@ -39,8 +37,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
set set
{ {
if (_updatingTree) return; if (_updatingTree) return;
SetAndNotify(ref _selectedTreeItem, value); if (!SetAndNotify(ref _selectedTreeItem, value)) return;
_profileEditorService.ChangeSelectedProfileElement(value?.ProfileElement);
if (value != null && value.ProfileElement is RenderProfileElement renderElement)
_profileEditorService.ChangeSelectedProfileElement(renderElement);
else
_profileEditorService.ChangeSelectedProfileElement(null);
} }
} }
@ -109,6 +111,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
RootFolder = _folderVmFactory.Create(folder); RootFolder = _folderVmFactory.Create(folder);
_updatingTree = false; _updatingTree = false;
// Auto-select the first layer
if (_profileEditorService.SelectedProfile != null && SelectedTreeItem == null)
{
if (_profileEditorService.SelectedProfile.GetRootFolder().Children.FirstOrDefault() is RenderProfileElement firstElement)
Execute.PostToUIThread(() => _profileEditorService.ChangeSelectedProfileElement(firstElement));
}
} }
private static DragDropType GetDragDropType(IDropInfo dropInfo) private static DragDropType GetDragDropType(IDropInfo dropInfo)
@ -140,8 +149,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
} }
} }
protected override void OnInitialActivate()
{
_profileEditorService.ProfileSelected += OnProfileSelected;
_profileEditorService.ProfileElementSelected += OnProfileElementSelected;
CreateRootFolderViewModel();
}
protected override void OnClose() protected override void OnClose()
{ {
_profileEditorService.ProfileSelected -= OnProfileSelected;
_profileEditorService.ProfileElementSelected -= OnProfileElementSelected;
RootFolder?.Dispose(); RootFolder?.Dispose();
RootFolder = null; RootFolder = null;
base.OnClose(); base.OnClose();