mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Profiles - Save folder open/closed state
Profiles editor - Save last selected element and reselect it Profile editor - Save pan/zoom position Profile editor - Added option to resume normal playback on focus loss
This commit is contained in:
parent
ab754942d5
commit
8728599dcc
@ -14,6 +14,8 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Folder : RenderProfileElement
|
public sealed class Folder : RenderProfileElement
|
||||||
{
|
{
|
||||||
|
private bool _isExpanded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="Folder" /> class and adds itself to the child collection of the provided
|
/// Creates a new instance of the <see cref="Folder" /> class and adds itself to the child collection of the provided
|
||||||
/// <paramref name="parent" />
|
/// <paramref name="parent" />
|
||||||
@ -46,6 +48,7 @@ namespace Artemis.Core
|
|||||||
Profile = profile;
|
Profile = profile;
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Name = folderEntity.Name;
|
Name = folderEntity.Name;
|
||||||
|
IsExpanded = folderEntity.IsExpanded;
|
||||||
Suspended = folderEntity.Suspended;
|
Suspended = folderEntity.Suspended;
|
||||||
Order = folderEntity.Order;
|
Order = folderEntity.Order;
|
||||||
|
|
||||||
@ -57,6 +60,15 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsRootFolder => Parent == Profile;
|
public bool IsRootFolder => Parent == Profile;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether this folder is expanded
|
||||||
|
/// </summary>
|
||||||
|
public bool IsExpanded
|
||||||
|
{
|
||||||
|
get => _isExpanded;
|
||||||
|
set => SetAndNotify(ref _isExpanded, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the folder entity this folder uses for persistent storage
|
/// Gets the folder entity this folder uses for persistent storage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -72,8 +84,10 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
List<ILayerProperty> result = new();
|
List<ILayerProperty> result = new();
|
||||||
foreach (BaseLayerEffect layerEffect in LayerEffects)
|
foreach (BaseLayerEffect layerEffect in LayerEffects)
|
||||||
|
{
|
||||||
if (layerEffect.BaseProperties != null)
|
if (layerEffect.BaseProperties != null)
|
||||||
result.AddRange(layerEffect.BaseProperties.GetAllLayerProperties());
|
result.AddRange(layerEffect.BaseProperties.GetAllLayerProperties());
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -151,27 +165,6 @@ namespace Artemis.Core
|
|||||||
return $"[Folder] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
return $"[Folder] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CalculateRenderProperties()
|
|
||||||
{
|
|
||||||
if (Disposed)
|
|
||||||
throw new ObjectDisposedException("Folder");
|
|
||||||
|
|
||||||
SKPath path = new() {FillType = SKPathFillType.Winding};
|
|
||||||
foreach (ProfileElement child in Children)
|
|
||||||
{
|
|
||||||
if (child is RenderProfileElement effectChild && effectChild.Path != null)
|
|
||||||
path.AddPath(effectChild.Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Path = path;
|
|
||||||
|
|
||||||
// Folder render properties are based on child paths and thus require an update
|
|
||||||
if (Parent is Folder folder)
|
|
||||||
folder.CalculateRenderProperties();
|
|
||||||
|
|
||||||
OnRenderPropertiesUpdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Rendering
|
#region Rendering
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -229,57 +222,6 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
Disposed = true;
|
|
||||||
|
|
||||||
Disable();
|
|
||||||
foreach (ProfileElement profileElement in Children)
|
|
||||||
profileElement.Dispose();
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void Load()
|
|
||||||
{
|
|
||||||
ExpandedPropertyGroups.AddRange(FolderEntity.ExpandedPropertyGroups);
|
|
||||||
Reset();
|
|
||||||
|
|
||||||
// Load child folders
|
|
||||||
foreach (FolderEntity childFolder in Profile.ProfileEntity.Folders.Where(f => f.ParentId == EntityId))
|
|
||||||
ChildrenList.Add(new Folder(Profile, this, childFolder));
|
|
||||||
// Load child layers
|
|
||||||
foreach (LayerEntity childLayer in Profile.ProfileEntity.Layers.Where(f => f.ParentId == EntityId))
|
|
||||||
ChildrenList.Add(new Layer(Profile, this, childLayer));
|
|
||||||
|
|
||||||
// Ensure order integrity, should be unnecessary but no one is perfect specially me
|
|
||||||
ChildrenList = ChildrenList.OrderBy(c => c.Order).ToList();
|
|
||||||
for (int index = 0; index < ChildrenList.Count; index++)
|
|
||||||
ChildrenList[index].Order = index + 1;
|
|
||||||
|
|
||||||
LoadRenderElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void Save()
|
|
||||||
{
|
|
||||||
if (Disposed)
|
|
||||||
throw new ObjectDisposedException("Folder");
|
|
||||||
|
|
||||||
FolderEntity.Id = EntityId;
|
|
||||||
FolderEntity.ParentId = Parent?.EntityId ?? new Guid();
|
|
||||||
|
|
||||||
FolderEntity.Order = Order;
|
|
||||||
FolderEntity.Name = Name;
|
|
||||||
FolderEntity.Suspended = Suspended;
|
|
||||||
|
|
||||||
FolderEntity.ProfileId = Profile.EntityId;
|
|
||||||
FolderEntity.ExpandedPropertyGroups.Clear();
|
|
||||||
FolderEntity.ExpandedPropertyGroups.AddRange(ExpandedPropertyGroups);
|
|
||||||
|
|
||||||
SaveRenderElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Enable()
|
public override void Enable()
|
||||||
{
|
{
|
||||||
@ -320,18 +262,87 @@ namespace Artemis.Core
|
|||||||
Enabled = false;
|
Enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Events
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when a property affecting the rendering properties of this folder has been updated
|
/// Occurs when a property affecting the rendering properties of this folder has been updated
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler? RenderPropertiesUpdated;
|
public event EventHandler? RenderPropertiesUpdated;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
Disposed = true;
|
||||||
|
|
||||||
|
Disable();
|
||||||
|
foreach (ProfileElement profileElement in Children)
|
||||||
|
profileElement.Dispose();
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void CalculateRenderProperties()
|
||||||
|
{
|
||||||
|
if (Disposed)
|
||||||
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
|
SKPath path = new() {FillType = SKPathFillType.Winding};
|
||||||
|
foreach (ProfileElement child in Children)
|
||||||
|
{
|
||||||
|
if (child is RenderProfileElement effectChild && effectChild.Path != null)
|
||||||
|
path.AddPath(effectChild.Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Path = path;
|
||||||
|
|
||||||
|
// Folder render properties are based on child paths and thus require an update
|
||||||
|
if (Parent is Folder folder)
|
||||||
|
folder.CalculateRenderProperties();
|
||||||
|
|
||||||
|
OnRenderPropertiesUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Load()
|
||||||
|
{
|
||||||
|
ExpandedPropertyGroups.AddRange(FolderEntity.ExpandedPropertyGroups);
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
// Load child folders
|
||||||
|
foreach (FolderEntity childFolder in Profile.ProfileEntity.Folders.Where(f => f.ParentId == EntityId))
|
||||||
|
ChildrenList.Add(new Folder(Profile, this, childFolder));
|
||||||
|
// Load child layers
|
||||||
|
foreach (LayerEntity childLayer in Profile.ProfileEntity.Layers.Where(f => f.ParentId == EntityId))
|
||||||
|
ChildrenList.Add(new Layer(Profile, this, childLayer));
|
||||||
|
|
||||||
|
// Ensure order integrity, should be unnecessary but no one is perfect specially me
|
||||||
|
ChildrenList = ChildrenList.OrderBy(c => c.Order).ToList();
|
||||||
|
for (int index = 0; index < ChildrenList.Count; index++)
|
||||||
|
ChildrenList[index].Order = index + 1;
|
||||||
|
|
||||||
|
LoadRenderElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Save()
|
||||||
|
{
|
||||||
|
if (Disposed)
|
||||||
|
throw new ObjectDisposedException("Folder");
|
||||||
|
|
||||||
|
FolderEntity.Id = EntityId;
|
||||||
|
FolderEntity.ParentId = Parent?.EntityId ?? new Guid();
|
||||||
|
|
||||||
|
FolderEntity.Order = Order;
|
||||||
|
FolderEntity.Name = Name;
|
||||||
|
FolderEntity.IsExpanded = IsExpanded;
|
||||||
|
FolderEntity.Suspended = Suspended;
|
||||||
|
|
||||||
|
FolderEntity.ProfileId = Profile.EntityId;
|
||||||
|
FolderEntity.ExpandedPropertyGroups.Clear();
|
||||||
|
FolderEntity.ExpandedPropertyGroups.AddRange(ExpandedPropertyGroups);
|
||||||
|
|
||||||
|
SaveRenderElement();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnRenderPropertiesUpdated()
|
private void OnRenderPropertiesUpdated()
|
||||||
{
|
{
|
||||||
RenderPropertiesUpdated?.Invoke(this, EventArgs.Empty);
|
RenderPropertiesUpdated?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,6 +14,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
private bool _isFreshImport;
|
private bool _isFreshImport;
|
||||||
|
private ProfileElement? _lastSelectedProfileElement;
|
||||||
|
|
||||||
internal Profile(ProfileConfiguration configuration, ProfileEntity profileEntity) : base(null!)
|
internal Profile(ProfileConfiguration configuration, ProfileEntity profileEntity) : base(null!)
|
||||||
{
|
{
|
||||||
@ -60,6 +61,15 @@ namespace Artemis.Core
|
|||||||
set => SetAndNotify(ref _isFreshImport, value);
|
set => SetAndNotify(ref _isFreshImport, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the last selected profile element of this profile
|
||||||
|
/// </summary>
|
||||||
|
public ProfileElement? LastSelectedProfileElement
|
||||||
|
{
|
||||||
|
get => _lastSelectedProfileElement;
|
||||||
|
set => SetAndNotify(ref _lastSelectedProfileElement, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the profile entity this profile uses for persistent storage
|
/// Gets the profile entity this profile uses for persistent storage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -187,6 +197,15 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ProfileEntity.LastSelectedProfileElement != Guid.Empty)
|
||||||
|
{
|
||||||
|
LastSelectedProfileElement = GetAllFolders().FirstOrDefault(f => f.EntityId == ProfileEntity.LastSelectedProfileElement);
|
||||||
|
if (LastSelectedProfileElement == null)
|
||||||
|
LastSelectedProfileElement = GetAllLayers().FirstOrDefault(f => f.EntityId == ProfileEntity.LastSelectedProfileElement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LastSelectedProfileElement = null;
|
||||||
|
|
||||||
foreach (ScriptConfiguration scriptConfiguration in ScriptConfigurations)
|
foreach (ScriptConfiguration scriptConfiguration in ScriptConfigurations)
|
||||||
scriptConfiguration.Script?.Dispose();
|
scriptConfiguration.Script?.Dispose();
|
||||||
ScriptConfigurations.Clear();
|
ScriptConfigurations.Clear();
|
||||||
@ -201,6 +220,7 @@ namespace Artemis.Core
|
|||||||
ProfileEntity.Id = EntityId;
|
ProfileEntity.Id = EntityId;
|
||||||
ProfileEntity.Name = Configuration.Name;
|
ProfileEntity.Name = Configuration.Name;
|
||||||
ProfileEntity.IsFreshImport = IsFreshImport;
|
ProfileEntity.IsFreshImport = IsFreshImport;
|
||||||
|
ProfileEntity.LastSelectedProfileElement = LastSelectedProfileElement?.EntityId ?? Guid.Empty;
|
||||||
|
|
||||||
foreach (ProfileElement profileElement in Children)
|
foreach (ProfileElement profileElement in Children)
|
||||||
profileElement.Save();
|
profileElement.Save();
|
||||||
|
|||||||
@ -179,7 +179,8 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("ProfileConfiguration");
|
throw new ObjectDisposedException("ProfileConfiguration");
|
||||||
|
if (IsBeingEdited)
|
||||||
|
return true;
|
||||||
if (Category.IsSuspended || IsSuspended || IsMissingModule)
|
if (Category.IsSuspended || IsSuspended || IsMissingModule)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@ -209,7 +209,7 @@ namespace Artemis.Core.Services
|
|||||||
ProcessPendingKeyEvents(profileConfiguration);
|
ProcessPendingKeyEvents(profileConfiguration);
|
||||||
|
|
||||||
// Profiles being edited are updated at their own leisure
|
// Profiles being edited are updated at their own leisure
|
||||||
if (profileConfiguration.IsBeingEdited)
|
if (profileConfiguration.IsBeingEdited && RenderForEditor)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool shouldBeActive = profileConfiguration.ShouldBeActive(false);
|
bool shouldBeActive = profileConfiguration.ShouldBeActive(false);
|
||||||
@ -254,11 +254,9 @@ namespace Artemis.Core.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
|
ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
|
||||||
if (RenderForEditor)
|
// Always render profiles being edited
|
||||||
{
|
|
||||||
if (profileConfiguration.IsBeingEdited)
|
if (profileConfiguration.IsBeingEdited)
|
||||||
profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
|
profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Ensure all criteria are met before rendering
|
// Ensure all criteria are met before rendering
|
||||||
|
|||||||
@ -16,6 +16,7 @@ namespace Artemis.Storage.Entities.Profile
|
|||||||
|
|
||||||
public int Order { get; set; }
|
public int Order { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
public bool IsExpanded { get; set; }
|
||||||
public bool Suspended { get; set; }
|
public bool Suspended { get; set; }
|
||||||
|
|
||||||
[BsonRef("ProfileEntity")]
|
[BsonRef("ProfileEntity")]
|
||||||
|
|||||||
@ -18,6 +18,7 @@ namespace Artemis.Storage.Entities.Profile
|
|||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public bool IsFreshImport { get; set; }
|
public bool IsFreshImport { get; set; }
|
||||||
|
public Guid LastSelectedProfileElement { get; set; }
|
||||||
|
|
||||||
public List<FolderEntity> Folders { get; set; }
|
public List<FolderEntity> Folders { get; set; }
|
||||||
public List<LayerEntity> Layers { get; set; }
|
public List<LayerEntity> Layers { get; set; }
|
||||||
|
|||||||
@ -27,12 +27,12 @@ namespace Artemis.UI.Shared
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the minimum value
|
/// Gets or sets the minimum value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty MinProperty = DependencyProperty.Register(nameof(Min), typeof(float?), typeof(DraggableFloat));
|
public static readonly DependencyProperty MinProperty = DependencyProperty.Register(nameof(Min), typeof(object), typeof(DraggableFloat));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the maximum value
|
/// Gets or sets the maximum value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly DependencyProperty MaxProperty = DependencyProperty.Register(nameof(Max), typeof(float?), typeof(DraggableFloat));
|
public static readonly DependencyProperty MaxProperty = DependencyProperty.Register(nameof(Max), typeof(object), typeof(DraggableFloat));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when the value has changed
|
/// Occurs when the value has changed
|
||||||
@ -90,18 +90,18 @@ namespace Artemis.UI.Shared
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the minimum value
|
/// Gets or sets the minimum value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float? Min
|
public object? Min
|
||||||
{
|
{
|
||||||
get => (float?) GetValue(MinProperty);
|
get => (object?) GetValue(MinProperty);
|
||||||
set => SetValue(MinProperty, value);
|
set => SetValue(MinProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the maximum value
|
/// Gets or sets the maximum value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float? Max
|
public object? Max
|
||||||
{
|
{
|
||||||
get => (float?) GetValue(MaxProperty);
|
get => (object?) GetValue(MaxProperty);
|
||||||
set => SetValue(MaxProperty, value);
|
set => SetValue(MaxProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,10 +207,11 @@ namespace Artemis.UI.Shared
|
|||||||
stepSize = stepSize * 10;
|
stepSize = stepSize * 10;
|
||||||
|
|
||||||
float value = (float) RoundToNearestOf(startValue + stepSize * (x - startX), stepSize);
|
float value = (float) RoundToNearestOf(startValue + stepSize * (x - startX), stepSize);
|
||||||
if (Min != null)
|
|
||||||
value = Math.Max(value, Min.Value);
|
if (Min != null && float.TryParse(Min.ToString(), out float minFloat))
|
||||||
if (Max != null)
|
value = Math.Max(value, minFloat);
|
||||||
value = Math.Min(value, Max.Value);
|
if (Max != null && float.TryParse(Max.ToString(), out float maxFloat))
|
||||||
|
value = Math.Min(value, maxFloat);
|
||||||
|
|
||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,9 +17,17 @@ namespace Artemis.UI.Shared.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
ProfileConfiguration? SelectedProfileConfiguration { get; }
|
ProfileConfiguration? SelectedProfileConfiguration { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the previous selected profile configuration
|
||||||
|
/// </summary>
|
||||||
|
ProfileConfiguration? PreviousSelectedProfileConfiguration { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the currently selected profile
|
/// Gets the currently selected profile
|
||||||
/// <para><see langword="null" /> if the editor is closed, always equal to <see cref="SelectedProfileConfiguration" />.<see cref="Profile" /></para>
|
/// <para>
|
||||||
|
/// <see langword="null" /> if the editor is closed, always equal to <see cref="SelectedProfileConfiguration" />.
|
||||||
|
/// <see cref="Profile" />
|
||||||
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Profile? SelectedProfile { get; }
|
Profile? SelectedProfile { get; }
|
||||||
|
|
||||||
@ -53,6 +61,11 @@ namespace Artemis.UI.Shared.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
bool Playing { get; set; }
|
bool Playing { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a boolean indicating whether editing should be suspended
|
||||||
|
/// </summary>
|
||||||
|
bool SuspendEditing { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes the selected profile by its <see cref="ProfileConfiguration" />
|
/// Changes the selected profile by its <see cref="ProfileConfiguration" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -4,7 +4,6 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Modules;
|
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
using Artemis.UI.Shared.Services.Models;
|
using Artemis.UI.Shared.Services.Models;
|
||||||
@ -30,6 +29,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
private TimeSpan _currentTime;
|
private TimeSpan _currentTime;
|
||||||
private bool _doTick;
|
private bool _doTick;
|
||||||
private int _pixelsPerSecond;
|
private int _pixelsPerSecond;
|
||||||
|
private bool _suspendEditing;
|
||||||
|
|
||||||
public ProfileEditorService(IKernel kernel, ILogger logger, IProfileService profileService, ICoreService coreService, IRgbService rgbService, IModuleService moduleService)
|
public ProfileEditorService(IKernel kernel, ILogger logger, IProfileService profileService, ICoreService coreService, IRgbService rgbService, IModuleService moduleService)
|
||||||
{
|
{
|
||||||
@ -76,7 +76,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
|
|
||||||
private void Tick()
|
private void Tick()
|
||||||
{
|
{
|
||||||
if (SelectedProfile == null || _doTick)
|
if (SelectedProfile == null || _doTick || SuspendEditing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TickProfileElement(SelectedProfile.GetRootFolder());
|
TickProfileElement(SelectedProfile.GetRootFolder());
|
||||||
@ -106,6 +106,27 @@ namespace Artemis.UI.Shared.Services
|
|||||||
public ReadOnlyCollection<PropertyInputRegistration> RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly();
|
public ReadOnlyCollection<PropertyInputRegistration> RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly();
|
||||||
|
|
||||||
public bool Playing { get; set; }
|
public bool Playing { get; set; }
|
||||||
|
|
||||||
|
public bool SuspendEditing
|
||||||
|
{
|
||||||
|
get => _suspendEditing;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_suspendEditing = value;
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
Playing = false;
|
||||||
|
_profileService.RenderForEditor = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SelectedProfileConfiguration != null)
|
||||||
|
_profileService.RenderForEditor = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileConfiguration? PreviousSelectedProfileConfiguration { get; private set; }
|
||||||
public ProfileConfiguration? SelectedProfileConfiguration { get; private set; }
|
public ProfileConfiguration? SelectedProfileConfiguration { get; private set; }
|
||||||
public Profile? SelectedProfile => SelectedProfileConfiguration?.Profile;
|
public Profile? SelectedProfile => SelectedProfileConfiguration?.Profile;
|
||||||
public RenderProfileElement? SelectedProfileElement { get; private set; }
|
public RenderProfileElement? SelectedProfileElement { get; private set; }
|
||||||
@ -152,13 +173,18 @@ namespace Artemis.UI.Shared.Services
|
|||||||
SelectedProfileConfiguration.IsBeingEdited = false;
|
SelectedProfileConfiguration.IsBeingEdited = false;
|
||||||
|
|
||||||
// The new profile may need activation
|
// The new profile may need activation
|
||||||
|
PreviousSelectedProfileConfiguration = SelectedProfileConfiguration;
|
||||||
SelectedProfileConfiguration = profileConfiguration;
|
SelectedProfileConfiguration = profileConfiguration;
|
||||||
|
;
|
||||||
if (SelectedProfileConfiguration != null)
|
if (SelectedProfileConfiguration != null)
|
||||||
{
|
{
|
||||||
SelectedProfileConfiguration.IsBeingEdited = true;
|
SelectedProfileConfiguration.IsBeingEdited = true;
|
||||||
_moduleService.SetActivationOverride(SelectedProfileConfiguration.Module);
|
_moduleService.SetActivationOverride(SelectedProfileConfiguration.Module);
|
||||||
_profileService.ActivateProfile(SelectedProfileConfiguration);
|
_profileService.ActivateProfile(SelectedProfileConfiguration);
|
||||||
_profileService.RenderForEditor = true;
|
_profileService.RenderForEditor = true;
|
||||||
|
|
||||||
|
if (SelectedProfileConfiguration.Profile?.LastSelectedProfileElement is RenderProfileElement renderProfileElement)
|
||||||
|
ChangeSelectedProfileElement(renderProfileElement);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -179,6 +205,7 @@ namespace Artemis.UI.Shared.Services
|
|||||||
if (SelectedProfile == null)
|
if (SelectedProfile == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
SelectedProfile.LastSelectedProfileElement = SelectedProfileElement;
|
||||||
_profileService.SaveProfile(SelectedProfile, true);
|
_profileService.SaveProfile(SelectedProfile, true);
|
||||||
OnSelectedProfileUpdated(new ProfileConfigurationEventArgs(SelectedProfileConfiguration));
|
OnSelectedProfileUpdated(new ProfileConfigurationEventArgs(SelectedProfileConfiguration));
|
||||||
UpdateProfilePreview();
|
UpdateProfilePreview();
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
namespace Artemis.UI.Events
|
using Artemis.UI.Screens.Sidebar;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Events
|
||||||
{
|
{
|
||||||
public class RequestSelectSidebarItemEvent
|
public class RequestSelectSidebarItemEvent
|
||||||
{
|
{
|
||||||
@ -7,6 +9,12 @@
|
|||||||
DisplayName = displayName;
|
DisplayName = displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RequestSelectSidebarItemEvent(SidebarScreenViewModel viewModel)
|
||||||
|
{
|
||||||
|
ViewModel = viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
public string DisplayName { get; }
|
public string DisplayName { get; }
|
||||||
|
public SidebarScreenViewModel ViewModel { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -559,6 +559,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
|
|
||||||
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (!ProfileEditorService.Playing)
|
||||||
|
{
|
||||||
|
Pause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Execute.PostToUIThread(() =>
|
Execute.PostToUIThread(() =>
|
||||||
{
|
{
|
||||||
TimeSpan newTime = ProfileEditorService.CurrentTime.Add(TimeSpan.FromSeconds(e.DeltaTime));
|
TimeSpan newTime = ProfileEditorService.CurrentTime.Add(TimeSpan.FromSeconds(e.DeltaTime));
|
||||||
|
|||||||
@ -110,6 +110,24 @@
|
|||||||
IsEnabled="{Binding HasSelectedElement}"
|
IsEnabled="{Binding HasSelectedElement}"
|
||||||
Command="{s:Action OpenLayerPropertyScripts}"/>
|
Command="{s:Action OpenLayerPropertyScripts}"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem Header="_Options">
|
||||||
|
<MenuItem Header="Focus Selected Layer"
|
||||||
|
ToolTip="If enabled, displays only the layer you currently have selected"
|
||||||
|
IsCheckable="True"
|
||||||
|
IsChecked="{Binding FocusSelectedLayer.Value}"
|
||||||
|
IsEnabled="False"/>
|
||||||
|
<MenuItem Header="Display Data Model Values"
|
||||||
|
IsCheckable="True"
|
||||||
|
IsChecked="{Binding ShowDataModelValues.Value}"/>
|
||||||
|
<MenuItem Header="Run Profile on Focus Loss"
|
||||||
|
ToolTip="If enabled, regular profile playback is resumed on focus loss"
|
||||||
|
IsCheckable="True"
|
||||||
|
IsChecked="{Binding StopOnFocusLoss.Value}"/>
|
||||||
|
<MenuItem Header="Apply All Data Bindings During Edit"
|
||||||
|
ToolTip="If enabled, updates all data bindings instead of only the one you are editing"
|
||||||
|
IsCheckable="True"
|
||||||
|
IsChecked="{Binding AlwaysApplyDataBindings.Value}"/>
|
||||||
|
</MenuItem>
|
||||||
<MenuItem Header="_Help">
|
<MenuItem Header="_Help">
|
||||||
<MenuItem Header="Artemis Wiki"
|
<MenuItem Header="Artemis Wiki"
|
||||||
Icon="{materialDesign:PackIcon Kind=BookEdit}"
|
Icon="{materialDesign:PackIcon Kind=BookEdit}"
|
||||||
|
|||||||
@ -1,24 +1,28 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Events;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
|
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties;
|
||||||
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||||
using Artemis.UI.Screens.ProfileEditor.Visualization;
|
using Artemis.UI.Screens.ProfileEditor.Visualization;
|
||||||
|
using Artemis.UI.Screens.Sidebar;
|
||||||
using Artemis.UI.Services;
|
using Artemis.UI.Services;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
using MaterialDesignThemes.Wpf;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
using ProfileConfigurationEventArgs = Artemis.UI.Shared.ProfileConfigurationEventArgs;
|
using ProfileConfigurationEventArgs = Artemis.UI.Shared.ProfileConfigurationEventArgs;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor
|
namespace Artemis.UI.Screens.ProfileEditor
|
||||||
{
|
{
|
||||||
public class ProfileEditorViewModel : MainScreenViewModel
|
public class ProfileEditorViewModel : MainScreenViewModel, IHandle<MainWindowFocusChangedEvent>
|
||||||
{
|
{
|
||||||
private readonly IDebugService _debugService;
|
private readonly IDebugService _debugService;
|
||||||
private readonly IMessageService _messageService;
|
private readonly IMessageService _messageService;
|
||||||
@ -28,14 +32,11 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
private readonly ISidebarVmFactory _sidebarVmFactory;
|
private readonly ISidebarVmFactory _sidebarVmFactory;
|
||||||
private readonly IWindowManager _windowManager;
|
private readonly IWindowManager _windowManager;
|
||||||
private PluginSetting<GridLength> _bottomPanelsHeight;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private PluginSetting<GridLength> _dataModelConditionsHeight;
|
|
||||||
private DisplayConditionsViewModel _displayConditionsViewModel;
|
private DisplayConditionsViewModel _displayConditionsViewModel;
|
||||||
private PluginSetting<GridLength> _elementPropertiesWidth;
|
|
||||||
private LayerPropertiesViewModel _layerPropertiesViewModel;
|
private LayerPropertiesViewModel _layerPropertiesViewModel;
|
||||||
private ProfileTreeViewModel _profileTreeViewModel;
|
private ProfileTreeViewModel _profileTreeViewModel;
|
||||||
private ProfileViewModel _profileViewModel;
|
private ProfileViewModel _profileViewModel;
|
||||||
private PluginSetting<GridLength> _sidePanelsWidth;
|
|
||||||
|
|
||||||
public ProfileEditorViewModel(ProfileViewModel profileViewModel,
|
public ProfileEditorViewModel(ProfileViewModel profileViewModel,
|
||||||
ProfileTreeViewModel profileTreeViewModel,
|
ProfileTreeViewModel profileTreeViewModel,
|
||||||
@ -48,6 +49,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
IMessageService messageService,
|
IMessageService messageService,
|
||||||
IDebugService debugService,
|
IDebugService debugService,
|
||||||
IWindowManager windowManager,
|
IWindowManager windowManager,
|
||||||
|
IEventAggregator eventAggregator,
|
||||||
IScriptVmFactory scriptVmFactory,
|
IScriptVmFactory scriptVmFactory,
|
||||||
ISidebarVmFactory sidebarVmFactory)
|
ISidebarVmFactory sidebarVmFactory)
|
||||||
{
|
{
|
||||||
@ -57,6 +59,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
_messageService = messageService;
|
_messageService = messageService;
|
||||||
_debugService = debugService;
|
_debugService = debugService;
|
||||||
_windowManager = windowManager;
|
_windowManager = windowManager;
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
_scriptVmFactory = scriptVmFactory;
|
_scriptVmFactory = scriptVmFactory;
|
||||||
_sidebarVmFactory = sidebarVmFactory;
|
_sidebarVmFactory = sidebarVmFactory;
|
||||||
|
|
||||||
@ -102,29 +105,14 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
set => SetAndNotify(ref _profileViewModel, value);
|
set => SetAndNotify(ref _profileViewModel, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginSetting<GridLength> SidePanelsWidth
|
public PluginSetting<GridLength> SidePanelsWidth => _settingsService.GetSetting("ProfileEditor.SidePanelsWidth", new GridLength(385));
|
||||||
{
|
public PluginSetting<GridLength> DataModelConditionsHeight => _settingsService.GetSetting("ProfileEditor.DataModelConditionsHeight", new GridLength(345));
|
||||||
get => _sidePanelsWidth;
|
public PluginSetting<GridLength> BottomPanelsHeight => _settingsService.GetSetting("ProfileEditor.BottomPanelsHeight", new GridLength(265));
|
||||||
set => SetAndNotify(ref _sidePanelsWidth, value);
|
public PluginSetting<GridLength> ElementPropertiesWidth => _settingsService.GetSetting("ProfileEditor.ElementPropertiesWidth", new GridLength(545));
|
||||||
}
|
public PluginSetting<bool> StopOnFocusLoss => _settingsService.GetSetting("ProfileEditor.StopOnFocusLoss", true);
|
||||||
|
public PluginSetting<bool> ShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
||||||
public PluginSetting<GridLength> DataModelConditionsHeight
|
public PluginSetting<bool> FocusSelectedLayer => _settingsService.GetSetting("ProfileEditor.FocusSelectedLayer", true);
|
||||||
{
|
public PluginSetting<bool> AlwaysApplyDataBindings => _settingsService.GetSetting("ProfileEditor.AlwaysApplyDataBindings", true);
|
||||||
get => _dataModelConditionsHeight;
|
|
||||||
set => SetAndNotify(ref _dataModelConditionsHeight, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PluginSetting<GridLength> BottomPanelsHeight
|
|
||||||
{
|
|
||||||
get => _bottomPanelsHeight;
|
|
||||||
set => SetAndNotify(ref _bottomPanelsHeight, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PluginSetting<GridLength> ElementPropertiesWidth
|
|
||||||
{
|
|
||||||
get => _elementPropertiesWidth;
|
|
||||||
set => SetAndNotify(ref _elementPropertiesWidth, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Undo()
|
public void Undo()
|
||||||
{
|
{
|
||||||
@ -180,25 +168,39 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
_messageService.ShowMessage("Redid profile update", "UNDO", Undo);
|
_messageService.ShowMessage("Redid profile update", "UNDO", Undo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Overrides of Screen
|
||||||
|
|
||||||
protected override void OnInitialActivate()
|
protected override void OnInitialActivate()
|
||||||
{
|
{
|
||||||
|
StopOnFocusLoss.AutoSave = true;
|
||||||
|
ShowDataModelValues.AutoSave = true;
|
||||||
|
FocusSelectedLayer.AutoSave = true;
|
||||||
|
AlwaysApplyDataBindings.AutoSave = true;
|
||||||
|
|
||||||
_profileEditorService.SelectedProfileChanged += ProfileEditorServiceOnSelectedProfileChanged;
|
_profileEditorService.SelectedProfileChanged += ProfileEditorServiceOnSelectedProfileChanged;
|
||||||
_profileEditorService.SelectedProfileElementChanged += ProfileEditorServiceOnSelectedProfileElementChanged;
|
_profileEditorService.SelectedProfileElementChanged += ProfileEditorServiceOnSelectedProfileElementChanged;
|
||||||
LoadWorkspaceSettings();
|
_eventAggregator.Subscribe(this);
|
||||||
base.OnInitialActivate();
|
base.OnInitialActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClose()
|
protected override void OnClose()
|
||||||
{
|
{
|
||||||
|
StopOnFocusLoss.AutoSave = false;
|
||||||
|
ShowDataModelValues.AutoSave = false;
|
||||||
|
FocusSelectedLayer.AutoSave = false;
|
||||||
|
AlwaysApplyDataBindings.AutoSave = false;
|
||||||
|
|
||||||
_profileEditorService.SelectedProfileChanged -= ProfileEditorServiceOnSelectedProfileChanged;
|
_profileEditorService.SelectedProfileChanged -= ProfileEditorServiceOnSelectedProfileChanged;
|
||||||
_profileEditorService.SelectedProfileElementChanged -= ProfileEditorServiceOnSelectedProfileElementChanged;
|
_profileEditorService.SelectedProfileElementChanged -= ProfileEditorServiceOnSelectedProfileElementChanged;
|
||||||
|
_eventAggregator.Unsubscribe(this);
|
||||||
SaveWorkspaceSettings();
|
SaveWorkspaceSettings();
|
||||||
_profileEditorService.ChangeSelectedProfileConfiguration(null);
|
_profileEditorService.ChangeSelectedProfileConfiguration(null);
|
||||||
|
|
||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
private void ProfileEditorServiceOnSelectedProfileChanged(object sender, ProfileConfigurationEventArgs e)
|
private void ProfileEditorServiceOnSelectedProfileChanged(object sender, ProfileConfigurationEventArgs e)
|
||||||
{
|
{
|
||||||
NotifyOfPropertyChange(nameof(ProfileConfiguration));
|
NotifyOfPropertyChange(nameof(ProfileConfiguration));
|
||||||
@ -209,14 +211,6 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
NotifyOfPropertyChange(nameof(HasSelectedElement));
|
NotifyOfPropertyChange(nameof(HasSelectedElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadWorkspaceSettings()
|
|
||||||
{
|
|
||||||
SidePanelsWidth = _settingsService.GetSetting("ProfileEditor.SidePanelsWidth", new GridLength(385));
|
|
||||||
DataModelConditionsHeight = _settingsService.GetSetting("ProfileEditor.DataModelConditionsHeight", new GridLength(345));
|
|
||||||
BottomPanelsHeight = _settingsService.GetSetting("ProfileEditor.BottomPanelsHeight", new GridLength(265));
|
|
||||||
ElementPropertiesWidth = _settingsService.GetSetting("ProfileEditor.ElementPropertiesWidth", new GridLength(545));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveWorkspaceSettings()
|
private void SaveWorkspaceSettings()
|
||||||
{
|
{
|
||||||
SidePanelsWidth.Save();
|
SidePanelsWidth.Save();
|
||||||
@ -322,5 +316,19 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Implementation of IHandle<in MainWindowFocusChangedEvent>
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Handle(MainWindowFocusChangedEvent message)
|
||||||
|
{
|
||||||
|
if (!StopOnFocusLoss.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_profileEditorService.SuspendEditing = !message.IsFocused;
|
||||||
|
ProfileViewModel.SuspendedEditing = !message.IsFocused;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,6 +97,11 @@
|
|||||||
<b:Interaction.Behaviors>
|
<b:Interaction.Behaviors>
|
||||||
<behaviors:TreeViewSelectionBehavior SelectedItem="{Binding SelectedTreeItem}" />
|
<behaviors:TreeViewSelectionBehavior SelectedItem="{Binding SelectedTreeItem}" />
|
||||||
</b:Interaction.Behaviors>
|
</b:Interaction.Behaviors>
|
||||||
|
<TreeView.ItemContainerStyle>
|
||||||
|
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource MaterialDesignTreeViewItem}">
|
||||||
|
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay, FallbackValue=False}"/>
|
||||||
|
</Style>
|
||||||
|
</TreeView.ItemContainerStyle>
|
||||||
<TreeView.Resources>
|
<TreeView.Resources>
|
||||||
<HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Items}">
|
<HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Items}">
|
||||||
<ContentControl s:View.Model="{Binding}" />
|
<ContentControl s:View.Model="{Binding}" />
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
@ -24,8 +25,6 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_profileTreeVmFactory = profileTreeVmFactory;
|
_profileTreeVmFactory = profileTreeVmFactory;
|
||||||
|
|
||||||
CreateRootFolderViewModel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TreeItemViewModel SelectedTreeItem
|
public TreeItemViewModel SelectedTreeItem
|
||||||
@ -54,6 +53,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
protected override void OnInitialActivate()
|
protected override void OnInitialActivate()
|
||||||
{
|
{
|
||||||
Subscribe();
|
Subscribe();
|
||||||
|
CreateRootFolderViewModel();
|
||||||
base.OnInitialActivate();
|
base.OnInitialActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +83,13 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
|
|
||||||
ActiveItem = _profileTreeVmFactory.FolderViewModel(folder);
|
ActiveItem = _profileTreeVmFactory.FolderViewModel(folder);
|
||||||
_updatingTree = false;
|
_updatingTree = false;
|
||||||
|
|
||||||
|
Execute.PostToUIThread(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(1500);
|
||||||
|
SelectedTreeItem = ActiveItem.GetAllChildren().FirstOrDefault(c => c.ProfileElement == _profileEditorService.SelectedProfileElement);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDropTarget
|
#region IDropTarget
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Artemis.Core;
|
using System.ComponentModel;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
@ -19,5 +20,35 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override bool SupportsChildren => true;
|
public override bool SupportsChildren => true;
|
||||||
|
|
||||||
|
public override bool IsExpanded
|
||||||
|
{
|
||||||
|
get => ((Folder) ProfileElement).IsExpanded;
|
||||||
|
set => ((Folder) ProfileElement).IsExpanded = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProfileElementOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.PropertyName == nameof(Folder.IsExpanded))
|
||||||
|
NotifyOfPropertyChange(nameof(IsExpanded));
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of Screen
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnInitialActivate()
|
||||||
|
{
|
||||||
|
ProfileElement.PropertyChanged += ProfileElementOnPropertyChanged;
|
||||||
|
base.OnInitialActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
ProfileElement.PropertyChanged -= ProfileElementOnPropertyChanged;
|
||||||
|
base.OnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,5 +33,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
public Layer Layer => ProfileElement as Layer;
|
public Layer Layer => ProfileElement as Layer;
|
||||||
public bool ShowIcons => Layer?.LayerBrush != null;
|
public bool ShowIcons => Layer?.LayerBrush != null;
|
||||||
public override bool SupportsChildren => false;
|
public override bool SupportsChildren => false;
|
||||||
|
|
||||||
|
public override bool IsExpanded { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,6 +52,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement();
|
public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement();
|
||||||
|
|
||||||
public abstract bool SupportsChildren { get; }
|
public abstract bool SupportsChildren { get; }
|
||||||
|
public abstract bool IsExpanded { get; set; }
|
||||||
|
|
||||||
public List<TreeItemViewModel> GetAllChildren()
|
public List<TreeItemViewModel> GetAllChildren()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.SuspendedProfileEditorView"
|
||||||
|
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.ProfileEditor"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
|
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Top" Margin="16">
|
||||||
|
<materialDesign:PackIcon Kind="PauseCircle" Width="250" Height="250" HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignHeadline4TextBlock}" TextWrapping="Wrap" HorizontalAlignment="Center" Margin="0 25">
|
||||||
|
Profile editing has been paused
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" TextWrapping="Wrap" HorizontalAlignment="Center">
|
||||||
|
Artemis has resumed regular profile playback. As soon as you focus this window, the editor will open to continue editing
|
||||||
|
'<Run Text="{Binding PreviousSelectedProfileConfiguration.Name}" />'.
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" HorizontalAlignment="Center">
|
||||||
|
You can disable this behaviour in the editor's option menu.
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.UI.Events;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.ProfileEditor
|
||||||
|
{
|
||||||
|
public class SuspendedProfileEditorViewModel : MainScreenViewModel, IHandle<MainWindowFocusChangedEvent>
|
||||||
|
{
|
||||||
|
private readonly IEventAggregator _eventAggregator;
|
||||||
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
|
private ProfileConfiguration _previousSelectedProfileConfiguration;
|
||||||
|
|
||||||
|
public SuspendedProfileEditorViewModel(IEventAggregator eventAggregator, IProfileEditorService profileEditorService)
|
||||||
|
{
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
|
_profileEditorService = profileEditorService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileConfiguration PreviousSelectedProfileConfiguration
|
||||||
|
{
|
||||||
|
get => _previousSelectedProfileConfiguration;
|
||||||
|
set => SetAndNotify(ref _previousSelectedProfileConfiguration, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MainWindowFocusChangedEvent message)
|
||||||
|
{
|
||||||
|
if (!message.IsFocused)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RootViewModel rootViewModel = (RootViewModel) Parent;
|
||||||
|
if (PreviousSelectedProfileConfiguration != null)
|
||||||
|
rootViewModel.SidebarViewModel.SelectProfileConfiguration(PreviousSelectedProfileConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of Screen
|
||||||
|
|
||||||
|
protected override void OnInitialActivate()
|
||||||
|
{
|
||||||
|
PreviousSelectedProfileConfiguration = _profileEditorService.PreviousSelectedProfileConfiguration;
|
||||||
|
_eventAggregator.Subscribe(this);
|
||||||
|
base.OnInitialActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
_eventAggregator.Unsubscribe(this);
|
||||||
|
base.OnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -101,6 +101,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid Name="EditorDisplayGrid"
|
<Grid Name="EditorDisplayGrid"
|
||||||
|
Visibility="{Binding SuspendedEditing, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}"
|
||||||
shared:SizeObserver.Observe="True"
|
shared:SizeObserver.Observe="True"
|
||||||
shared:SizeObserver.ObservedHeight="{Binding PanZoomViewModel.CanvasHeight}"
|
shared:SizeObserver.ObservedHeight="{Binding PanZoomViewModel.CanvasHeight}"
|
||||||
shared:SizeObserver.ObservedWidth="{Binding PanZoomViewModel.CanvasWidth}">
|
shared:SizeObserver.ObservedWidth="{Binding PanZoomViewModel.CanvasWidth}">
|
||||||
@ -130,24 +131,6 @@
|
|||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<StackPanel ZIndex="1" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="10" Cursor="Arrow">
|
|
||||||
<materialDesign:Card Padding="8">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<CheckBox Style="{StaticResource MaterialDesignCheckBox}"
|
|
||||||
IsChecked="{Binding FocusSelectedLayer.Value}"
|
|
||||||
ToolTip="If selected, dims all LEDs that are not part of the selected layer">
|
|
||||||
Focus selected layer
|
|
||||||
</CheckBox>
|
|
||||||
<CheckBox Style="{StaticResource MaterialDesignCheckBox}"
|
|
||||||
Margin="10 0 0 0"
|
|
||||||
IsChecked="{Binding AlwaysApplyDataBindings.Value}"
|
|
||||||
ToolTip="If selected, updates all data bindings instead of only the one you are editing">
|
|
||||||
Apply all data bindings in editor
|
|
||||||
</CheckBox>
|
|
||||||
</StackPanel>
|
|
||||||
</materialDesign:Card>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" VerticalAlignment="Bottom" HorizontalAlignment="Right"
|
<StackPanel Orientation="Vertical" VerticalAlignment="Bottom" HorizontalAlignment="Right"
|
||||||
Margin="10" ZIndex="1">
|
Margin="10" ZIndex="1">
|
||||||
<Slider Orientation="Vertical"
|
<Slider Orientation="Vertical"
|
||||||
|
|||||||
@ -26,16 +26,15 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
|
|
||||||
private int _activeToolIndex;
|
private int _activeToolIndex;
|
||||||
private VisualizationToolViewModel _activeToolViewModel;
|
private VisualizationToolViewModel _activeToolViewModel;
|
||||||
private PluginSetting<bool> _alwaysApplyDataBindings;
|
|
||||||
private bool _canApplyToLayer;
|
private bool _canApplyToLayer;
|
||||||
private bool _canSelectEditTool;
|
private bool _canSelectEditTool;
|
||||||
private BindableCollection<ArtemisDevice> _devices;
|
private BindableCollection<ArtemisDevice> _devices;
|
||||||
private BindableCollection<ArtemisLed> _highlightedLeds;
|
private BindableCollection<ArtemisLed> _highlightedLeds;
|
||||||
private PluginSetting<bool> _focusSelectedLayer;
|
|
||||||
private DateTime _lastUpdate;
|
private DateTime _lastUpdate;
|
||||||
private PanZoomViewModel _panZoomViewModel;
|
private PanZoomViewModel _panZoomViewModel;
|
||||||
private Layer _previousSelectedLayer;
|
private Layer _previousSelectedLayer;
|
||||||
private int _previousTool;
|
private int _previousTool;
|
||||||
|
private bool _suspendedEditing;
|
||||||
|
|
||||||
public ProfileViewModel(IProfileEditorService profileEditorService,
|
public ProfileViewModel(IProfileEditorService profileEditorService,
|
||||||
IRgbService rgbService,
|
IRgbService rgbService,
|
||||||
@ -79,18 +78,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
set => SetAndNotify(ref _highlightedLeds, value);
|
set => SetAndNotify(ref _highlightedLeds, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginSetting<bool> AlwaysApplyDataBindings
|
|
||||||
{
|
|
||||||
get => _alwaysApplyDataBindings;
|
|
||||||
set => SetAndNotify(ref _alwaysApplyDataBindings, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PluginSetting<bool> FocusSelectedLayer
|
|
||||||
{
|
|
||||||
get => _focusSelectedLayer;
|
|
||||||
set => SetAndNotify(ref _focusSelectedLayer, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VisualizationToolViewModel ActiveToolViewModel
|
public VisualizationToolViewModel ActiveToolViewModel
|
||||||
{
|
{
|
||||||
get => _activeToolViewModel;
|
get => _activeToolViewModel;
|
||||||
@ -132,9 +119,21 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
set => SetAndNotify(ref _canApplyToLayer, value);
|
set => SetAndNotify(ref _canApplyToLayer, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool SuspendedEditing
|
||||||
|
{
|
||||||
|
get => _suspendedEditing;
|
||||||
|
set => SetAndNotify(ref _suspendedEditing, value);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnInitialActivate()
|
protected override void OnInitialActivate()
|
||||||
{
|
{
|
||||||
PanZoomViewModel = new PanZoomViewModel {LimitToZero = false};
|
PanZoomViewModel = new PanZoomViewModel
|
||||||
|
{
|
||||||
|
LimitToZero = false,
|
||||||
|
PanX = _settingsService.GetSetting("ProfileEditor.PanX", 0d).Value,
|
||||||
|
PanY = _settingsService.GetSetting("ProfileEditor.PanY", 0d).Value,
|
||||||
|
Zoom = _settingsService.GetSetting("ProfileEditor.Zoom", 0d).Value
|
||||||
|
};
|
||||||
|
|
||||||
Devices = new BindableCollection<ArtemisDevice>();
|
Devices = new BindableCollection<ArtemisDevice>();
|
||||||
HighlightedLeds = new BindableCollection<ArtemisLed>();
|
HighlightedLeds = new BindableCollection<ArtemisLed>();
|
||||||
@ -144,13 +143,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
|
|
||||||
ApplyActiveProfile();
|
ApplyActiveProfile();
|
||||||
|
|
||||||
AlwaysApplyDataBindings = _settingsService.GetSetting("ProfileEditor.AlwaysApplyDataBindings", true);
|
|
||||||
FocusSelectedLayer = _settingsService.GetSetting("ProfileEditor.FocusSelectedLayer", true);
|
|
||||||
|
|
||||||
_lastUpdate = DateTime.Now;
|
_lastUpdate = DateTime.Now;
|
||||||
_coreService.FrameRendered += OnFrameRendered;
|
_coreService.FrameRendered += OnFrameRendered;
|
||||||
|
|
||||||
FocusSelectedLayer.SettingChanged += HighlightSelectedLayerOnSettingChanged;
|
|
||||||
_rgbService.DeviceAdded += RgbServiceOnDevicesModified;
|
_rgbService.DeviceAdded += RgbServiceOnDevicesModified;
|
||||||
_rgbService.DeviceRemoved += RgbServiceOnDevicesModified;
|
_rgbService.DeviceRemoved += RgbServiceOnDevicesModified;
|
||||||
_profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged;
|
_profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged;
|
||||||
@ -163,7 +158,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
protected override void OnClose()
|
protected override void OnClose()
|
||||||
{
|
{
|
||||||
_coreService.FrameRendered -= OnFrameRendered;
|
_coreService.FrameRendered -= OnFrameRendered;
|
||||||
FocusSelectedLayer.SettingChanged -= HighlightSelectedLayerOnSettingChanged;
|
|
||||||
_rgbService.DeviceAdded -= RgbServiceOnDevicesModified;
|
_rgbService.DeviceAdded -= RgbServiceOnDevicesModified;
|
||||||
_rgbService.DeviceRemoved -= RgbServiceOnDevicesModified;
|
_rgbService.DeviceRemoved -= RgbServiceOnDevicesModified;
|
||||||
_profileEditorService.SelectedProfileChanged -= OnSelectedProfileChanged;
|
_profileEditorService.SelectedProfileChanged -= OnSelectedProfileChanged;
|
||||||
@ -172,8 +166,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
if (_previousSelectedLayer != null)
|
if (_previousSelectedLayer != null)
|
||||||
_previousSelectedLayer.LayerBrushUpdated -= SelectedLayerOnLayerBrushUpdated;
|
_previousSelectedLayer.LayerBrushUpdated -= SelectedLayerOnLayerBrushUpdated;
|
||||||
|
|
||||||
AlwaysApplyDataBindings.Save();
|
_settingsService.GetSetting("ProfileEditor.PanX", 0d).Value = PanZoomViewModel.PanX;
|
||||||
FocusSelectedLayer.Save();
|
_settingsService.GetSetting("ProfileEditor.PanX", 0d).Save();
|
||||||
|
_settingsService.GetSetting("ProfileEditor.PanY", 0d).Value = PanZoomViewModel.PanY;
|
||||||
|
_settingsService.GetSetting("ProfileEditor.PanY", 0d).Save();
|
||||||
|
_settingsService.GetSetting("ProfileEditor.Zoom", 0d).Value = PanZoomViewModel.Zoom;
|
||||||
|
_settingsService.GetSetting("ProfileEditor.Zoom", 0d).Save();
|
||||||
|
|
||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
@ -210,7 +208,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
private void UpdateLedsDimStatus()
|
private void UpdateLedsDimStatus()
|
||||||
{
|
{
|
||||||
HighlightedLeds.Clear();
|
HighlightedLeds.Clear();
|
||||||
if (FocusSelectedLayer.Value && _profileEditorService.SelectedProfileElement is Layer layer)
|
if (_profileEditorService.SelectedProfileElement is Layer layer)
|
||||||
HighlightedLeds.AddRange(layer.Leds);
|
HighlightedLeds.AddRange(layer.Leds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +306,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
|||||||
TimeSpan delta = DateTime.Now - _lastUpdate;
|
TimeSpan delta = DateTime.Now - _lastUpdate;
|
||||||
_lastUpdate = DateTime.Now;
|
_lastUpdate = DateTime.Now;
|
||||||
|
|
||||||
if (!AlwaysApplyDataBindings.Value || _profileEditorService.SelectedProfile == null)
|
if (!_settingsService.GetSetting("ProfileEditor.AlwaysApplyDataBindings", true).Value || _profileEditorService.SelectedProfile == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (IDataBindingRegistration dataBindingRegistration in _profileEditorService.SelectedProfile.GetAllFolders()
|
foreach (IDataBindingRegistration dataBindingRegistration in _profileEditorService.SelectedProfile.GetAllFolders()
|
||||||
|
|||||||
@ -15,6 +15,7 @@ using MaterialDesignExtensions.Controls;
|
|||||||
using MaterialDesignThemes.Wpf;
|
using MaterialDesignThemes.Wpf;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
using Stylet.Xaml;
|
||||||
using Constants = Artemis.Core.Constants;
|
using Constants = Artemis.Core.Constants;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens
|
namespace Artemis.UI.Screens
|
||||||
@ -90,6 +91,8 @@ namespace Artemis.UI.Screens
|
|||||||
{
|
{
|
||||||
if (!_lostFocus)
|
if (!_lostFocus)
|
||||||
return;
|
return;
|
||||||
|
if (!((MaterialWindow)View).IsActive)
|
||||||
|
return;
|
||||||
|
|
||||||
_lostFocus = false;
|
_lostFocus = false;
|
||||||
_eventAggregator.Publish(new MainWindowFocusChangedEvent(true));
|
_eventAggregator.Publish(new MainWindowFocusChangedEvent(true));
|
||||||
|
|||||||
@ -126,7 +126,12 @@ namespace Artemis.UI.Screens.Sidebar
|
|||||||
|
|
||||||
public void Handle(RequestSelectSidebarItemEvent message)
|
public void Handle(RequestSelectSidebarItemEvent message)
|
||||||
{
|
{
|
||||||
SidebarScreenViewModel requested = SidebarScreens.FirstOrDefault(s => s.DisplayName == message.DisplayName);
|
SidebarScreenViewModel requested = null;
|
||||||
|
if (message.DisplayName != null)
|
||||||
|
requested = SidebarScreens.FirstOrDefault(s => s.DisplayName == message.DisplayName);
|
||||||
|
else
|
||||||
|
requested = message.ViewModel;
|
||||||
|
|
||||||
if (requested != null)
|
if (requested != null)
|
||||||
SelectedSidebarScreen = requested;
|
SelectedSidebarScreen = requested;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user