using System; using System.Linq; using System.Windows; 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, IProfileEditorPanelViewModel, IDropTarget { private readonly IProfileEditorService _profileEditorService; private readonly IProfileTreeVmFactory _profileTreeVmFactory; private TreeItemViewModel _selectedTreeItem; private bool _updatingTree; public ProfileTreeViewModel(IProfileEditorService profileEditorService, IProfileTreeVmFactory profileTreeVmFactory) { _profileEditorService = profileEditorService; _profileTreeVmFactory = profileTreeVmFactory; CreateRootFolderViewModel(); } public TreeItemViewModel SelectedTreeItem { get => _selectedTreeItem; set { if (_updatingTree) return; if (!SetAndNotify(ref _selectedTreeItem, value)) return; if (value != null && value.ProfileElement is RenderProfileElement renderElement) _profileEditorService.ChangeSelectedProfileElement(renderElement); else _profileEditorService.ChangeSelectedProfileElement(null); } } // ReSharper disable once UnusedMember.Global - Called from view public void AddFolder() { ActiveItem?.AddFolder(); } // ReSharper disable once UnusedMember.Global - Called from view public void AddLayer() { ActiveItem?.AddLayer(); } protected override void OnInitialActivate() { Subscribe(); base.OnInitialActivate(); } protected override void OnClose() { Unsubscribe(); base.OnClose(); } private void CreateRootFolderViewModel() { _updatingTree = true; ProfileElement firstChild = _profileEditorService.SelectedProfile?.Children?.FirstOrDefault(); if (!(firstChild is Folder folder)) { ActivateItem(null); return; } ActivateItem(_profileTreeVmFactory.FolderViewModel(folder)); _updatingTree = false; } private static DragDropType GetDragDropType(IDropInfo dropInfo) { TreeItemViewModel source = (TreeItemViewModel) dropInfo.Data; TreeItemViewModel target = (TreeItemViewModel) dropInfo.TargetItem; 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) { TreeItemViewModel source = (TreeItemViewModel) dropInfo.Data; TreeItemViewModel target = (TreeItemViewModel) dropInfo.TargetItem; 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.UpdateSelectedProfile(); Subscribe(); } #region Event handlers private void Subscribe() { _profileEditorService.ProfileSelected += OnProfileSelected; _profileEditorService.ProfileElementSelected += OnProfileElementSelected; } private void Unsubscribe() { _profileEditorService.ProfileSelected -= OnProfileSelected; _profileEditorService.ProfileElementSelected -= OnProfileElementSelected; } private void OnProfileElementSelected(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 OnProfileSelected(object sender, EventArgs e) { CreateRootFolderViewModel(); } #endregion } public enum DragDropType { None, Add, InsertBefore, InsertAfter } }