1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00
Robert 8728599dcc 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
2021-07-01 21:12:09 +02:00

254 lines
8.2 KiB
C#

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using GongSolutions.Wpf.DragDrop;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
{
public class ProfileTreeViewModel : Conductor<FolderViewModel>, IProfileEditorPanelViewModel, IDropTarget
{
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
private bool _draggingTreeView;
private TreeItemViewModel _selectedTreeItem;
private bool _updatingTree;
public ProfileTreeViewModel(IProfileEditorService profileEditorService, IProfileTreeVmFactory profileTreeVmFactory)
{
_profileEditorService = profileEditorService;
_profileTreeVmFactory = profileTreeVmFactory;
}
public TreeItemViewModel SelectedTreeItem
{
get => _selectedTreeItem;
set
{
if (!_updatingTree && SetAndNotify(ref _selectedTreeItem, value) && !_draggingTreeView)
ApplySelectedTreeItem();
}
}
public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement();
public void TreeViewPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
_draggingTreeView = true;
}
public void TreeViewPreviewMouseUp(object sender, MouseButtonEventArgs e)
{
_draggingTreeView = false;
ApplySelectedTreeItem();
}
protected override void OnInitialActivate()
{
Subscribe();
CreateRootFolderViewModel();
base.OnInitialActivate();
}
protected override void OnClose()
{
Unsubscribe();
base.OnClose();
}
private void ApplySelectedTreeItem()
{
if (_selectedTreeItem != null && _selectedTreeItem.ProfileElement is RenderProfileElement renderElement)
_profileEditorService.ChangeSelectedProfileElement(renderElement);
else
_profileEditorService.ChangeSelectedProfileElement(null);
}
private void CreateRootFolderViewModel()
{
_updatingTree = true;
ProfileElement firstChild = _profileEditorService.SelectedProfile?.Children?.FirstOrDefault();
if (firstChild is not Folder folder)
{
ActivateItem(null);
return;
}
ActiveItem = _profileTreeVmFactory.FolderViewModel(folder);
_updatingTree = false;
Execute.PostToUIThread(async () =>
{
await Task.Delay(1500);
SelectedTreeItem = ActiveItem.GetAllChildren().FirstOrDefault(c => c.ProfileElement == _profileEditorService.SelectedProfileElement);
});
}
#region IDropTarget
private static DragDropType GetDragDropType(IDropInfo dropInfo)
{
if (!(dropInfo.Data is TreeItemViewModel source) || !(dropInfo.TargetItem is TreeItemViewModel target))
return DragDropType.None;
if (source == target)
return DragDropType.None;
TreeItemViewModel parent = target;
while (parent != null)
{
if (parent == source)
return DragDropType.None;
parent = parent.Parent as TreeItemViewModel;
}
switch (dropInfo.InsertPosition)
{
case RelativeInsertPosition.AfterTargetItem | RelativeInsertPosition.TargetItemCenter:
case RelativeInsertPosition.BeforeTargetItem | RelativeInsertPosition.TargetItemCenter:
return target.SupportsChildren ? DragDropType.Add : DragDropType.None;
case RelativeInsertPosition.BeforeTargetItem:
return DragDropType.InsertBefore;
case RelativeInsertPosition.AfterTargetItem:
return DragDropType.InsertAfter;
default:
return DragDropType.None;
}
}
public void DragOver(IDropInfo dropInfo)
{
DragDropType dragDropType = GetDragDropType(dropInfo);
switch (dragDropType)
{
case DragDropType.Add:
dropInfo.DropTargetAdorner = DropTargetAdorners.Highlight;
dropInfo.Effects = DragDropEffects.Move;
break;
case DragDropType.InsertBefore:
case DragDropType.InsertAfter:
dropInfo.DropTargetAdorner = DropTargetAdorners.Insert;
dropInfo.Effects = DragDropEffects.Move;
break;
}
}
public void Drop(IDropInfo dropInfo)
{
if (!(dropInfo.Data is TreeItemViewModel source) || !(dropInfo.TargetItem is TreeItemViewModel target))
return;
if (source == target)
return;
DragDropType dragDropType = GetDragDropType(dropInfo);
switch (dragDropType)
{
case DragDropType.Add:
((TreeItemViewModel) source.Parent).RemoveExistingElement(source);
target.AddExistingElement(source);
break;
case DragDropType.InsertBefore:
target.SetElementInFront(source);
break;
case DragDropType.InsertAfter:
target.SetElementBehind(source);
break;
}
Unsubscribe();
_profileEditorService.SaveSelectedProfileConfiguration();
Subscribe();
}
#endregion
#region Context menu
public void AddFolder()
{
ActiveItem?.AddFolder();
}
public void AddLayer()
{
ActiveItem?.AddLayer();
}
public void PasteElement()
{
Folder rootFolder = _profileEditorService.SelectedProfile?.GetRootFolder();
if (rootFolder != null)
_profileEditorService.PasteProfileElement(rootFolder, rootFolder.Children.Count);
}
public void ContextMenuOpening(object sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(CanPasteElement));
}
#endregion
#region Event handlers
private void Subscribe()
{
_profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged;
_profileEditorService.SelectedProfileElementChanged += OnSelectedProfileElementChanged;
}
private void Unsubscribe()
{
_profileEditorService.SelectedProfileChanged -= OnSelectedProfileChanged;
_profileEditorService.SelectedProfileElementChanged -= OnSelectedProfileElementChanged;
}
private void OnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
{
if (e.RenderProfileElement == SelectedTreeItem?.ProfileElement)
return;
if (ActiveItem == null)
{
CreateRootFolderViewModel();
return;
}
_updatingTree = true;
ActiveItem.UpdateProfileElements();
_updatingTree = false;
if (e.RenderProfileElement == null)
{
SelectedTreeItem = null;
}
else
{
TreeItemViewModel match = ActiveItem.GetAllChildren().FirstOrDefault(vm => vm.ProfileElement == e.RenderProfileElement);
if (match != null)
SelectedTreeItem = match;
}
}
private void OnSelectedProfileChanged(object sender, EventArgs e)
{
CreateRootFolderViewModel();
}
#endregion
}
public enum DragDropType
{
None,
Add,
InsertBefore,
InsertAfter
}
}