diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs
index 7ef74f1d1..6a02aa2ec 100644
--- a/src/Artemis.Core/Models/Profile/Folder.cs
+++ b/src/Artemis.Core/Models/Profile/Folder.cs
@@ -22,7 +22,8 @@ namespace Artemis.Core
///
/// The parent of the folder
/// The name of the folder
- public Folder(ProfileElement parent, string name) : base(parent.Profile)
+ /// The order where to place the child (0-based), defaults to the end of the collection
+ public Folder(ProfileElement parent, string name, int order) : base(parent.Profile)
{
FolderEntity = new FolderEntity();
EntityId = Guid.NewGuid();
@@ -31,7 +32,7 @@ namespace Artemis.Core
Profile = Parent.Profile;
Name = name;
- Parent.AddChild(this);
+ Parent.AddChild(this, order);
}
///
diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs
index dfb0a68dc..b1ccccfc6 100644
--- a/src/Artemis.Core/Models/Profile/Layer.cs
+++ b/src/Artemis.Core/Models/Profile/Layer.cs
@@ -29,7 +29,8 @@ namespace Artemis.Core
///
/// The parent of the layer
/// The name of the layer
- public Layer(ProfileElement parent, string name) : base(parent.Profile)
+ /// The order where to place the child (0-based), defaults to the end of the collection
+ public Layer(ProfileElement parent, string name, int order) : base(parent.Profile)
{
LayerEntity = new LayerEntity();
EntityId = Guid.NewGuid();
@@ -47,7 +48,7 @@ namespace Artemis.Core
Adapter = new LayerAdapter(this);
Initialize();
- Parent.AddChild(this, 0);
+ Parent.AddChild(this, order);
}
///
diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs
index a9090e12d..a905c3017 100644
--- a/src/Artemis.Core/Models/Profile/Profile.cs
+++ b/src/Artemis.Core/Models/Profile/Profile.cs
@@ -198,7 +198,7 @@ namespace Artemis.Core
FolderEntity? rootFolder = ProfileEntity.Folders.FirstOrDefault(f => f.ParentId == EntityId);
if (rootFolder == null)
{
- Folder _ = new(this, "Root folder");
+ Folder _ = new(this, "Root folder", 0);
}
else
{
diff --git a/src/Artemis.Core/Utilities/Utilities.cs b/src/Artemis.Core/Utilities/Utilities.cs
index e6391399a..42774d5d9 100644
--- a/src/Artemis.Core/Utilities/Utilities.cs
+++ b/src/Artemis.Core/Utilities/Utilities.cs
@@ -44,6 +44,9 @@ namespace Artemis.Core
/// A list of extra arguments to pass to Artemis when restarting
public static void Restart(bool elevate, TimeSpan delay, params string[] extraArgs)
{
+ if (!OperatingSystem.IsWindows() && elevate)
+ throw new ArtemisCoreException("Elevation on non-Windows platforms is not supported.");
+
OnRestartRequested(new RestartEventArgs(elevate, delay, extraArgs.ToList()));
}
diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs
index 58d6560fd..d467c25a2 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs
@@ -137,7 +137,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
if (!SupportsChildren)
throw new ArtemisUIException("Cannot add a folder to a profile element of type " + ProfileElement.GetType().Name);
- Folder _ = new(ProfileElement, "New folder");
+ Folder _ = new(ProfileElement, "New folder", 0);
_profileEditorService.SaveSelectedProfileConfiguration();
}
@@ -146,7 +146,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
if (!SupportsChildren)
throw new ArtemisUIException("Cannot add a layer to a profile element of type " + ProfileElement.GetType().Name);
- Layer layer = new(ProfileElement, "New layer");
+ Layer layer = new(ProfileElement, "New layer", 0);
// Could be null if the default brush got disabled
LayerBrushDescriptor brush = _layerBrushService.GetDefaultLayerBrush();
diff --git a/src/Avalonia/Artemis.UI.Linux/Artemis.UI.Linux.csproj b/src/Avalonia/Artemis.UI.Linux/Artemis.UI.Linux.csproj
index 69e1b2744..95b799e45 100644
--- a/src/Avalonia/Artemis.UI.Linux/Artemis.UI.Linux.csproj
+++ b/src/Avalonia/Artemis.UI.Linux/Artemis.UI.Linux.csproj
@@ -14,6 +14,7 @@
+
diff --git a/src/Avalonia/Artemis.UI.Linux/packages.lock.json b/src/Avalonia/Artemis.UI.Linux/packages.lock.json
index bb01b4430..251ccdd08 100644
--- a/src/Avalonia/Artemis.UI.Linux/packages.lock.json
+++ b/src/Avalonia/Artemis.UI.Linux/packages.lock.json
@@ -53,6 +53,20 @@
"System.Reactive": "5.0.0"
}
},
+ "ReactiveUI": {
+ "type": "Direct",
+ "requested": "[17.1.9, )",
+ "resolved": "17.1.9",
+ "contentHash": "bxH6uzEi1b6cfGoBBvCXWrdT18+Rleggi0R/vOaCYc+zvlSleJW6wlUtcWjrKzgQHD8EN3c02A4JBTt9oGSWWQ==",
+ "dependencies": {
+ "DynamicData": "7.4.3",
+ "Splat": "14.1.1",
+ "System.ComponentModel": "4.3.0",
+ "System.Diagnostics.Contracts": "4.3.0",
+ "System.Dynamic.Runtime": "4.3.0",
+ "System.Runtime.Serialization.Primitives": "4.3.0"
+ }
+ },
"Avalonia.Angle.Windows.Natives": {
"type": "Transitive",
"resolved": "2.1.0.2020091801",
@@ -191,8 +205,8 @@
},
"DynamicData": {
"type": "Transitive",
- "resolved": "7.3.1",
- "contentHash": "E9oTvWlAgzct0MuWt6k+0s+nSDA3LkFVvDwkMUTklIZZnva314KZAEF2vG4XX9I98ia+EpMqjte67jWEBJlsRw==",
+ "resolved": "7.4.3",
+ "contentHash": "7eGyREbtzyaRutMa+iToi2e41JboEVK9c1ZBcTvJOfEoTRIZX3hChIsxIvV0ErzMXtGHAIS2O0I8jLDUIds5wg==",
"dependencies": {
"System.Reactive": "5.0.0"
}
@@ -522,15 +536,6 @@
"Ninject": "3.3.3"
}
},
- "ReactiveUI": {
- "type": "Transitive",
- "resolved": "16.2.6",
- "contentHash": "jf1RvD8HxHuA6CGQtheGHUCHzRrhpvo0z593Npsz7g8KJWXfGR45Dc9bILJHoymBxhdDD1L1WjUfh0fcucIPPg==",
- "dependencies": {
- "DynamicData": "7.3.1",
- "Splat": "13.1.1"
- }
- },
"ReactiveUI.Validation": {
"type": "Transitive",
"resolved": "2.2.1",
@@ -918,6 +923,14 @@
"System.Text.Encoding": "4.3.0"
}
},
+ "System.Diagnostics.Contracts": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "eelRRbnm+OloiQvp9CXS0ixjNQldjjkHO4iIkR5XH2VIP8sUB/SIpa1TdUW6/+HDcQ+MlhP3pNa1u5SbzYuWGA==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
"System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -1398,6 +1411,15 @@
"System.Runtime.Extensions": "4.3.0"
}
},
+ "System.Runtime.Serialization.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==",
+ "dependencies": {
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
"System.Security.AccessControl": {
"type": "Transitive",
"resolved": "5.0.0",
@@ -1757,6 +1779,7 @@
"Material.Icons.Avalonia": "1.0.2",
"RGB.NET.Core": "1.0.0-prerelease1",
"RGB.NET.Layout": "1.0.0-prerelease1",
+ "ReactiveUI": "17.1.9",
"ReactiveUI.Validation": "2.2.1",
"Splat.Ninject": "14.1.17"
}
@@ -1774,6 +1797,7 @@
"FluentAvaloniaUI": "1.1.8",
"Material.Icons.Avalonia": "1.0.2",
"RGB.NET.Core": "1.0.0-prerelease1",
+ "ReactiveUI": "17.1.9",
"ReactiveUI.Validation": "2.2.1"
}
}
diff --git a/src/Avalonia/Artemis.UI.MacOS/Artemis.UI.MacOS.csproj b/src/Avalonia/Artemis.UI.MacOS/Artemis.UI.MacOS.csproj
index 69e1b2744..95b799e45 100644
--- a/src/Avalonia/Artemis.UI.MacOS/Artemis.UI.MacOS.csproj
+++ b/src/Avalonia/Artemis.UI.MacOS/Artemis.UI.MacOS.csproj
@@ -14,6 +14,7 @@
+
diff --git a/src/Avalonia/Artemis.UI.MacOS/packages.lock.json b/src/Avalonia/Artemis.UI.MacOS/packages.lock.json
index bb01b4430..251ccdd08 100644
--- a/src/Avalonia/Artemis.UI.MacOS/packages.lock.json
+++ b/src/Avalonia/Artemis.UI.MacOS/packages.lock.json
@@ -53,6 +53,20 @@
"System.Reactive": "5.0.0"
}
},
+ "ReactiveUI": {
+ "type": "Direct",
+ "requested": "[17.1.9, )",
+ "resolved": "17.1.9",
+ "contentHash": "bxH6uzEi1b6cfGoBBvCXWrdT18+Rleggi0R/vOaCYc+zvlSleJW6wlUtcWjrKzgQHD8EN3c02A4JBTt9oGSWWQ==",
+ "dependencies": {
+ "DynamicData": "7.4.3",
+ "Splat": "14.1.1",
+ "System.ComponentModel": "4.3.0",
+ "System.Diagnostics.Contracts": "4.3.0",
+ "System.Dynamic.Runtime": "4.3.0",
+ "System.Runtime.Serialization.Primitives": "4.3.0"
+ }
+ },
"Avalonia.Angle.Windows.Natives": {
"type": "Transitive",
"resolved": "2.1.0.2020091801",
@@ -191,8 +205,8 @@
},
"DynamicData": {
"type": "Transitive",
- "resolved": "7.3.1",
- "contentHash": "E9oTvWlAgzct0MuWt6k+0s+nSDA3LkFVvDwkMUTklIZZnva314KZAEF2vG4XX9I98ia+EpMqjte67jWEBJlsRw==",
+ "resolved": "7.4.3",
+ "contentHash": "7eGyREbtzyaRutMa+iToi2e41JboEVK9c1ZBcTvJOfEoTRIZX3hChIsxIvV0ErzMXtGHAIS2O0I8jLDUIds5wg==",
"dependencies": {
"System.Reactive": "5.0.0"
}
@@ -522,15 +536,6 @@
"Ninject": "3.3.3"
}
},
- "ReactiveUI": {
- "type": "Transitive",
- "resolved": "16.2.6",
- "contentHash": "jf1RvD8HxHuA6CGQtheGHUCHzRrhpvo0z593Npsz7g8KJWXfGR45Dc9bILJHoymBxhdDD1L1WjUfh0fcucIPPg==",
- "dependencies": {
- "DynamicData": "7.3.1",
- "Splat": "13.1.1"
- }
- },
"ReactiveUI.Validation": {
"type": "Transitive",
"resolved": "2.2.1",
@@ -918,6 +923,14 @@
"System.Text.Encoding": "4.3.0"
}
},
+ "System.Diagnostics.Contracts": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "eelRRbnm+OloiQvp9CXS0ixjNQldjjkHO4iIkR5XH2VIP8sUB/SIpa1TdUW6/+HDcQ+MlhP3pNa1u5SbzYuWGA==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
"System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -1398,6 +1411,15 @@
"System.Runtime.Extensions": "4.3.0"
}
},
+ "System.Runtime.Serialization.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==",
+ "dependencies": {
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
"System.Security.AccessControl": {
"type": "Transitive",
"resolved": "5.0.0",
@@ -1757,6 +1779,7 @@
"Material.Icons.Avalonia": "1.0.2",
"RGB.NET.Core": "1.0.0-prerelease1",
"RGB.NET.Layout": "1.0.0-prerelease1",
+ "ReactiveUI": "17.1.9",
"ReactiveUI.Validation": "2.2.1",
"Splat.Ninject": "14.1.17"
}
@@ -1774,6 +1797,7 @@
"FluentAvaloniaUI": "1.1.8",
"Material.Icons.Avalonia": "1.0.2",
"RGB.NET.Core": "1.0.0-prerelease1",
+ "ReactiveUI": "17.1.9",
"ReactiveUI.Validation": "2.2.1"
}
}
diff --git a/src/Avalonia/Artemis.UI.Shared/Artemis.UI.Shared.csproj b/src/Avalonia/Artemis.UI.Shared/Artemis.UI.Shared.csproj
index 8d084dfdd..1ceca6a48 100644
--- a/src/Avalonia/Artemis.UI.Shared/Artemis.UI.Shared.csproj
+++ b/src/Avalonia/Artemis.UI.Shared/Artemis.UI.Shared.csproj
@@ -24,6 +24,7 @@
+
diff --git a/src/Avalonia/Artemis.UI.Shared/Services/Builders/NotificationBuilder.cs b/src/Avalonia/Artemis.UI.Shared/Services/Builders/NotificationBuilder.cs
index 266f71062..e66117255 100644
--- a/src/Avalonia/Artemis.UI.Shared/Services/Builders/NotificationBuilder.cs
+++ b/src/Avalonia/Artemis.UI.Shared/Services/Builders/NotificationBuilder.cs
@@ -123,7 +123,7 @@ namespace Artemis.UI.Shared.Services.Builders
public IControl Build()
{
return _action != null
- ? new Button {Content = _text, Command = ReactiveCommand.Create(() => _action)}
+ ? new Button {Content = _text, Command = ReactiveCommand.Create(() => _action())}
: new Button {Content = _text};
}
}
diff --git a/src/Avalonia/Artemis.UI.Shared/Styles/Border.axaml b/src/Avalonia/Artemis.UI.Shared/Styles/Border.axaml
index b1d279fb3..27e3bf784 100644
--- a/src/Avalonia/Artemis.UI.Shared/Styles/Border.axaml
+++ b/src/Avalonia/Artemis.UI.Shared/Styles/Border.axaml
@@ -25,6 +25,10 @@
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs
index 1d1ddb99e..1e2b76874 100644
--- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs
+++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs
@@ -1,11 +1,14 @@
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
+using System.Reactive;
using System.Reactive.Disposables;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Services;
using Artemis.UI.Shared;
+using HistoricalReactiveCommand;
using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
@@ -13,15 +16,48 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
public class ProfileTreeViewModel : ActivatableViewModelBase
{
private readonly IProfileEditorVmFactory _profileEditorVmFactory;
+ private TreeItemViewModel? _selectedTreeItem;
public ProfileTreeViewModel(IProfileEditorService profileEditorService, IProfileEditorVmFactory profileEditorVmFactory)
{
_profileEditorVmFactory = profileEditorVmFactory;
- this.WhenActivated(d => profileEditorService.CurrentProfileConfiguration.WhereNotNull().Subscribe(Repopulate).DisposeWith(d));
+
+ this.WhenActivated(d =>
+ {
+ ProfileConfiguration profileConfiguration = null!;
+ profileEditorService.CurrentProfileConfiguration.WhereNotNull().Subscribe(p => profileConfiguration = p).DisposeWith(d);
+ profileEditorService.CurrentProfileConfiguration.WhereNotNull().Subscribe(Repopulate).DisposeWith(d);
+ profileEditorService.CurrentProfileElement.WhereNotNull().Subscribe(SelectCurrentProfileElement).DisposeWith(d);
+
+ Folder rootFolder = profileConfiguration.Profile!.GetRootFolder();
+ AddLayer = ReactiveCommandEx.CreateWithHistory("AddLayerAtRoot",
+ // ReSharper disable once ObjectCreationAsStatement
+ () => new Layer(rootFolder, "New layer", 0),
+ () => rootFolder.RemoveChild(rootFolder.Children[0]),
+ profileConfiguration.Profile.EntityId.ToString()
+ );
+
+ AddFolder = ReactiveCommandEx.CreateWithHistory("AddFolderAtRoot",
+ // ReSharper disable once ObjectCreationAsStatement
+ () => new Folder(rootFolder, "New folder", 0),
+ () => rootFolder.RemoveChild(rootFolder.Children[0]),
+ profileConfiguration.Profile.EntityId.ToString()
+ );
+ });
+ this.WhenAnyValue(vm => vm.SelectedTreeItem).Subscribe(model => profileEditorService.ChangeCurrentProfileElement(model?.ProfileElement));
}
+ public ReactiveCommandWithHistory? AddLayer { get; set; }
+ public ReactiveCommandWithHistory? AddFolder { get; set; }
+
public ObservableCollection TreeItems { get; } = new();
+ public TreeItemViewModel? SelectedTreeItem
+ {
+ get => _selectedTreeItem;
+ set => this.RaiseAndSetIfChanged(ref _selectedTreeItem, value);
+ }
+
private void Repopulate(ProfileConfiguration profileConfiguration)
{
if (TreeItems.Any())
@@ -33,11 +69,43 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
foreach (ProfileElement profileElement in profileConfiguration.Profile.GetRootFolder().Children)
{
if (profileElement is Folder folder)
- TreeItems.Add(_profileEditorVmFactory.FolderTreeItemViewModel(folder));
+ TreeItems.Add(_profileEditorVmFactory.FolderTreeItemViewModel(null, folder));
else if (profileElement is Layer layer)
- TreeItems.Add(_profileEditorVmFactory.LayerTreeItemViewModel(layer));
+ TreeItems.Add(_profileEditorVmFactory.LayerTreeItemViewModel(null, layer));
}
-
+ }
+
+ private void SelectCurrentProfileElement(RenderProfileElement element)
+ {
+ if (SelectedTreeItem?.ProfileElement == element)
+ return;
+
+ // Find the tree item belonging to the selected element
+ List treeItems = GetAllTreeItems(TreeItems);
+ TreeItemViewModel? selected = treeItems.FirstOrDefault(e => e.ProfileElement == element);
+
+ // Walk up the tree, expanding parents
+ TreeItemViewModel? currentParent = selected?.Parent;
+ while (currentParent != null)
+ {
+ currentParent.IsExpanded = true;
+ currentParent = currentParent.Parent;
+ }
+
+ SelectedTreeItem = selected;
+ }
+
+ private List GetAllTreeItems(ObservableCollection treeItems)
+ {
+ List result = new();
+ foreach (TreeItemViewModel treeItemViewModel in treeItems)
+ {
+ result.Add(treeItemViewModel);
+ if (treeItemViewModel.Children.Any())
+ result.AddRange(GetAllTreeItems(treeItemViewModel.Children));
+ }
+
+ return result;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs
index 28397234e..2497df852 100644
--- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs
+++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs
@@ -1,8 +1,55 @@
-using Artemis.UI.Shared;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Artemis.Core;
+using Artemis.UI.Shared;
+using HistoricalReactiveCommand;
+using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
{
public abstract class TreeItemViewModel : ActivatableViewModelBase
{
+ private bool _isExpanded;
+
+ protected TreeItemViewModel(TreeItemViewModel? parent, RenderProfileElement profileElement)
+ {
+ Parent = parent;
+ ProfileElement = profileElement;
+
+ AddLayerAtIndex = ReactiveCommandEx.CreateWithHistory("AddLayerAtIndex",
+ (targetIndex, _) => new Layer(ProfileElement, "New folder", targetIndex),
+ (targetIndex, _) =>
+ {
+ Layer toRemove = (Layer) ProfileElement.Children.ElementAt(targetIndex);
+ ProfileElement.RemoveChild(toRemove);
+ return toRemove;
+ },
+ historyId: ProfileElement.Profile.EntityId.ToString()
+ );
+
+ AddFolderAtIndex = ReactiveCommandEx.CreateWithHistory("AddFolderAtIndex",
+ (targetIndex, _) => new Folder(ProfileElement, "New folder", targetIndex),
+ (targetIndex, _) =>
+ {
+ Folder toRemove = (Folder) ProfileElement.Children.ElementAt(targetIndex);
+ ProfileElement.RemoveChild(toRemove);
+ return toRemove;
+ },
+ historyId: ProfileElement.Profile.EntityId.ToString()
+ );
+ }
+
+ public ReactiveCommandWithHistory AddLayerAtIndex { get; set; }
+ public ReactiveCommandWithHistory AddFolderAtIndex { get; set; }
+
+ public RenderProfileElement ProfileElement { get; }
+ public TreeItemViewModel? Parent { get; set; }
+ public ObservableCollection Children { get; } = new();
+
+ public bool IsExpanded
+ {
+ get => _isExpanded;
+ set => this.RaiseAndSetIfChanged(ref _isExpanded, value);
+ }
}
}
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarView.axaml b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarView.axaml
new file mode 100644
index 000000000..62afce2c8
--- /dev/null
+++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarView.axaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarView.axaml.cs
new file mode 100644
index 000000000..08b7a31c3
--- /dev/null
+++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarView.axaml.cs
@@ -0,0 +1,25 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Markup.Xaml;
+
+namespace Artemis.UI.Screens.ProfileEditor
+{
+ public partial class ProfileEditorTitleBarView : UserControl
+ {
+ public ProfileEditorTitleBarView()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ private void MenuItem_OnSubmenuOpened(object? sender, RoutedEventArgs e)
+ {
+
+ }
+ }
+}
diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarViewModel.cs
new file mode 100644
index 000000000..c30c92144
--- /dev/null
+++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorTitleBarViewModel.cs
@@ -0,0 +1,24 @@
+using Artemis.UI.Screens.ProfileEditor.Panels.MenuBar;
+using Artemis.UI.Services.Interfaces;
+using Artemis.UI.Shared;
+
+namespace Artemis.UI.Screens.ProfileEditor
+{
+ public class ProfileEditorTitleBarViewModel : ViewModelBase
+ {
+ private readonly IDebugService _debugService;
+
+ public ProfileEditorTitleBarViewModel(IDebugService debugService, MenuBarViewModel menuBarViewModel)
+ {
+ MenuBarViewModel = menuBarViewModel;
+ _debugService = debugService;
+ }
+
+ public MenuBarViewModel MenuBarViewModel { get; }
+
+ public void ShowDebugger()
+ {
+ _debugService.ShowDebugger();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.axaml b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.axaml
index a64869c3d..1d04329a8 100644
--- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.axaml
+++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.axaml
@@ -24,204 +24,19 @@
+
+
-
-
-
-
+
+
+
-
@@ -239,7 +54,6 @@
-
@@ -249,9 +63,9 @@
-
+
-
+
diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs
index da3b0978b..63b13aa40 100644
--- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs
+++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs
@@ -1,6 +1,7 @@
using System;
using System.Reactive.Disposables;
using Artemis.Core;
+using Artemis.UI.Screens.ProfileEditor.Panels.MenuBar;
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
using Artemis.UI.Screens.ProfileEditor.VisualEditor;
using Artemis.UI.Services;
@@ -13,16 +14,28 @@ namespace Artemis.UI.Screens.ProfileEditor
private ProfileConfiguration? _profile;
///
- public ProfileEditorViewModel(IScreen hostScreen, IProfileEditorService profileEditorService, VisualEditorViewModel visualEditorViewModel, ProfileTreeViewModel profileTreeViewModel)
+ public ProfileEditorViewModel(IScreen hostScreen,
+ IProfileEditorService profileEditorService,
+ VisualEditorViewModel visualEditorViewModel,
+ ProfileTreeViewModel profileTreeViewModel,
+ ProfileEditorTitleBarViewModel profileEditorTitleBarViewModel,
+ MenuBarViewModel menuBarViewModel)
: base(hostScreen, "profile-editor")
{
VisualEditorViewModel = visualEditorViewModel;
ProfileTreeViewModel = profileTreeViewModel;
- this.WhenActivated(disposables => { profileEditorService.CurrentProfileConfiguration.WhereNotNull().Subscribe(p => Profile = p).DisposeWith(disposables); });
+
+ if (OperatingSystem.IsWindows())
+ TitleBarViewModel = profileEditorTitleBarViewModel;
+ else
+ MenuBarViewModel = menuBarViewModel;
+
+ this.WhenActivated(disposables => profileEditorService.CurrentProfileConfiguration.WhereNotNull().Subscribe(p => Profile = p).DisposeWith(disposables));
}
public VisualEditorViewModel VisualEditorViewModel { get; }
public ProfileTreeViewModel ProfileTreeViewModel { get; }
+ public MenuBarViewModel? MenuBarViewModel { get; }
public ProfileConfiguration? Profile
{
diff --git a/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarView.axaml b/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarView.axaml
new file mode 100644
index 000000000..3ff09a332
--- /dev/null
+++ b/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarView.axaml
@@ -0,0 +1,11 @@
+
+
+
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarView.axaml.cs
new file mode 100644
index 000000000..24d3e8070
--- /dev/null
+++ b/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarView.axaml.cs
@@ -0,0 +1,19 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Artemis.UI.Screens.Root
+{
+ public partial class DefaultTitleBarView : UserControl
+ {
+ public DefaultTitleBarView()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarViewModel.cs b/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarViewModel.cs
new file mode 100644
index 000000000..1f5060c7c
--- /dev/null
+++ b/src/Avalonia/Artemis.UI/Screens/Root/DefaultTitleBarViewModel.cs
@@ -0,0 +1,20 @@
+using Artemis.UI.Services.Interfaces;
+using Artemis.UI.Shared;
+
+namespace Artemis.UI.Screens.Root
+{
+ public class DefaultTitleBarViewModel : ViewModelBase
+ {
+ private readonly IDebugService _debugService;
+
+ public DefaultTitleBarViewModel(IDebugService debugService)
+ {
+ _debugService = debugService;
+ }
+
+ public void ShowDebugger()
+ {
+ _debugService.ShowDebugger();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/Screens/Root/RootView.axaml b/src/Avalonia/Artemis.UI/Screens/Root/RootView.axaml
index 6c5dde4ca..991a035dd 100644
--- a/src/Avalonia/Artemis.UI/Screens/Root/RootView.axaml
+++ b/src/Avalonia/Artemis.UI/Screens/Root/RootView.axaml
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Avalonia/Artemis.UI/Screens/Root/RootViewModel.cs b/src/Avalonia/Artemis.UI/Screens/Root/RootViewModel.cs
index 1301bb454..52f22ac97 100644
--- a/src/Avalonia/Artemis.UI/Screens/Root/RootViewModel.cs
+++ b/src/Avalonia/Artemis.UI/Screens/Root/RootViewModel.cs
@@ -1,4 +1,5 @@
-using System;
+
+using System;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core;
@@ -21,6 +22,7 @@ namespace Artemis.UI.Screens.Root
public class RootViewModel : ActivatableViewModelBase, IScreen, IMainWindowProvider
{
private readonly IAssetLoader _assetLoader;
+ private readonly DefaultTitleBarViewModel _defaultTitleBarViewModel;
private readonly ICoreService _coreService;
private readonly IDebugService _debugService;
private readonly IClassicDesktopStyleApplicationLifetime _lifeTime;
@@ -30,6 +32,7 @@ namespace Artemis.UI.Screens.Root
private SidebarViewModel? _sidebarViewModel;
private TrayIcon? _trayIcon;
private TrayIcons? _trayIcons;
+ private ViewModelBase? _titleBarViewModel;
public RootViewModel(ICoreService coreService,
ISettingsService settingsService,
@@ -38,6 +41,7 @@ namespace Artemis.UI.Screens.Root
IMainWindowService mainWindowService,
IDebugService debugService,
IAssetLoader assetLoader,
+ DefaultTitleBarViewModel defaultTitleBarViewModel,
ISidebarVmFactory sidebarVmFactory)
{
Router = new RoutingState();
@@ -47,6 +51,7 @@ namespace Artemis.UI.Screens.Root
_windowService = windowService;
_debugService = debugService;
_assetLoader = assetLoader;
+ _defaultTitleBarViewModel = defaultTitleBarViewModel;
_sidebarVmFactory = sidebarVmFactory;
_lifeTime = (IClassicDesktopStyleApplicationLifetime) Application.Current.ApplicationLifetime;
@@ -54,15 +59,31 @@ namespace Artemis.UI.Screens.Root
mainWindowService.ConfigureMainWindowProvider(this);
DisplayAccordingToSettings();
+ Router.CurrentViewModel.Subscribe(UpdateTitleBarViewModel);
Task.Run(coreService.Initialize);
}
+ private void UpdateTitleBarViewModel(IRoutableViewModel? viewModel)
+ {
+ if (viewModel is MainScreenViewModel mainScreenViewModel && mainScreenViewModel.TitleBarViewModel != null)
+ TitleBarViewModel = mainScreenViewModel.TitleBarViewModel;
+ else
+ TitleBarViewModel = _defaultTitleBarViewModel;
+ }
+
+
public SidebarViewModel? SidebarViewModel
{
get => _sidebarViewModel;
set => this.RaiseAndSetIfChanged(ref _sidebarViewModel, value);
}
+ public ViewModelBase? TitleBarViewModel
+ {
+ get => _titleBarViewModel;
+ set => this.RaiseAndSetIfChanged(ref _titleBarViewModel, value);
+ }
+
private void CurrentMainWindowOnClosed(object? sender, EventArgs e)
{
_lifeTime.MainWindow = null;
diff --git a/src/Avalonia/Artemis.UI/Services/ProfileEditorService.cs b/src/Avalonia/Artemis.UI/Services/ProfileEditorService.cs
index 966bbc8ac..51b299614 100644
--- a/src/Avalonia/Artemis.UI/Services/ProfileEditorService.cs
+++ b/src/Avalonia/Artemis.UI/Services/ProfileEditorService.cs
@@ -22,8 +22,7 @@ namespace Artemis.UI.Services
CurrentProfileConfiguration = Observable.Defer(() => Observable.Return(_currentProfileConfiguration)).Concat(_changeCurrentProfileConfiguration);
CurrentProfileElement = Observable.Defer(() => Observable.Return(_currentProfileElement)).Concat(_changeCurrentProfileElement);
}
-
-
+
public IObservable CurrentProfileConfiguration { get; }
public IObservable CurrentProfileElement { get; }
diff --git a/src/Avalonia/Artemis.UI/packages.lock.json b/src/Avalonia/Artemis.UI/packages.lock.json
index 908975a90..36aa30742 100644
--- a/src/Avalonia/Artemis.UI/packages.lock.json
+++ b/src/Avalonia/Artemis.UI/packages.lock.json
@@ -115,6 +115,20 @@
"Material.Icons": "1.0.2"
}
},
+ "ReactiveUI": {
+ "type": "Direct",
+ "requested": "[17.1.9, )",
+ "resolved": "17.1.9",
+ "contentHash": "bxH6uzEi1b6cfGoBBvCXWrdT18+Rleggi0R/vOaCYc+zvlSleJW6wlUtcWjrKzgQHD8EN3c02A4JBTt9oGSWWQ==",
+ "dependencies": {
+ "DynamicData": "7.4.3",
+ "Splat": "14.1.1",
+ "System.ComponentModel": "4.3.0",
+ "System.Diagnostics.Contracts": "4.3.0",
+ "System.Dynamic.Runtime": "4.3.0",
+ "System.Runtime.Serialization.Primitives": "4.3.0"
+ }
+ },
"ReactiveUI.Validation": {
"type": "Direct",
"requested": "[2.2.1, )",
@@ -268,8 +282,8 @@
},
"DynamicData": {
"type": "Transitive",
- "resolved": "7.3.1",
- "contentHash": "E9oTvWlAgzct0MuWt6k+0s+nSDA3LkFVvDwkMUTklIZZnva314KZAEF2vG4XX9I98ia+EpMqjte67jWEBJlsRw==",
+ "resolved": "7.4.3",
+ "contentHash": "7eGyREbtzyaRutMa+iToi2e41JboEVK9c1ZBcTvJOfEoTRIZX3hChIsxIvV0ErzMXtGHAIS2O0I8jLDUIds5wg==",
"dependencies": {
"System.Reactive": "5.0.0"
}
@@ -562,15 +576,6 @@
"Ninject": "3.3.3"
}
},
- "ReactiveUI": {
- "type": "Transitive",
- "resolved": "16.2.6",
- "contentHash": "jf1RvD8HxHuA6CGQtheGHUCHzRrhpvo0z593Npsz7g8KJWXfGR45Dc9bILJHoymBxhdDD1L1WjUfh0fcucIPPg==",
- "dependencies": {
- "DynamicData": "7.3.1",
- "Splat": "13.1.1"
- }
- },
"RGB.NET.Presets": {
"type": "Transitive",
"resolved": "1.0.0-prerelease1",
@@ -928,6 +933,14 @@
"System.Text.Encoding": "4.3.0"
}
},
+ "System.Diagnostics.Contracts": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "eelRRbnm+OloiQvp9CXS0ixjNQldjjkHO4iIkR5XH2VIP8sUB/SIpa1TdUW6/+HDcQ+MlhP3pNa1u5SbzYuWGA==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
"System.Diagnostics.Debug": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -1408,6 +1421,15 @@
"System.Runtime.Extensions": "4.3.0"
}
},
+ "System.Runtime.Serialization.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==",
+ "dependencies": {
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
"System.Security.AccessControl": {
"type": "Transitive",
"resolved": "5.0.0",
@@ -1763,6 +1785,7 @@
"FluentAvaloniaUI": "1.1.8",
"Material.Icons.Avalonia": "1.0.2",
"RGB.NET.Core": "1.0.0-prerelease1",
+ "ReactiveUI": "17.1.9",
"ReactiveUI.Validation": "2.2.1"
}
}