mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 19:36:28 +00:00
Profile tree - Implemented proper copy/pasting
This commit is contained in:
1 parent
f694f39219
commit
aae4e71d8e
21 files changed
+524
-294
No files matched your search
@@ -34,10 +34,11 @@
|
||||
dd:DragDrop.IsDropTarget="True"
|
||||
dd:DragDrop.DropHandler="{Binding}">
|
||||
<TreeView.InputBindings>
|
||||
<KeyBinding Key="F2" Command="{s:Action RenameElement}" s:View.ActionTarget="{Binding SelectedTreeItem}"/>
|
||||
<KeyBinding Key="Delete" Command="{s:Action DeleteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}"/>
|
||||
<KeyBinding Key="C" Modifiers="Control" Command="{s:Action CopyElement}" s:View.ActionTarget="{Binding SelectedTreeItem}"/>
|
||||
<KeyBinding Key="V" Modifiers="Control" Command="{s:Action PasteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}"/>
|
||||
<KeyBinding Key="F2" Command="{s:Action RenameElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
||||
<KeyBinding Key="Delete" Command="{s:Action DeleteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
||||
<KeyBinding Key="D" Modifiers="Control" Command="{s:Action DuplicateElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
||||
<KeyBinding Key="C" Modifiers="Control" Command="{s:Action CopyElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
||||
<KeyBinding Key="V" Modifiers="Control" Command="{s:Action PasteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
||||
</TreeView.InputBindings>
|
||||
<b:Interaction.Behaviors>
|
||||
<behaviors:TreeViewSelectionBehavior ExpandSelected="True" SelectedItem="{Binding SelectedTreeItem}" />
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
{
|
||||
public class ProfileTreeViewModel : Conductor<FolderViewModel>, IProfileEditorPanelViewModel, IDropTarget
|
||||
{
|
||||
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||
private TreeItemViewModel _selectedTreeItem;
|
||||
private bool _updatingTree;
|
||||
|
||||
@@ -41,6 +41,73 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -84,80 +151,6 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
Subscribe();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// Auto-select the first layer
|
||||
// if (_profileEditorService.SelectedProfile != null && SelectedTreeItem == null)
|
||||
// {
|
||||
// if (_profileEditorService.SelectedProfile.GetRootFolder().Children.FirstOrDefault() is RenderProfileElement firstElement)
|
||||
// Execute.PostToUIThread(() => _profileEditorService.ChangeSelectedProfileElement(firstElement));
|
||||
// }
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void Subscribe()
|
||||
@@ -187,7 +180,9 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
ActiveItem.UpdateProfileElements();
|
||||
_updatingTree = false;
|
||||
if (e.RenderProfileElement == null)
|
||||
{
|
||||
SelectedTreeItem = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
TreeItemViewModel match = ActiveItem.GetAllChildren().FirstOrDefault(vm => vm.ProfileElement == e.RenderProfileElement);
|
||||
|
||||
@@ -13,17 +13,6 @@
|
||||
<StackPanel Margin="-10" Background="Transparent">
|
||||
<StackPanel.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Rename" Command="{s:Action RenameElement}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="RenameBox" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Delete" Command="{s:Action DeleteElement}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="TrashCan" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Add new folder" Command="{s:Action AddFolder}">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="CreateNewFolder" />
|
||||
@@ -34,6 +23,33 @@
|
||||
<materialDesign:PackIcon Kind="LayersPlus" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Duplicate" Command="{s:Action DuplicateElement}" InputGestureText="Ctrl+D">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ContentDuplicate" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Copy" Command="{s:Action CopyElement}" InputGestureText="Ctrl+C">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ContentCopy" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Paste" Command="{s:Action PasteElement}" InputGestureText="Ctrl+V">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ContentPaste" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Rename" Command="{s:Action RenameElement}" InputGestureText="F2">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="RenameBox" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Delete" Command="{s:Action DeleteElement}" InputGestureText="Del">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="TrashCan" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</StackPanel.ContextMenu>
|
||||
<Grid Margin="10">
|
||||
|
||||
@@ -13,17 +13,28 @@
|
||||
<StackPanel Margin="-10" Background="Transparent">
|
||||
<StackPanel.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Rename" Command="{s:Action RenameElement}">
|
||||
<MenuItem Header="Duplicate" Command="{s:Action DuplicateElement}" InputGestureText="Ctrl+D">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="RenameBox" />
|
||||
<materialDesign:PackIcon Kind="ContentDuplicate" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Duplicate" Command="{s:Action DuplicateElement}">
|
||||
</MenuItem>
|
||||
<MenuItem Header="Copy" Command="{s:Action CopyElement}" InputGestureText="Ctrl+C">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ContentCopy" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Delete" Command="{s:Action DeleteElement}">
|
||||
<MenuItem Header="Paste" Command="{s:Action PasteElement}" InputGestureText="Ctrl+V">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="ContentPaste" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Rename" Command="{s:Action RenameElement}" InputGestureText="F2">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="RenameBox" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Delete" Command="{s:Action DeleteElement}" InputGestureText="Del">
|
||||
<MenuItem.Icon>
|
||||
<materialDesign:PackIcon Kind="TrashCan" />
|
||||
</MenuItem.Icon>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared.Services;
|
||||
@@ -8,8 +7,6 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
public class LayerViewModel : TreeItemViewModel
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
|
||||
public LayerViewModel(ProfileElement layer,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
@@ -18,15 +15,6 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
ISurfaceService surfaceService) :
|
||||
base(layer, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
}
|
||||
|
||||
public void DuplicateElement()
|
||||
{
|
||||
Layer layer = Layer.CreateCopy();
|
||||
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
_profileEditorService.ChangeSelectedProfileElement(layer);
|
||||
}
|
||||
|
||||
public Layer Layer => ProfileElement as Layer;
|
||||
|
||||
@@ -5,12 +5,11 @@ using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.UI.Exceptions;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.ProfileEditor.Dialogs;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Utilities;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
@@ -178,36 +177,44 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
ProfileElement newSelection = null;
|
||||
if (ProfileElement.Parent != null)
|
||||
{
|
||||
int index = ProfileElement.Parent.Children.IndexOf(ProfileElement);
|
||||
// If there is a next element, select that
|
||||
if (index < ProfileElement.Parent.Children.Count - 1)
|
||||
newSelection = ProfileElement.Parent.Children[index + 1];
|
||||
// Otherwise select the previous element
|
||||
else if (index > 0)
|
||||
newSelection = ProfileElement.Parent.Children[index - 1];
|
||||
// And if that's not there, fall back to the parent
|
||||
else
|
||||
newSelection = ProfileElement.Parent;
|
||||
}
|
||||
|
||||
// Farewell, cruel world
|
||||
TreeItemViewModel parent = (TreeItemViewModel) Parent;
|
||||
ProfileElement.Parent?.RemoveChild(ProfileElement);
|
||||
parent.RemoveExistingElement(this);
|
||||
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
_profileEditorService.ChangeSelectedProfileElement(null);
|
||||
_profileEditorService.ChangeSelectedProfileElement(newSelection as RenderProfileElement);
|
||||
}
|
||||
|
||||
public void DuplicateElement()
|
||||
{
|
||||
_profileEditorService.DuplicateProfileElement(ProfileElement);
|
||||
}
|
||||
|
||||
public void CopyElement()
|
||||
{
|
||||
if (ProfileElement is Layer layer)
|
||||
JsonClipboard.SetObject(layer.LayerEntity);
|
||||
else if (ProfileElement is Folder folder)
|
||||
JsonClipboard.SetObject(folder.FolderEntity);
|
||||
_profileEditorService.CopyProfileElement(ProfileElement);
|
||||
}
|
||||
|
||||
public void PasteElement()
|
||||
{
|
||||
object? clipboardObject = JsonClipboard.GetData();
|
||||
if (clipboardObject is LayerEntity layerEntity)
|
||||
{
|
||||
layerEntity.Id = Guid.NewGuid();
|
||||
layerEntity.Name += " - copy";
|
||||
Layer pasted = new Layer(ProfileElement.Profile, ProfileElement.Parent, layerEntity);
|
||||
ProfileElement.Parent.AddChild(pasted, ProfileElement.Order - 1);
|
||||
}
|
||||
else if (clipboardObject is FolderEntity folderEntity)
|
||||
{
|
||||
}
|
||||
if (ProfileElement.Parent is Folder parent)
|
||||
_profileEditorService.PasteProfileElement(parent, ProfileElement.Order);
|
||||
}
|
||||
|
||||
public void UpdateProfileElements()
|
||||
@@ -217,19 +224,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
foreach (TreeItemViewModel treeItemViewModel in toRemove)
|
||||
Items.Remove(treeItemViewModel);
|
||||
|
||||
// Order the children
|
||||
List<TreeItemViewModel> vmsList = Items.OrderBy(v => v.ProfileElement.Order).ToList();
|
||||
for (int index = 0; index < vmsList.Count; index++)
|
||||
{
|
||||
TreeItemViewModel profileElementViewModel = vmsList[index];
|
||||
if (Items.IndexOf(profileElementViewModel) != index)
|
||||
((BindableCollection<TreeItemViewModel>) Items).Move(Items.IndexOf(profileElementViewModel), index);
|
||||
}
|
||||
|
||||
// Ensure every child element has an up-to-date VM
|
||||
if (ProfileElement.Children == null)
|
||||
return;
|
||||
|
||||
// Add missing children
|
||||
List<TreeItemViewModel> newChildren = new List<TreeItemViewModel>();
|
||||
foreach (ProfileElement profileElement in ProfileElement.Children.OrderBy(c => c.Order))
|
||||
if (profileElement is Folder folder)
|
||||
@@ -243,15 +238,15 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
newChildren.Add(_profileTreeVmFactory.LayerViewModel(layer));
|
||||
}
|
||||
|
||||
if (!newChildren.Any())
|
||||
return;
|
||||
|
||||
// Add the new children in one call, prevent extra UI events
|
||||
foreach (TreeItemViewModel treeItemViewModel in newChildren)
|
||||
{
|
||||
treeItemViewModel.UpdateProfileElements();
|
||||
Items.Add(treeItemViewModel);
|
||||
}
|
||||
|
||||
// Order the children
|
||||
((BindableCollection<TreeItemViewModel>) Items).Sort(i => i.ProfileElement.Order);
|
||||
}
|
||||
|
||||
public void EnableToggled()
|
||||
|
||||
@@ -382,6 +382,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
else
|
||||
_previousSelectedLayer = null;
|
||||
|
||||
ApplyActiveProfile();
|
||||
UpdateLedsDimStatus();
|
||||
UpdateCanSelectEditTool();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user