diff --git a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs b/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs index c7eadbe8d..c544b819b 100644 --- a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs @@ -3,10 +3,11 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Linq; +using Stylet; namespace Artemis.Core.Models.Profile.Abstract { - public abstract class ProfileElement + public abstract class ProfileElement : PropertyChangedBase { protected List _children; @@ -55,7 +56,9 @@ namespace Artemis.Core.Models.Profile.Abstract var folders = new List(); foreach (var childFolder in Children.Where(c => c is Folder).Cast()) { + // Add all folders in this element folders.Add(childFolder); + // Add all folders in folders inside this element folders.AddRange(childFolder.GetAllFolders()); } @@ -64,14 +67,16 @@ namespace Artemis.Core.Models.Profile.Abstract public List GetAllLayers() { - var folders = new List(); - foreach (var childLayer in Children.Where(c => c is Layer).Cast()) - { - folders.Add(childLayer); - folders.AddRange(childLayer.GetAllLayers()); - } + var layers = new List(); - return folders; + // Add all layers in this element + layers.AddRange(Children.Where(c => c is Layer).Cast()); + + // Add all layers in folders inside this element + foreach (var childFolder in Children.Where(c => c is Folder).Cast()) + layers.AddRange(childFolder.GetAllLayers()); + + return layers; } /// diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index 068b61faa..9952527ed 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Drawing; using System.Linq; using Artemis.Core.Models.Profile.Abstract; @@ -27,6 +26,10 @@ namespace Artemis.Core.Models.Profile Profile = profile; Parent = parent; + Name = folderEntity.Name; + Order = folderEntity.Order; + + // TODO: Load conditions // Load child folders foreach (var childFolder in Profile.ProfileEntity.Folders.Where(f => f.ParentId == EntityId)) diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 08659f12b..4d8e1b847 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -3,7 +3,6 @@ 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; @@ -11,7 +10,6 @@ using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Interfaces; using Artemis.Core.Services.Interfaces; using Artemis.Storage.Entities.Profile; -using Device = Artemis.Core.Models.Surface.Device; namespace Artemis.Core.Models.Profile { @@ -35,6 +33,9 @@ namespace Artemis.Core.Models.Profile Profile = profile; Parent = parent; + Name = layerEntity.Name; + Order = layerEntity.Order; + LayerType = pluginService.GetLayerTypeByGuid(layerEntity.LayerTypeGuid); Leds = new List(); } @@ -129,7 +130,7 @@ namespace Artemis.Core.Models.Profile path.AddRectangles(Leds.Select(l => l.AbsoluteRenderRectangle).ToArray()); RenderPath = path; } - + public override string ToString() { return $"Layer - {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index d5b6b4451..d16fc3b25 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -140,7 +140,7 @@ namespace Artemis.Core.Models.Profile { Deactivated?.Invoke(this, EventArgs.Empty); } - + #endregion } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index 9eeee057b..da840cf70 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -96,9 +96,11 @@ namespace Artemis.Core.Services.Storage profile.ApplyToEntity(); if (includeChildren) { - foreach (var profileElement in profile.Children) - profileElement.ApplyToEntity(); - + foreach (var folder in profile.GetAllFolders()) + folder.ApplyToEntity(); + foreach (var layer in profile.GetAllLayers()) + layer.ApplyToEntity(); + if (_surfaceService.ActiveSurface != null) profile.ApplySurface(_surfaceService.ActiveSurface); } diff --git a/src/Artemis.Storage/Entities/Profile/LayerEntity.cs b/src/Artemis.Storage/Entities/Profile/LayerEntity.cs index 28016388c..378e9d7cf 100644 --- a/src/Artemis.Storage/Entities/Profile/LayerEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/LayerEntity.cs @@ -6,13 +6,20 @@ namespace Artemis.Storage.Entities.Profile { public class LayerEntity { + public LayerEntity() + { + Leds = new List(); + Condition = new List(); + Elements = new List(); + } + public Guid Id { get; set; } public Guid ParentId { get; set; } public Guid LayerTypeGuid { get; set; } public int Order { get; set; } public string Name { get; set; } - + public List Leds { get; set; } public List Condition { get; set; } public List Elements { get; set; } diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 3e967b541..7b8c0726f 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -166,7 +166,10 @@ Resources.resx - + + ProfileElementRenameView.xaml + + @@ -220,6 +223,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileCreateViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileCreateViewModel.cs index e3d0ec753..a40a8405c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileCreateViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileCreateViewModel.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Artemis.UI.ViewModels.Dialogs; +using FluentValidation; using Stylet; namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs @@ -27,4 +28,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs Session.Close(); } } + + public class ProfileCreateViewModelValidator : AbstractValidator + { + public ProfileCreateViewModelValidator() + { + RuleFor(m => m.ProfileName).NotEmpty().WithMessage("Profile name may not be empty"); + } + } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml new file mode 100644 index 000000000..4bf479023 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml @@ -0,0 +1,39 @@ + + + + Rename profile element + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml.cs new file mode 100644 index 000000000..6b1e35317 --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs +{ + /// + /// Interaction logic for ProfileElementRenameView.xaml + /// + public partial class ProfileElementRenameView : UserControl + { + public ProfileElementRenameView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs new file mode 100644 index 000000000..49a180f9f --- /dev/null +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/ProfileElementRenameViewModel.cs @@ -0,0 +1,41 @@ +using System.Threading.Tasks; +using Artemis.Core.Models.Profile.Abstract; +using Artemis.UI.ViewModels.Dialogs; +using FluentValidation; +using Stylet; + +namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs +{ + public class ProfileElementRenameViewModel : DialogViewModelBase + { + public ProfileElementRenameViewModel(IModelValidator validator, ProfileElement profileElement) : base(validator) + { + ElementName = profileElement.Name; + } + + public string ElementName { get; set; } + + public async Task Accept() + { + await ValidateAsync(); + + if (HasErrors) + return; + + Session.Close(ElementName); + } + + public void Cancel() + { + Session.Close(); + } + } + + public class ProfileElementRenameViewModelValidator : AbstractValidator + { + public ProfileElementRenameViewModelValidator() + { + RuleFor(m => m.ElementName).NotEmpty().WithMessage("Element name may not be empty"); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/SurfaceCreateViewModelValidator.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/SurfaceCreateViewModelValidator.cs deleted file mode 100644 index 10ad86a51..000000000 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Dialogs/SurfaceCreateViewModelValidator.cs +++ /dev/null @@ -1,12 +0,0 @@ -using FluentValidation; - -namespace Artemis.UI.Screens.Module.ProfileEditor.Dialogs -{ - public class ProfileCreateViewModelValidator : AbstractValidator - { - public ProfileCreateViewModelValidator() - { - RuleFor(m => m.ProfileName).NotEmpty().WithMessage("Profile name may not be empty"); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorPanelViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorPanelViewModel.cs index a0214b88a..77a81d739 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorPanelViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorPanelViewModel.cs @@ -1,13 +1,16 @@ -using Artemis.Core.Models.Profile; -using Stylet; +using Stylet; namespace Artemis.UI.Screens.Module.ProfileEditor { public class ProfileEditorPanelViewModel : Screen { - public Profile Profile { get; set; } + public ProfileEditorViewModel ProfileEditorViewModel { get; set; } - public virtual void OnProfileChanged() + public virtual void ActiveProfileChanged() + { + } + + public virtual void ActiveProfileUpdated() { } } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs index 4b87a8a75..191ec1c78 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileEditorViewModel.cs @@ -18,16 +18,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor { public class ProfileEditorViewModel : Conductor.Collection.AllActive { - private readonly IDialogService _dialogService; private readonly IProfileService _profileService; public ProfileEditorViewModel(ProfileModule module, ICollection viewModels, IProfileService profileService, IDialogService dialogService) { _profileService = profileService; - _dialogService = dialogService; DisplayName = "Profile editor"; Module = module; + DialogService = dialogService; DisplayConditionsViewModel = (DisplayConditionsViewModel) viewModels.First(vm => vm is DisplayConditionsViewModel); ElementPropertiesViewModel = (ElementPropertiesViewModel) viewModels.First(vm => vm is ElementPropertiesViewModel); @@ -42,6 +41,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor } public ProfileModule Module { get; } + public IDialogService DialogService { get; } public DisplayConditionsViewModel DisplayConditionsViewModel { get; } public ElementPropertiesViewModel ElementPropertiesViewModel { get; } public LayerElementsViewModel LayerElementsViewModel { get; } @@ -68,8 +68,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor foreach (var panelViewModel in Items) { - panelViewModel.Profile = profile; - panelViewModel.OnProfileChanged(); + panelViewModel.ProfileEditorViewModel = this; + panelViewModel.ActiveProfileChanged(); } if (oldProfile != null) @@ -87,14 +87,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor public async Task AddProfile() { - var result = await _dialogService.ShowDialog(); + var result = await DialogService.ShowDialog(); if (result is string name) CreateProfile(name); } public async Task DeleteActiveProfile() { - var result = await _dialogService.ShowConfirmDialog( + var result = await DialogService.ShowConfirmDialog( "Delete active profile", "Are you sure you want to delete your currently active profile? This cannot be undone." ); @@ -154,5 +154,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor if (!activeProfile.IsActivated) Module.ChangeActiveProfile(activeProfile); } + + public void OnProfileUpdated() + { + _profileService.UpdateProfile(SelectedProfile, true); + + foreach (var panelViewModel in Items) + { + panelViewModel.ActiveProfileUpdated(); + } + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/Abstract/ProfileElementViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/Abstract/ProfileElementViewModel.cs index b832fbdcf..d6c2d78e8 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/Abstract/ProfileElementViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/Abstract/ProfileElementViewModel.cs @@ -1,17 +1,26 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using Artemis.Core.Models.Profile.Abstract; +using Artemis.UI.Screens.Module.ProfileEditor.Dialogs; using Stylet; namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.Abstract { public abstract class ProfileElementViewModel : PropertyChangedBase { - protected ProfileElementViewModel() + protected ProfileElementViewModel(FolderViewModel parent, ProfileElement profileElement, ProfileEditorViewModel profileEditorViewModel) { + Parent = parent; + ProfileElement = profileElement; + ProfileEditorViewModel = profileEditorViewModel; + Children = new BindableCollection(); } public FolderViewModel Parent { get; set; } + public ProfileEditorViewModel ProfileEditorViewModel { get; set; } + public ProfileElement ProfileElement { get; set; } public BindableCollection Children { get; set; } @@ -51,5 +60,35 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.Abstract Parent.Folder.AddChild(source.ProfileElement, ProfileElement.Order + 1); Parent.UpdateProfileElements(); } + + public async Task RenameElement() + { + var result = await ProfileEditorViewModel.DialogService.ShowDialog( + new Dictionary {{"profileElement", ProfileElement}} + ); + if (result is string newName) + { + ProfileElement.Name = newName; + ProfileEditorViewModel.OnProfileUpdated(); + } + } + + public async Task DeleteElement() + { + var result = await ProfileEditorViewModel.DialogService.ShowConfirmDialog( + "Delete profile element", + "Are you sure you want to delete this element? This cannot be undone." + ); + + if (!result) + return; + + // Farewell, cruel world + ProfileElement.Parent.RemoveChild(ProfileElement); + Parent.RemoveExistingElement(this); + Parent.UpdateProfileElements(); + + ProfileEditorViewModel.OnProfileUpdated(); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/FolderView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/FolderView.xaml index e840fda57..be62c30de 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/FolderView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/FolderView.xaml @@ -12,11 +12,16 @@ - + + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/FolderViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/FolderViewModel.cs index fede07d5e..9130a34ff 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/FolderViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/FolderViewModel.cs @@ -6,11 +6,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements { public class FolderViewModel : ProfileElementViewModel { - public FolderViewModel(Folder folder, FolderViewModel parent) + public FolderViewModel(FolderViewModel parent, Folder folder, ProfileEditorViewModel profileEditorViewModel) : base(parent, folder, profileEditorViewModel) { Folder = folder; - Parent = parent; - ProfileElement = folder; + UpdateProfileElements(); } public Folder Folder { get; } @@ -19,12 +18,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements { Folder.AddFolder("New folder"); UpdateProfileElements(); + + ProfileEditorViewModel.OnProfileUpdated(); } public void AddLayer() { Folder.AddLayer("New layer"); UpdateProfileElements(); + + ProfileEditorViewModel.OnProfileUpdated(); } public void RemoveExistingElement(ProfileElementViewModel element) @@ -32,8 +35,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements Folder.RemoveChild(element.ProfileElement); Children.Remove(element); element.Parent = null; - - UpdateProfileElements(); } public void AddExistingElement(ProfileElementViewModel element) @@ -41,11 +42,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements Folder.AddChild(element.ProfileElement); Children.Add(element); element.Parent = this; - - UpdateProfileElements(); } - public override void UpdateProfileElements() + public sealed override void UpdateProfileElements() { // Ensure every child element has an up-to-date VM if (Folder.Children != null) @@ -57,13 +56,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements { existing = Children.FirstOrDefault(p => p is FolderViewModel vm && vm.Folder == folder); if (existing == null) - Children.Add(new FolderViewModel(folder, this)); + Children.Add(new FolderViewModel(this, folder, ProfileEditorViewModel)); } else if (profileElement is Layer layer) { existing = Children.FirstOrDefault(p => p is LayerViewModel vm && vm.Layer == layer); if (existing == null) - Children.Add(new LayerViewModel(layer, this)); + Children.Add(new LayerViewModel(this, layer, ProfileEditorViewModel)); } existing?.UpdateProfileElements(); diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/LayerView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/LayerView.xaml index 8e9ce8161..c6079bbe2 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/LayerView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/LayerView.xaml @@ -12,11 +12,16 @@ - + + + + + + diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/LayerViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/LayerViewModel.cs index 5fa46a993..550849d69 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/LayerViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/LayerViewModel.cs @@ -5,11 +5,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements { public class LayerViewModel : ProfileElementViewModel { - public LayerViewModel(Layer layer, FolderViewModel parent) + public LayerViewModel(FolderViewModel parent, Layer layer, ProfileEditorViewModel profileEditorViewModel) : base(parent, layer, profileEditorViewModel) { Layer = layer; - Parent = parent; - ProfileElement = layer; } public Layer Layer { get; } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/ProfileElementsViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/ProfileElementsViewModel.cs index fc7307cf8..67020ee03 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/ProfileElementsViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileElements/ProfileElementsViewModel.cs @@ -56,6 +56,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements target.SetElementBehind(source); break; } + + ProfileEditorViewModel.OnProfileUpdated(); } public void AddFolder() @@ -68,24 +70,24 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements RootFolder?.AddLayer(); } - public override void OnProfileChanged() + public override void ActiveProfileChanged() { CreateRootFolderViewModel(); - base.OnProfileChanged(); + base.ActiveProfileChanged(); } private void CreateRootFolderViewModel() { - if (!(Profile?.Children?.FirstOrDefault() is Folder folder)) + if (!(ProfileEditorViewModel?.SelectedProfile?.Children?.FirstOrDefault() is Folder folder)) { RootFolder = null; return; } - RootFolder = new FolderViewModel(folder, null); + RootFolder = new FolderViewModel(null, folder, ProfileEditorViewModel); } - private DragDropType GetDragDropType(IDropInfo dropInfo) + private static DragDropType GetDragDropType(IDropInfo dropInfo) { var source = dropInfo.Data as ProfileElementViewModel; var target = dropInfo.TargetItem as ProfileElementViewModel;