mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-31 09:43:46 +00:00
Profile elements - Added Windows Explorer-like naming of new elements
This commit is contained in:
parent
b503906b9a
commit
013bc1c316
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -11,6 +12,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ProfileElement : BreakableModel, IDisposable
|
public abstract class ProfileElement : BreakableModel, IDisposable
|
||||||
{
|
{
|
||||||
|
internal readonly List<ProfileElement> ChildrenList;
|
||||||
private Guid _entityId;
|
private Guid _entityId;
|
||||||
private string? _name;
|
private string? _name;
|
||||||
private int _order;
|
private int _order;
|
||||||
@ -18,8 +20,6 @@ namespace Artemis.Core
|
|||||||
private Profile _profile;
|
private Profile _profile;
|
||||||
private bool _suspended;
|
private bool _suspended;
|
||||||
|
|
||||||
internal readonly List<ProfileElement> ChildrenList;
|
|
||||||
|
|
||||||
internal ProfileElement(Profile profile)
|
internal ProfileElement(Profile profile)
|
||||||
{
|
{
|
||||||
_profile = profile;
|
_profile = profile;
|
||||||
@ -120,6 +120,49 @@ namespace Artemis.Core
|
|||||||
return $"{nameof(EntityId)}: {EntityId}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}";
|
return $"{nameof(EntityId)}: {EntityId}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a child was added to the <see cref="Children" /> list
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<ProfileElementEventArgs>? ChildAdded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a child was removed from the <see cref="Children" /> list
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<ProfileElementEventArgs>? ChildRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ChildAdded" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnChildAdded(ProfileElement child)
|
||||||
|
{
|
||||||
|
ChildAdded?.Invoke(this, new ProfileElementEventArgs(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ChildRemoved" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnChildRemoved(ProfileElement child)
|
||||||
|
{
|
||||||
|
ChildRemoved?.Invoke(this, new ProfileElementEventArgs(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes the profile element
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
#region Hierarchy
|
#region Hierarchy
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -248,6 +291,48 @@ namespace Artemis.Core
|
|||||||
return layers;
|
return layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a name for a new layer according to any other layers with a default name similar to creating new folders in
|
||||||
|
/// Explorer
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The resulting name i.e. <c>New layer</c> or <c>New layer (2)</c></returns>
|
||||||
|
public string GetNewLayerName()
|
||||||
|
{
|
||||||
|
if (!Children.Any(c => c is Layer))
|
||||||
|
return "New layer";
|
||||||
|
|
||||||
|
// Grab existing unnamed layers and get the first available number
|
||||||
|
// Looks slow but it's not https://stackoverflow.com/a/8865806/5015269
|
||||||
|
Regex regex = new(@"New layer \((\d+)\)");
|
||||||
|
int firstAvailable = Enumerable.Range(1, int.MaxValue)
|
||||||
|
.Except(Children.Where(c => c is Layer && c.Name != null && regex.IsMatch(c.Name))
|
||||||
|
.Select(c => int.Parse(regex.Match(c.Name!).Groups[1].Value))
|
||||||
|
.OrderBy(i => i))
|
||||||
|
.First();
|
||||||
|
return $"New layer ({firstAvailable})";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a name for a new folder according to any other folders with a default name similar to creating new folders
|
||||||
|
/// in Explorer
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The resulting name i.e. <c>New folder</c> or <c>New folder (2)</c></returns>
|
||||||
|
public string GetNewFolderName()
|
||||||
|
{
|
||||||
|
if (!Children.Any(c => c is Folder))
|
||||||
|
return "New folder";
|
||||||
|
|
||||||
|
// Grab existing unnamed layers and get the first available number
|
||||||
|
// Looks slow but it's not https://stackoverflow.com/a/8865806/5015269
|
||||||
|
Regex regex = new(@"New folder \((\d+)\)");
|
||||||
|
int firstAvailable = Enumerable.Range(1, int.MaxValue)
|
||||||
|
.Except(Children.Where(c => c is Folder && c.Name != null && regex.IsMatch(c.Name))
|
||||||
|
.Select(c => int.Parse(regex.Match(c.Name!).Groups[1].Value))
|
||||||
|
.OrderBy(i => i))
|
||||||
|
.First();
|
||||||
|
return $"New folder ({firstAvailable})";
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Storage
|
#region Storage
|
||||||
@ -256,56 +341,5 @@ namespace Artemis.Core
|
|||||||
internal abstract void Save();
|
internal abstract void Save();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a child was added to the <see cref="Children" /> list
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<ProfileElementEventArgs>? ChildAdded;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a child was removed from the <see cref="Children" /> list
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<ProfileElementEventArgs>? ChildRemoved;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the <see cref="ChildAdded" /> event
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnChildAdded(ProfileElement child)
|
|
||||||
{
|
|
||||||
ChildAdded?.Invoke(this, new ProfileElementEventArgs(child));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the <see cref="ChildRemoved" /> event
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnChildRemoved(ProfileElement child)
|
|
||||||
{
|
|
||||||
ChildRemoved?.Invoke(this, new ProfileElementEventArgs(child));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes the profile element
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,13 +42,13 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
{
|
{
|
||||||
if (ProfileElement is Layer targetLayer)
|
if (ProfileElement is Layer targetLayer)
|
||||||
{
|
{
|
||||||
Layer layer = new(targetLayer.Parent, "New layer");
|
Layer layer = new(targetLayer.Parent, targetLayer.GetNewLayerName());
|
||||||
layer.AddLeds(rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
layer.AddLeds(rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
||||||
profileEditorService.ExecuteCommand(new AddProfileElement(layer, targetLayer.Parent, targetLayer.Order));
|
profileEditorService.ExecuteCommand(new AddProfileElement(layer, targetLayer.Parent, targetLayer.Order));
|
||||||
}
|
}
|
||||||
else if (ProfileElement != null)
|
else if (ProfileElement != null)
|
||||||
{
|
{
|
||||||
Layer layer = new(ProfileElement, "New layer");
|
Layer layer = new(ProfileElement, ProfileElement.GetNewLayerName());
|
||||||
layer.AddLeds(rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
layer.AddLeds(rgbService.EnabledDevices.SelectMany(d => d.Leds));
|
||||||
profileEditorService.ExecuteCommand(new AddProfileElement(layer, ProfileElement, 0));
|
profileEditorService.ExecuteCommand(new AddProfileElement(layer, ProfileElement, 0));
|
||||||
}
|
}
|
||||||
@ -57,9 +57,9 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
AddFolder = ReactiveCommand.Create(() =>
|
AddFolder = ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
if (ProfileElement is Layer targetLayer)
|
if (ProfileElement is Layer targetLayer)
|
||||||
profileEditorService.ExecuteCommand(new AddProfileElement(new Folder(targetLayer.Parent, "New folder"), targetLayer.Parent, targetLayer.Order));
|
profileEditorService.ExecuteCommand(new AddProfileElement(new Folder(targetLayer.Parent, targetLayer.Parent.GetNewFolderName()), targetLayer.Parent, targetLayer.Order));
|
||||||
else if (ProfileElement != null)
|
else if (ProfileElement != null)
|
||||||
profileEditorService.ExecuteCommand(new AddProfileElement(new Folder(ProfileElement, "New folder"), ProfileElement, 0));
|
profileEditorService.ExecuteCommand(new AddProfileElement(new Folder(ProfileElement, ProfileElement.GetNewFolderName()), ProfileElement, 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
Rename = ReactiveCommand.Create(() =>
|
Rename = ReactiveCommand.Create(() =>
|
||||||
|
|||||||
@ -56,6 +56,7 @@ public class VisualEditorViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
private void CreateVisualizers(ProfileConfiguration? profileConfiguration)
|
private void CreateVisualizers(ProfileConfiguration? profileConfiguration)
|
||||||
{
|
{
|
||||||
|
// TODO: Monitor and respond to new layers/folders and deletions
|
||||||
_visualizers.Edit(list =>
|
_visualizers.Edit(list =>
|
||||||
{
|
{
|
||||||
list.Clear();
|
list.Clear();
|
||||||
|
|||||||
@ -7,7 +7,6 @@ using Artemis.UI.Shared.Services.ProfileEditor;
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.Mixins;
|
using Avalonia.Controls.Mixins;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ShimSkiaSharp;
|
|
||||||
using SKRect = SkiaSharp.SKRect;
|
using SKRect = SkiaSharp.SKRect;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.VisualEditor.Visualizers;
|
namespace Artemis.UI.Screens.ProfileEditor.VisualEditor.Visualizers;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user