1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00
SpoinkyNL 24afb6b0f5 UI - Large amount of memory improvements in the VMs
Core - Minor memory improvements
2020-06-19 21:48:26 +02:00

224 lines
8.0 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core.Models.Profile;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.Exceptions;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.Dialogs;
using Artemis.UI.Shared.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{
public abstract class TreeItemViewModel : PropertyChangedBase, IDisposable
{
private readonly IDialogService _dialogService;
private readonly IFolderVmFactory _folderVmFactory;
private readonly ILayerService _layerService;
private readonly ILayerVmFactory _layerVmFactory;
private readonly IProfileEditorService _profileEditorService;
protected TreeItemViewModel(TreeItemViewModel parent,
ProfileElement profileElement,
IProfileEditorService profileEditorService,
IDialogService dialogService,
ILayerService layerService,
IFolderVmFactory folderVmFactory,
ILayerVmFactory layerVmFactory)
{
_profileEditorService = profileEditorService;
_dialogService = dialogService;
_layerService = layerService;
_folderVmFactory = folderVmFactory;
_layerVmFactory = layerVmFactory;
Parent = parent;
ProfileElement = profileElement;
Children = new BindableCollection<TreeItemViewModel>();
UpdateProfileElements();
}
public TreeItemViewModel Parent { get; set; }
public ProfileElement ProfileElement { get; set; }
public abstract bool SupportsChildren { get; }
public BindableCollection<TreeItemViewModel> Children { get; set; }
public List<TreeItemViewModel> GetAllChildren()
{
var children = new List<TreeItemViewModel>();
foreach (var childFolder in Children)
{
// Add all children in this element
children.Add(childFolder);
// Add all children of children inside this element
children.AddRange(childFolder.GetAllChildren());
}
return children;
}
public void SetElementInFront(TreeItemViewModel source)
{
if (source.Parent != Parent)
{
source.Parent.RemoveExistingElement(source);
Parent.AddExistingElement(source);
}
Parent.ProfileElement.RemoveChild(source.ProfileElement);
Parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order);
Parent.UpdateProfileElements();
}
public void SetElementBehind(TreeItemViewModel source)
{
if (source.Parent != Parent)
{
source.Parent.RemoveExistingElement(source);
Parent.AddExistingElement(source);
}
Parent.ProfileElement.RemoveChild(source.ProfileElement);
Parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order + 1);
Parent.UpdateProfileElements();
}
public void RemoveExistingElement(TreeItemViewModel treeItem)
{
if (!SupportsChildren)
throw new ArtemisUIException("Cannot remove a child from a profile element of type " + ProfileElement.GetType().Name);
ProfileElement.RemoveChild(treeItem.ProfileElement);
Children.Remove(treeItem);
treeItem.Parent = null;
}
public void AddExistingElement(TreeItemViewModel treeItem)
{
if (!SupportsChildren)
throw new ArtemisUIException("Cannot add a child to a profile element of type " + ProfileElement.GetType().Name);
ProfileElement.AddChild(treeItem.ProfileElement);
Children.Add(treeItem);
treeItem.Parent = this;
}
public void AddFolder()
{
if (!SupportsChildren)
throw new ArtemisUIException("Cannot add a folder to a profile element of type " + ProfileElement.GetType().Name);
ProfileElement.AddChild(new Folder(ProfileElement.Profile, ProfileElement, "New folder"));
UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile();
}
public void AddLayer()
{
if (!SupportsChildren)
throw new ArtemisUIException("Cannot add a layer to a profile element of type " + ProfileElement.GetType().Name);
_layerService.CreateLayer(ProfileElement.Profile, ProfileElement, "New layer");
UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile();
}
// ReSharper disable once UnusedMember.Global - Called from view
public async Task RenameElement()
{
var result = await _dialogService.ShowDialog<RenameViewModel>(
new Dictionary<string, object>
{
{"subject", ProfileElement is Folder ? "folder" : "layer"},
{"currentName", ProfileElement.Name}
}
);
if (result is string newName)
{
ProfileElement.Name = newName;
_profileEditorService.UpdateSelectedProfile();
}
}
// ReSharper disable once UnusedMember.Global - Called from view
public async Task DeleteElement()
{
var result = await _dialogService.ShowConfirmDialog(
"Delete profile element",
"Are you sure you want to delete this element? This cannot be undone."
);
if (!result)
return;
// Farewell, cruel world
var parent = Parent;
ProfileElement.Parent?.RemoveChild(ProfileElement);
parent.RemoveExistingElement(this);
parent.UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile();
}
public void UpdateProfileElements()
{
// Order the children
var vmsList = Children.OrderBy(v => v.ProfileElement.Order).ToList();
for (var index = 0; index < vmsList.Count; index++)
{
var profileElementViewModel = vmsList[index];
Children.Move(Children.IndexOf(profileElementViewModel), index);
}
// Ensure every child element has an up-to-date VM
if (ProfileElement.Children == null)
return;
var newChildren = new List<TreeItemViewModel>();
foreach (var profileElement in ProfileElement.Children.OrderBy(c => c.Order))
{
if (profileElement is Folder folder)
{
if (Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder) == null)
newChildren.Add(_folderVmFactory.Create((FolderViewModel) this, folder));
}
else if (profileElement is Layer layer)
{
if (Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer) == null)
newChildren.Add(_layerVmFactory.Create((FolderViewModel) this, layer));
}
}
if (!newChildren.Any())
return;
// Add the new children in one call, prevent extra UI events
Children.AddRange(newChildren);
foreach (var treeItemViewModel in newChildren)
treeItemViewModel.UpdateProfileElements();
}
public void EnableToggled()
{
_profileEditorService.UpdateSelectedProfile();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}