diff --git a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs b/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs index ac41df902..c7eadbe8d 100644 --- a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Drawing; using System.Linq; @@ -6,15 +8,26 @@ namespace Artemis.Core.Models.Profile.Abstract { public abstract class ProfileElement { + protected List _children; + + protected ProfileElement() + { + _children = new List(); + } + + public Guid EntityId { get; internal set; } + public Profile Profile { get; internal set; } + public ProfileElement Parent { get; internal set; } + /// /// The element's children /// - public List Children { get; set; } + public ReadOnlyCollection Children => _children.AsReadOnly(); /// /// The order in which this element appears in the update loop and editor /// - public int Order { get; set; } + public int Order { get; internal set; } /// /// The name which appears in the editor @@ -60,5 +73,58 @@ namespace Artemis.Core.Models.Profile.Abstract return folders; } + + /// + /// Adds a profile element to the collection, optionally at the given position (1-based) + /// + /// The profile element to add + /// The order where to place the child (1-based), defaults to the end of the collection + public void AddChild(ProfileElement child, int? order = null) + { + lock (_children) + { + // Add to the end of the list + if (order == null) + { + _children.Add(child); + child.Order = _children.Count; + return; + } + + // Shift everything after the given order + foreach (var profileElement in _children.Where(c => c.Order >= order).ToList()) + profileElement.Order++; + + int targetIndex; + if (order == 0) + targetIndex = 0; + else if (order > _children.Count) + targetIndex = _children.Count; + else + targetIndex = _children.FindIndex(c => c.Order == order + 1); + + _children.Insert(targetIndex, child); + child.Order = order.Value; + child.Parent = this; + } + } + + /// + /// Removes a profile element from the collection + /// + /// The profile element to remove + public void RemoveChild(ProfileElement child) + { + lock (_children) + { + _children.Remove(child); + + // Shift everything after the given order + foreach (var profileElement in _children.Where(c => c.Order > child.Order).ToList()) + profileElement.Order--; + + child.Parent = null; + } + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index d1de94683..068b61faa 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -10,40 +10,41 @@ namespace Artemis.Core.Models.Profile { public sealed class Folder : ProfileElement { - public Folder(Profile profile, Folder folder, string name) + public Folder(Profile profile, ProfileElement parent, string name) { FolderEntity = new FolderEntity(); EntityId = Guid.NewGuid(); Profile = profile; - ParentFolder = folder; + Parent = parent; Name = name; - Children = new List(); } - public Folder(Profile profile, Folder folder, FolderEntity folderEntity, IPluginService pluginService) + public Folder(Profile profile, ProfileElement parent, FolderEntity folderEntity, IPluginService pluginService) { FolderEntity = folderEntity; EntityId = folderEntity.Id; Profile = profile; - ParentFolder = folder; - Children = new List(); + Parent = parent; // Load child folders foreach (var childFolder in Profile.ProfileEntity.Folders.Where(f => f.ParentId == EntityId)) - folder.Children.Add(new Folder(profile, this, childFolder, pluginService)); + _children.Add(new Folder(profile, this, childFolder, pluginService)); // Load child layers foreach (var childLayer in Profile.ProfileEntity.Layers.Where(f => f.ParentId == EntityId)) - folder.Children.Add(new Layer(profile, this, childLayer, pluginService)); + _children.Add(new Layer(profile, this, childLayer, pluginService)); + + // Ensure order integrity, should be unnecessary but no one is perfect specially me + _children = _children.OrderBy(c => c.Order).ToList(); + for (var index = 0; index < _children.Count; index++) + { + var profileElement = _children[index]; + profileElement.Order = index + 1; + } } internal FolderEntity FolderEntity { get; set; } - internal Guid EntityId { get; set; } - - public Profile Profile { get; } - public Folder ParentFolder { get; } - public override void Update(double deltaTime) { @@ -59,10 +60,24 @@ namespace Artemis.Core.Models.Profile profileElement.Render(deltaTime, surface, graphics); } + public Folder AddFolder(string name) + { + var folder = new Folder(Profile, this, name) {Order = Children.LastOrDefault()?.Order ?? 1}; + AddChild(folder); + return folder; + } + + public Layer AddLayer(string name) + { + var layer = new Layer(Profile, this, name) {Order = Children.LastOrDefault()?.Order ?? 1}; + AddChild(layer); + return layer; + } + internal override void ApplyToEntity() { FolderEntity.Id = EntityId; - FolderEntity.ParentId = ParentFolder?.EntityId ?? new Guid(); + FolderEntity.ParentId = Parent?.EntityId ?? new Guid(); FolderEntity.Order = Order; FolderEntity.Name = Name; @@ -74,7 +89,7 @@ namespace Artemis.Core.Models.Profile public override string ToString() { - return $"{nameof(Profile)}: {Profile}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}"; + return $"Folder - {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 74a07932a..08659f12b 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; +using System.Reflection.Metadata.Ecma335; using Artemis.Core.Extensions; using Artemis.Core.Models.Profile.Abstract; using Artemis.Core.Models.Surface; @@ -16,33 +17,29 @@ namespace Artemis.Core.Models.Profile { public sealed class Layer : ProfileElement { - internal Layer(Profile profile, Folder folder, string name) + internal Layer(Profile profile, ProfileElement parent, string name) { LayerEntity = new LayerEntity(); EntityId = Guid.NewGuid(); Profile = profile; - ParentFolder = folder; + Parent = parent; Name = name; Leds = new List(); } - internal Layer(Profile profile, Folder folder, LayerEntity layerEntity, IPluginService pluginService) + internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity, IPluginService pluginService) { LayerEntity = layerEntity; EntityId = layerEntity.Id; Profile = profile; - ParentFolder = folder; + Parent = parent; LayerType = pluginService.GetLayerTypeByGuid(layerEntity.LayerTypeGuid); Leds = new List(); } internal LayerEntity LayerEntity { get; set; } - internal Guid EntityId { get; set; } - - public Profile Profile { get; } - public Folder ParentFolder { get; } public List Leds { get; private set; } public LayerType LayerType { get; private set; } @@ -76,7 +73,7 @@ namespace Artemis.Core.Models.Profile internal override void ApplyToEntity() { LayerEntity.Id = EntityId; - LayerEntity.ParentId = ParentFolder?.EntityId ?? new Guid(); + LayerEntity.ParentId = Parent?.EntityId ?? new Guid(); LayerEntity.LayerTypeGuid = LayerType?.PluginInfo.Guid ?? new Guid(); LayerEntity.Order = Order; @@ -135,7 +132,7 @@ namespace Artemis.Core.Models.Profile public override string ToString() { - return $"{nameof(Profile)}: {Profile}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}"; + return $"Layer - {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index 8be810229..d5b6b4451 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Drawing; using System.Linq; using Artemis.Core.Exceptions; @@ -20,8 +19,7 @@ namespace Artemis.Core.Models.Profile PluginInfo = pluginInfo; Name = name; - Children = new List {new Folder(this, null, "Root folder")}; - + AddChild(new Folder(this, null, "Root folder")); ApplyToEntity(); } @@ -36,16 +34,15 @@ namespace Artemis.Core.Models.Profile // Populate the profile starting at the root, the rest is populated recursively var rootFolder = profileEntity.Folders.FirstOrDefault(f => f.ParentId == new Guid()); if (rootFolder == null) - Children = new List {new Folder(this, null, "Root folder")}; + AddChild(new Folder(this, null, "Root folder")); else - Children = new List {new Folder(this, null, rootFolder, pluginService)}; + AddChild(new Folder(this, null, rootFolder, pluginService)); } public PluginInfo PluginInfo { get; } public bool IsActivated { get; private set; } internal ProfileEntity ProfileEntity { get; set; } - public Guid EntityId { get; set; } public override void Update(double deltaTime) { @@ -116,6 +113,12 @@ namespace Artemis.Core.Models.Profile return $"{nameof(Order)}: {Order}, {nameof(Name)}: {Name}, {nameof(PluginInfo)}: {PluginInfo}"; } + public void ApplySurface(Surface.Surface surface) + { + foreach (var layer in GetAllLayers()) + layer.ApplySurface(surface); + } + #region Events /// @@ -139,11 +142,5 @@ namespace Artemis.Core.Models.Profile } #endregion - - public void ApplySurface(Surface.Surface surface) - { - foreach (var layer in GetAllLayers()) - layer.ApplySurface(surface); - } } } \ No newline at end of file diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 3cfd90f1c..3e967b541 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -75,6 +75,9 @@ ..\packages\FluentValidation.8.5.0\lib\net45\FluentValidation.dll + + ..\packages\gong-wpf-dragdrop.2.1.0\lib\net47\GongSolutions.WPF.DragDrop.dll + ..\packages\Humanizer.Core.2.6.2\lib\netstandard2.0\Humanizer.dll @@ -170,8 +173,14 @@ - + + FolderView.xaml + + + + + @@ -235,7 +244,15 @@ Designer MSBuild:Compile - + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + Designer MSBuild:Compile @@ -374,6 +391,7 @@ + diff --git a/src/Artemis.UI/Screens/Module/ModuleRootView.xaml b/src/Artemis.UI/Screens/Module/ModuleRootView.xaml index 842c06649..399b44d17 100644 --- a/src/Artemis.UI/Screens/Module/ModuleRootView.xaml +++ b/src/Artemis.UI/Screens/Module/ModuleRootView.xaml @@ -20,7 +20,7 @@ - + diff --git a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs index 7a6a25776..07af5e8d9 100644 --- a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs @@ -36,7 +36,7 @@ namespace Artemis.UI.Screens.Module var moduleViewModels = Module.GetViewModels(); Items.AddRange(moduleViewModels); - + ActiveItem = Items.FirstOrDefault(); } } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileCreateView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileCreateView.xaml index 4feb16132..b457ac9d9 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileCreateView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileCreateView.xaml @@ -12,9 +12,9 @@ Add a new profile - diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionView.xaml index 0f7850149..02e4970f9 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionView.xaml @@ -1,12 +1,10 @@  - - - - + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionViewModel.cs index b7e1e7e9d..a67253375 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionViewModel.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions +namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions { public class DisplayConditionViewModel { } -} +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml index b72bf2077..c625e1b6c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml @@ -1,12 +1,10 @@  - - - - + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs index 9f8ca9b7f..b3a35f876 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions +namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions { public class DisplayConditionsViewModel : ProfileEditorPanelViewModel { } -} +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesView.xaml index cc288498f..bfefd1796 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesView.xaml @@ -1,12 +1,10 @@  - - - - + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesViewModel.cs index 463f037b8..e1a4c7bd3 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertiesViewModel.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Artemis.UI.Screens.Module.ProfileEditor.ElementProperties +namespace Artemis.UI.Screens.Module.ProfileEditor.ElementProperties { public class ElementPropertiesViewModel : ProfileEditorPanelViewModel { } -} +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertyView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertyView.xaml index 717b0d49b..632b6fc05 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertyView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertyView.xaml @@ -1,12 +1,10 @@  - - - - + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertyViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertyViewModel.cs index 47b1f5273..3afceb131 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertyViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ElementProperties/ElementPropertyViewModel.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Artemis.UI.Screens.Module.ProfileEditor.ElementProperties +namespace Artemis.UI.Screens.Module.ProfileEditor.ElementProperties { public class ElementPropertyViewModel { } -} +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementView.xaml index 74cb1b04b..c2f1efe5f 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementView.xaml @@ -1,12 +1,10 @@  - - - - + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementViewModel.cs index fe46522df..26d65f42c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementViewModel.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerElements +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerElements { public class LayerElementViewModel { } -} +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsView.xaml index f0d304dc4..33b04f8c3 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsView.xaml @@ -1,12 +1,10 @@  - - - - + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsViewModel.cs index 9200ff227..52e9a1f79 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerElements/LayerElementsViewModel.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Artemis.UI.Screens.Module.ProfileEditor.LayerElements +namespace Artemis.UI.Screens.Module.ProfileEditor.LayerElements { public class LayerElementsViewModel : ProfileEditorPanelViewModel { } -} +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Layers/LayersView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Layers/LayersView.xaml deleted file mode 100644 index af0e8100a..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Layers/LayersView.xaml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Layers/LayersViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Layers/LayersViewModel.cs deleted file mode 100644 index 58c4de160..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Layers/LayersViewModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Artemis.UI.Screens.Module.ProfileEditor.Layers -{ - public class LayersViewModel : ProfileEditorPanelViewModel - { - } -} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorPanelViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorPanelViewModel.cs index 4d58d279f..a0214b88a 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorPanelViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorPanelViewModel.cs @@ -1,8 +1,14 @@ -using Stylet; +using Artemis.Core.Models.Profile; +using Stylet; namespace Artemis.UI.Screens.Module.ProfileEditor { public class ProfileEditorPanelViewModel : Screen { + public Profile Profile { get; set; } + + public virtual void OnProfileChanged() + { + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorView.xaml index 11d47b754..3014abef4 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorView.xaml @@ -45,11 +45,11 @@ - @@ -57,19 +57,19 @@ - - + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/ProfileElementsViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/ProfileElementsViewModel.cs new file mode 100644 index 000000000..fc7307cf8 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/ProfileElementsViewModel.cs @@ -0,0 +1,124 @@ +using System.Linq; +using System.Windows; +using Artemis.Core.Models.Profile; +using Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.Abstract; +using GongSolutions.Wpf.DragDrop; + +namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements +{ + public class ProfileElementsViewModel : ProfileEditorPanelViewModel, IDropTarget + { + public ProfileElementsViewModel() + { + CreateRootFolderViewModel(); + } + + public FolderViewModel RootFolder { get; set; } + + public void DragOver(IDropInfo dropInfo) + { + var dragDropType = GetDragDropType(dropInfo); + + switch (dragDropType) + { + case DragDropType.FolderAdd: + dropInfo.DropTargetAdorner = DropTargetAdorners.Highlight; + dropInfo.Effects = DragDropEffects.Move; + break; + case DragDropType.FolderInsertBefore: + case DragDropType.FolderInsertAfter: + case DragDropType.LayerInsertBefore: + case DragDropType.LayerInsertAfter: + dropInfo.DropTargetAdorner = DropTargetAdorners.Insert; + dropInfo.Effects = DragDropEffects.Move; + break; + } + } + + public void Drop(IDropInfo dropInfo) + { + var source = (ProfileElementViewModel) dropInfo.Data; + var target = (ProfileElementViewModel) dropInfo.TargetItem; + + var dragDropType = GetDragDropType(dropInfo); + switch (dragDropType) + { + case DragDropType.FolderAdd: + source.Parent.RemoveExistingElement(source); + ((FolderViewModel) target).AddExistingElement(source); + break; + case DragDropType.FolderInsertBefore: + case DragDropType.LayerInsertBefore: + target.SetElementInFront(source); + break; + case DragDropType.FolderInsertAfter: + case DragDropType.LayerInsertAfter: + target.SetElementBehind(source); + break; + } + } + + public void AddFolder() + { + RootFolder?.AddFolder(); + } + + public void AddLayer() + { + RootFolder?.AddLayer(); + } + + public override void OnProfileChanged() + { + CreateRootFolderViewModel(); + base.OnProfileChanged(); + } + + private void CreateRootFolderViewModel() + { + if (!(Profile?.Children?.FirstOrDefault() is Folder folder)) + { + RootFolder = null; + return; + } + + RootFolder = new FolderViewModel(folder, null); + } + + private DragDropType GetDragDropType(IDropInfo dropInfo) + { + var source = dropInfo.Data as ProfileElementViewModel; + var target = dropInfo.TargetItem as ProfileElementViewModel; + if (source == target) + return DragDropType.None; + + if (target is FolderViewModel) + { + if (dropInfo.InsertPosition >= RelativeInsertPosition.TargetItemCenter) + return DragDropType.FolderAdd; + if (dropInfo.InsertPosition == RelativeInsertPosition.BeforeTargetItem) + return DragDropType.FolderInsertBefore; + return DragDropType.FolderInsertAfter; + } + + if (target is LayerViewModel) + { + if (dropInfo.InsertPosition == RelativeInsertPosition.BeforeTargetItem) + return DragDropType.LayerInsertBefore; + return DragDropType.LayerInsertAfter; + } + + return DragDropType.None; + } + } + + public enum DragDropType + { + None, + FolderAdd, + FolderInsertBefore, + FolderInsertAfter, + LayerInsertBefore, + LayerInsertAfter + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLedViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLedViewModel.cs index 08a3beb9d..3d1ba1784 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLedViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileLedViewModel.cs @@ -65,7 +65,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization private void CreateRectangleGeometry() { - DisplayGeometry = new RectangleGeometry(new Rect(0.5, 0.5, Width - 1, Height - 1)); } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml index 99344e47d..666120615 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileView.xaml @@ -1,12 +1,12 @@  @@ -36,12 +36,12 @@ + KeyUp="{s:Action EditorGridKeyUp}" + KeyDown="{s:Action EditorGridKeyDown}" + MouseWheel="{s:Action EditorGridMouseWheel}" + MouseUp="{s:Action EditorGridMouseClick}" + MouseDown="{s:Action EditorGridMouseClick}" + MouseMove="{s:Action EditorGridMouseMove}"> @@ -109,29 +109,29 @@ + Stroke="{DynamicResource PrimaryHueLightBrush}" + StrokeThickness="1" + Name="MultiSelectionPath" + IsHitTestVisible="False"> + Margin="0, 0, 15, 15"> + Orientation="Vertical" + Minimum="10" + Maximum="400" + Height="100" + FocusVisualStyle="{x:Null}" + Value="{Binding PanZoomViewModel.ZoomPercentage}" + Style="{StaticResource MaterialDesignDiscreteSlider}" /> @@ -140,10 +140,10 @@ - Initializing LED visualization... + Initializing LED visualization... - + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs index 9f3a3b3d9..3b80fea85 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs @@ -7,7 +7,6 @@ using System.Windows.Media; using Artemis.Core.Events; using Artemis.Core.Models.Surface; using Artemis.Core.Services; -using Artemis.Core.Services.Storage; using Artemis.Core.Services.Storage.Interfaces; using Artemis.UI.Screens.Shared; using Artemis.UI.Screens.SurfaceEditor; @@ -94,8 +93,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization lock (Devices) { if (IsInitializing) - IsInitializing = Devices.Any(d => !d.AddedLeds); - + IsInitializing = Devices.Any(d => !d.AddedLeds); + foreach (var profileDeviceViewModel in Devices) profileDeviceViewModel.Update(); } @@ -116,7 +115,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization #region Selection private MouseDragStatus _mouseDragStatus; - private System.Windows.Point _mouseDragStartPoint; + private Point _mouseDragStartPoint; // ReSharper disable once UnusedMember.Global - Called from view public void EditorGridMouseClick(object sender, MouseEventArgs e) @@ -124,7 +123,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization if (IsPanKeyDown()) return; - var position = e.GetPosition((IInputElement)sender); + var position = e.GetPosition((IInputElement) sender); var relative = PanZoomViewModel.GetRelativeMousePosition(sender, e); if (e.LeftButton == MouseButtonState.Pressed) StartMouseDrag(position, relative); @@ -142,12 +141,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization return; } - var position = e.GetPosition((IInputElement)sender); + var position = e.GetPosition((IInputElement) sender); if (_mouseDragStatus == MouseDragStatus.Selecting) UpdateSelection(position); } - private void StartMouseDrag(System.Windows.Point position, System.Windows.Point relative) + private void StartMouseDrag(Point position, Point relative) { _mouseDragStatus = MouseDragStatus.Selecting; _mouseDragStartPoint = position; @@ -156,7 +155,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization SelectionRectangle.Rect = new Rect(); } - private void StopMouseDrag(System.Windows.Point position) + private void StopMouseDrag(Point position) { var selectedRect = new Rect(_mouseDragStartPoint, position); // TODO: Select LEDs diff --git a/src/Artemis.UI/Screens/News/NewsView.xaml b/src/Artemis.UI/Screens/News/NewsView.xaml index 767131af9..84a82cb3c 100644 --- a/src/Artemis.UI/Screens/News/NewsView.xaml +++ b/src/Artemis.UI/Screens/News/NewsView.xaml @@ -1,12 +1,12 @@  - Today's news: There is no news (yet)! + Today's news: There is no news (yet)! - + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/RootViewModel.cs b/src/Artemis.UI/Screens/RootViewModel.cs index 8d4829336..a151bcc44 100644 --- a/src/Artemis.UI/Screens/RootViewModel.cs +++ b/src/Artemis.UI/Screens/RootViewModel.cs @@ -11,8 +11,6 @@ using Artemis.UI.Screens.News; using Artemis.UI.Screens.Settings; using Artemis.UI.Screens.SurfaceEditor; using Artemis.UI.Screens.Workshop; -using MahApps.Metro.Controls; -using MaterialDesignThemes.Wpf.Transitions; using Stylet; namespace Artemis.UI.Screens diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceCreateView.xaml b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceCreateView.xaml index e3e9b2c3c..f58bf81cb 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceCreateView.xaml +++ b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceCreateView.xaml @@ -6,15 +6,15 @@ xmlns:s="https://github.com/canton7/Stylet" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" - d:DesignHeight="213.053" d:DesignWidth="254.425" > + d:DesignHeight="213.053" d:DesignWidth="254.425"> Add a new surface layout - diff --git a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs index aed6a5b42..53433b4de 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs +++ b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs @@ -21,9 +21,9 @@ namespace Artemis.UI.Screens.SurfaceEditor { public class SurfaceEditorViewModel : Screen, IScreenViewModel { + private readonly IDeviceService _deviceService; private readonly IDialogService _dialogService; private readonly ISettingsService _settingsService; - private readonly IDeviceService _deviceService; private readonly ISurfaceService _surfaceService; public SurfaceEditorViewModel(ISurfaceService surfaceService, IDialogService dialogService, ISettingsService settingsService, IDeviceService deviceService) @@ -52,6 +52,9 @@ namespace Artemis.UI.Screens.SurfaceEditor get => _selectedSurface; set { + if (value == null) + return; + _selectedSurface = value; ApplySelectedSurfaceConfiguration(); } @@ -104,12 +107,6 @@ namespace Artemis.UI.Screens.SurfaceEditor private void ApplySelectedSurfaceConfiguration() { - if (SelectedSurface == null) - { - Execute.PostToUIThread(Devices.Clear); - return; - } - // Make sure all devices have an up-to-date VM foreach (var surfaceDeviceConfiguration in SelectedSurface.Devices) { diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml b/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml index 61af2a9be..72d4f800d 100644 --- a/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml +++ b/src/Artemis.UI/Screens/SurfaceEditor/Visualization/SurfaceDeviceView.xaml @@ -59,7 +59,7 @@ - + diff --git a/src/Artemis.UI/Screens/Workshop/WorkshopView.xaml b/src/Artemis.UI/Screens/Workshop/WorkshopView.xaml index 96713ef1e..edef5de79 100644 --- a/src/Artemis.UI/Screens/Workshop/WorkshopView.xaml +++ b/src/Artemis.UI/Screens/Workshop/WorkshopView.xaml @@ -1,12 +1,12 @@  - Work work! + Work work! - + \ No newline at end of file diff --git a/src/Artemis.UI/packages.config b/src/Artemis.UI/packages.config index ca3bbebe2..00b1df5f3 100644 --- a/src/Artemis.UI/packages.config +++ b/src/Artemis.UI/packages.config @@ -5,6 +5,7 @@ +