Profile editor - Moved files

This commit is contained in:
SpoinkyNL committed 2020-08-15 17:53:12 +02:00
1 parent 0516ccc658
commit 698d1b8bbd
86 files changed
+199 -215

No files matched your search

@@ -0,0 +1,65 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem.FolderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:treeItem="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem"
xmlns:treeItem1="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type treeItem1:FolderViewModel}}">
<!-- Capture clicks on full tree view item -->
<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" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Add new layer" Command="{s:Action AddLayer}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="LayersPlus" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<materialDesign:PackIcon Grid.Column="0"
Kind="Folder"
Visibility="{Binding IsExpanded, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" />
<materialDesign:PackIcon Grid.Column="0"
Kind="FolderOpen"
Visibility="{Binding IsExpanded, Converter={x:Static s:BoolToVisibilityConverter.Instance}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}}" />
<TextBlock Grid.Column="1" Text="{Binding ProfileElement.Name}" Margin="10 0 0 0" VerticalAlignment="Center" />
<ToggleButton Grid.Column="2"
Style="{StaticResource MaterialDesignFlatToggleButton}"
ToolTip="Toggle enabled state"
Width="18"
Height="18"
IsChecked="{Binding ProfileElement.Enabled}"
Command="{s:Action EnableToggled}"
VerticalAlignment="Center" Padding="-25">
<materialDesign:PackIcon Kind="Eye" Height="13" Width="13" />
</ToggleButton>
</Grid>
</StackPanel>
</UserControl>
@@ -0,0 +1,46 @@
using Artemis.Core.Models.Profile;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
{
public class FolderViewModel : TreeItemViewModel
{
protected override void Dispose(bool disposing)
{
if (disposing)
{
foreach (var treeItemViewModel in Children)
treeItemViewModel.Dispose();
Children.Clear();
}
base.Dispose(disposing);
}
// I hate this about DI, oh well
public FolderViewModel(ProfileElement folder,
IProfileEditorService profileEditorService,
IDialogService dialogService,
IRenderElementService renderElementService,
IFolderVmFactory folderVmFactory,
ILayerVmFactory layerVmFactory) :
base(null, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
{
}
public FolderViewModel(TreeItemViewModel parent,
ProfileElement folder,
IProfileEditorService profileEditorService,
IDialogService dialogService,
IRenderElementService renderElementService,
IFolderVmFactory folderVmFactory,
ILayerVmFactory layerVmFactory) :
base(parent, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
{
}
public override bool SupportsChildren => true;
}
}
@@ -0,0 +1,58 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem.LayerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:treeItem="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem"
xmlns:treeItem1="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type treeItem1:LayerViewModel}}">
<!-- Capture clicks on full tree view item -->
<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>
</ContextMenu>
</StackPanel.ContextMenu>
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<materialDesign:PackIcon Grid.Column="0" Kind="Layers" Width="16" VerticalAlignment="Center"/>
<materialDesign:PackIcon Grid.Column="1"
VerticalAlignment="Center"
Kind="{Binding Layer.LayerBrush.Descriptor.Icon}"
Width="16"
Margin="5 0 0 0"
ToolTip="{Binding Layer.LayerBrush.Descriptor.DisplayName, Mode=OneWay}"
Visibility="{Binding ShowIcons, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"
Background="Transparent" />
<TextBlock Grid.Column="2" Text="{Binding Layer.Name}" VerticalAlignment="Center" Margin="5 0 0 0" />
<ToggleButton Grid.Column="3"
Style="{StaticResource MaterialDesignFlatToggleButton}"
ToolTip="Toggle enabled state"
Width="18"
Height="18"
IsChecked="{Binding ProfileElement.Enabled}"
Command="{s:Action EnableToggled}"
VerticalAlignment="Center" Padding="-25">
<materialDesign:PackIcon Kind="Eye" Height="13" Width="13" />
</ToggleButton>
</Grid>
</StackPanel>
</UserControl>
@@ -0,0 +1,25 @@
using Artemis.Core.Models.Profile;
using Artemis.Core.Services.Interfaces;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services.Interfaces;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
{
public class LayerViewModel : TreeItemViewModel
{
public LayerViewModel(TreeItemViewModel parent,
ProfileElement folder,
IProfileEditorService profileEditorService,
IDialogService dialogService,
IRenderElementService renderElementService,
IFolderVmFactory folderVmFactory,
ILayerVmFactory layerVmFactory) :
base(parent, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
{
}
public Layer Layer => ProfileElement as Layer;
public bool ShowIcons => Layer?.LayerBrush != null;
public override bool SupportsChildren => false;
}
}
@@ -0,0 +1,248 @@
using System;
using System.Collections.Generic;
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.ProfileEditor.Dialogs;
using Artemis.UI.Shared.Services.Interfaces;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
{
public abstract class TreeItemViewModel : PropertyChangedBase, IDisposable
{
private readonly IDialogService _dialogService;
private readonly IFolderVmFactory _folderVmFactory;
private readonly ILayerVmFactory _layerVmFactory;
private readonly IProfileEditorService _profileEditorService;
private readonly IRenderElementService _renderElementService;
private TreeItemViewModel _parent;
private ProfileElement _profileElement;
protected TreeItemViewModel(TreeItemViewModel parent,
ProfileElement profileElement,
IProfileEditorService profileEditorService,
IDialogService dialogService,
IRenderElementService renderElementService,
IFolderVmFactory folderVmFactory,
ILayerVmFactory layerVmFactory)
{
_profileEditorService = profileEditorService;
_dialogService = dialogService;
_renderElementService = renderElementService;
_folderVmFactory = folderVmFactory;
_layerVmFactory = layerVmFactory;
Parent = parent;
ProfileElement = profileElement;
Children = new BindableCollection<TreeItemViewModel>();
ProfileElement.ChildAdded += ProfileElementOnChildAdded;
ProfileElement.ChildRemoved += ProfileElementOnChildRemoved;
UpdateProfileElements();
}
public TreeItemViewModel Parent
{
get => _parent;
set => SetAndNotify(ref _parent, value);
}
public ProfileElement ProfileElement
{
get => _profileElement;
set => SetAndNotify(ref _profileElement, value);
}
public BindableCollection<TreeItemViewModel> Children { get; }
public abstract bool SupportsChildren { get; }
public void Dispose()
{
ProfileElement.ChildAdded -= ProfileElementOnChildAdded;
ProfileElement.ChildRemoved -= ProfileElementOnChildRemoved;
Dispose(true);
GC.SuppressFinalize(this);
}
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);
}
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);
}
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;
treeItem.Dispose();
}
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"));
_profileEditorService.UpdateSelectedProfile();
}
public void AddLayer()
{
if (!SupportsChildren)
throw new ArtemisUIException("Cannot add a layer to a profile element of type " + ProfileElement.GetType().Name);
_renderElementService.CreateLayer(ProfileElement.Profile, ProfileElement, "New layer");
_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);
_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)
{
}
}
private void ProfileElementOnChildRemoved(object sender, EventArgs e)
{
UpdateProfileElements();
}
private void ProfileElementOnChildAdded(object sender, EventArgs e)
{
UpdateProfileElements();
}
}
}