diff --git a/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml b/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml index 3ee84f85d..02a5517ec 100644 --- a/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml +++ b/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml @@ -756,6 +756,11 @@ Closes the window hosting the view model + + + Called when the the window hosting the view model should close + + Occurs when the the window hosting the view model should close diff --git a/src/Avalonia/Artemis.UI.Linux/packages.lock.json b/src/Avalonia/Artemis.UI.Linux/packages.lock.json index 0fc43dcba..666de545f 100644 --- a/src/Avalonia/Artemis.UI.Linux/packages.lock.json +++ b/src/Avalonia/Artemis.UI.Linux/packages.lock.json @@ -219,8 +219,8 @@ }, "FluentAvaloniaUI": { "type": "Transitive", - "resolved": "1.1.6", - "contentHash": "EJukyiTmEVhaYlHdntFMyQKI4+u772rSClKYQqJRfkTb1NoJXLqiIVqMjx8ZQ0pxnfih+6CZ7+x82lfrGHIPUw==", + "resolved": "1.1.7", + "contentHash": "Hco3+M09A7rDknaYu5CcyGhUOqGj5mebrFzjZVGjW5YBYiMiV+x0vl2Fn6oIfXxhKgg1i70tTwQCtW/1GWFJeA==", "dependencies": { "Avalonia": "0.10.10", "Avalonia.Desktop": "0.10.10", @@ -689,16 +689,16 @@ }, "Splat": { "type": "Transitive", - "resolved": "13.1.63", - "contentHash": "7iW45RA7AbSlQPCgdokmysva5PGd6iBUhuNkC0XD73LF9dxfTkKeo3wZkohU7nvspDhJ7PJsYHvDtxIt5bMQ8Q==" + "resolved": "14.1.1", + "contentHash": "bKQtKu57w+iJ1T+WDyDdNq+LBNVdmNu2i0vGNyUdtmg4TEIEFiX2GfPusNEAW2QOfxyDE7i4+xTxbOKZr/4jhg==" }, "Splat.Ninject": { "type": "Transitive", - "resolved": "13.1.63", - "contentHash": "rTF0HSa6p8nxrXj2hwVgkutcTDJUXY34sY+zYK4ky65b7a0ROL8kdiYyxVVLE4Lq31N5Rcd4bBbqlPkgwZguww==", + "resolved": "14.1.1", + "contentHash": "lmhjY5yRKL6SgkwY0kEtnHI8JERYhRwFiOk+NgvOUtGYzVm/RRm1OrgrN+kPKzmuvsUrodx6FYTHrSkHL2I8Yg==", "dependencies": { "Ninject": "3.3.4", - "Splat": "13.1.63" + "Splat": "14.1.1" } }, "Svg.Custom": { @@ -1692,12 +1692,12 @@ "Avalonia.Diagnostics": "0.10.10", "Avalonia.ReactiveUI": "0.10.10", "Avalonia.Svg.Skia": "0.10.10", - "FluentAvaloniaUI": "1.1.6", + "FluentAvaloniaUI": "1.1.7", "Flurl.Http": "3.2.0", "Live.Avalonia": "1.3.1", "Material.Icons.Avalonia": "1.0.2", "ReactiveUI.Validation": "2.2.1", - "Splat.Ninject": "13.1.63" + "Splat.Ninject": "14.1.1" } }, "artemis.ui.shared": { @@ -1710,7 +1710,7 @@ "Avalonia.Xaml.Behaviors": "0.10.10.4", "Avalonia.Xaml.Interactions": "0.10.10.4", "Avalonia.Xaml.Interactivity": "0.10.10.4", - "FluentAvaloniaUI": "1.1.6", + "FluentAvaloniaUI": "1.1.7", "Material.Icons.Avalonia": "1.0.2", "ReactiveUI.Validation": "2.2.1" } diff --git a/src/Avalonia/Artemis.UI.MacOS/packages.lock.json b/src/Avalonia/Artemis.UI.MacOS/packages.lock.json index 4571535af..e9d390ff7 100644 --- a/src/Avalonia/Artemis.UI.MacOS/packages.lock.json +++ b/src/Avalonia/Artemis.UI.MacOS/packages.lock.json @@ -210,8 +210,8 @@ }, "FluentAvaloniaUI": { "type": "Transitive", - "resolved": "1.1.6", - "contentHash": "EJukyiTmEVhaYlHdntFMyQKI4+u772rSClKYQqJRfkTb1NoJXLqiIVqMjx8ZQ0pxnfih+6CZ7+x82lfrGHIPUw==", + "resolved": "1.1.7", + "contentHash": "Hco3+M09A7rDknaYu5CcyGhUOqGj5mebrFzjZVGjW5YBYiMiV+x0vl2Fn6oIfXxhKgg1i70tTwQCtW/1GWFJeA==", "dependencies": { "Avalonia": "0.10.10", "Avalonia.Desktop": "0.10.10", @@ -688,16 +688,16 @@ }, "Splat": { "type": "Transitive", - "resolved": "13.1.63", - "contentHash": "7iW45RA7AbSlQPCgdokmysva5PGd6iBUhuNkC0XD73LF9dxfTkKeo3wZkohU7nvspDhJ7PJsYHvDtxIt5bMQ8Q==" + "resolved": "14.1.1", + "contentHash": "bKQtKu57w+iJ1T+WDyDdNq+LBNVdmNu2i0vGNyUdtmg4TEIEFiX2GfPusNEAW2QOfxyDE7i4+xTxbOKZr/4jhg==" }, "Splat.Ninject": { "type": "Transitive", - "resolved": "13.1.63", - "contentHash": "rTF0HSa6p8nxrXj2hwVgkutcTDJUXY34sY+zYK4ky65b7a0ROL8kdiYyxVVLE4Lq31N5Rcd4bBbqlPkgwZguww==", + "resolved": "14.1.1", + "contentHash": "lmhjY5yRKL6SgkwY0kEtnHI8JERYhRwFiOk+NgvOUtGYzVm/RRm1OrgrN+kPKzmuvsUrodx6FYTHrSkHL2I8Yg==", "dependencies": { "Ninject": "3.3.4", - "Splat": "13.1.63" + "Splat": "14.1.1" } }, "Svg.Custom": { @@ -1691,12 +1691,12 @@ "Avalonia.Diagnostics": "0.10.10", "Avalonia.ReactiveUI": "0.10.10", "Avalonia.Svg.Skia": "0.10.10", - "FluentAvaloniaUI": "1.1.6", + "FluentAvaloniaUI": "1.1.7", "Flurl.Http": "3.2.0", "Live.Avalonia": "1.3.1", "Material.Icons.Avalonia": "1.0.2", "ReactiveUI.Validation": "2.2.1", - "Splat.Ninject": "13.1.63" + "Splat.Ninject": "14.1.1" } }, "artemis.ui.shared": { @@ -1709,7 +1709,7 @@ "Avalonia.Xaml.Behaviors": "0.10.10.4", "Avalonia.Xaml.Interactions": "0.10.10.4", "Avalonia.Xaml.Interactivity": "0.10.10.4", - "FluentAvaloniaUI": "1.1.6", + "FluentAvaloniaUI": "1.1.7", "Material.Icons.Avalonia": "1.0.2", "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 180b48704..63cb328e3 100644 --- a/src/Avalonia/Artemis.UI.Shared/Artemis.UI.Shared.csproj +++ b/src/Avalonia/Artemis.UI.Shared/Artemis.UI.Shared.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Avalonia/Artemis.UI.Shared/Styles/Artemis.axaml b/src/Avalonia/Artemis.UI.Shared/Styles/Artemis.axaml index f9f0aaa72..5bcd365a3 100644 --- a/src/Avalonia/Artemis.UI.Shared/Styles/Artemis.axaml +++ b/src/Avalonia/Artemis.UI.Shared/Styles/Artemis.axaml @@ -27,4 +27,16 @@ + + + + + diff --git a/src/Avalonia/Artemis.UI.Shared/Styles/TreeView.axaml b/src/Avalonia/Artemis.UI.Shared/Styles/TreeView.axaml new file mode 100644 index 000000000..df6fa92d6 --- /dev/null +++ b/src/Avalonia/Artemis.UI.Shared/Styles/TreeView.axaml @@ -0,0 +1,99 @@ + + + + + + + + Test + + + + + + + + + Test + + + + + + + + + Test + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Avalonia/Artemis.UI.Shared/packages.lock.json b/src/Avalonia/Artemis.UI.Shared/packages.lock.json index df39f637e..702356de1 100644 --- a/src/Avalonia/Artemis.UI.Shared/packages.lock.json +++ b/src/Avalonia/Artemis.UI.Shared/packages.lock.json @@ -72,9 +72,9 @@ }, "FluentAvaloniaUI": { "type": "Direct", - "requested": "[1.1.6, )", - "resolved": "1.1.6", - "contentHash": "EJukyiTmEVhaYlHdntFMyQKI4+u772rSClKYQqJRfkTb1NoJXLqiIVqMjx8ZQ0pxnfih+6CZ7+x82lfrGHIPUw==", + "requested": "[1.1.7, )", + "resolved": "1.1.7", + "contentHash": "Hco3+M09A7rDknaYu5CcyGhUOqGj5mebrFzjZVGjW5YBYiMiV+x0vl2Fn6oIfXxhKgg1i70tTwQCtW/1GWFJeA==", "dependencies": { "Avalonia": "0.10.10", "Avalonia.Desktop": "0.10.10", diff --git a/src/Avalonia/Artemis.UI.Windows/packages.lock.json b/src/Avalonia/Artemis.UI.Windows/packages.lock.json index c2d37b9eb..8ac82b3ba 100644 --- a/src/Avalonia/Artemis.UI.Windows/packages.lock.json +++ b/src/Avalonia/Artemis.UI.Windows/packages.lock.json @@ -226,8 +226,8 @@ }, "FluentAvaloniaUI": { "type": "Transitive", - "resolved": "1.1.6", - "contentHash": "EJukyiTmEVhaYlHdntFMyQKI4+u772rSClKYQqJRfkTb1NoJXLqiIVqMjx8ZQ0pxnfih+6CZ7+x82lfrGHIPUw==", + "resolved": "1.1.7", + "contentHash": "Hco3+M09A7rDknaYu5CcyGhUOqGj5mebrFzjZVGjW5YBYiMiV+x0vl2Fn6oIfXxhKgg1i70tTwQCtW/1GWFJeA==", "dependencies": { "Avalonia": "0.10.10", "Avalonia.Desktop": "0.10.10", @@ -704,16 +704,16 @@ }, "Splat": { "type": "Transitive", - "resolved": "13.1.63", - "contentHash": "7iW45RA7AbSlQPCgdokmysva5PGd6iBUhuNkC0XD73LF9dxfTkKeo3wZkohU7nvspDhJ7PJsYHvDtxIt5bMQ8Q==" + "resolved": "14.1.1", + "contentHash": "bKQtKu57w+iJ1T+WDyDdNq+LBNVdmNu2i0vGNyUdtmg4TEIEFiX2GfPusNEAW2QOfxyDE7i4+xTxbOKZr/4jhg==" }, "Splat.Ninject": { "type": "Transitive", - "resolved": "13.1.63", - "contentHash": "rTF0HSa6p8nxrXj2hwVgkutcTDJUXY34sY+zYK4ky65b7a0ROL8kdiYyxVVLE4Lq31N5Rcd4bBbqlPkgwZguww==", + "resolved": "14.1.1", + "contentHash": "lmhjY5yRKL6SgkwY0kEtnHI8JERYhRwFiOk+NgvOUtGYzVm/RRm1OrgrN+kPKzmuvsUrodx6FYTHrSkHL2I8Yg==", "dependencies": { "Ninject": "3.3.4", - "Splat": "13.1.63" + "Splat": "14.1.1" } }, "Svg.Custom": { @@ -1707,12 +1707,12 @@ "Avalonia.Diagnostics": "0.10.10", "Avalonia.ReactiveUI": "0.10.10", "Avalonia.Svg.Skia": "0.10.10", - "FluentAvaloniaUI": "1.1.6", + "FluentAvaloniaUI": "1.1.7", "Flurl.Http": "3.2.0", "Live.Avalonia": "1.3.1", "Material.Icons.Avalonia": "1.0.2", "ReactiveUI.Validation": "2.2.1", - "Splat.Ninject": "13.1.63" + "Splat.Ninject": "14.1.1" } }, "artemis.ui.shared": { @@ -1725,7 +1725,7 @@ "Avalonia.Xaml.Behaviors": "0.10.10.4", "Avalonia.Xaml.Interactions": "0.10.10.4", "Avalonia.Xaml.Interactivity": "0.10.10.4", - "FluentAvaloniaUI": "1.1.6", + "FluentAvaloniaUI": "1.1.7", "Material.Icons.Avalonia": "1.0.2", "ReactiveUI.Validation": "2.2.1" } diff --git a/src/Avalonia/Artemis.UI/Artemis.UI.csproj b/src/Avalonia/Artemis.UI/Artemis.UI.csproj index c8d210bf0..8f59f87df 100644 --- a/src/Avalonia/Artemis.UI/Artemis.UI.csproj +++ b/src/Avalonia/Artemis.UI/Artemis.UI.csproj @@ -19,12 +19,12 @@ - + - + @@ -58,4 +58,7 @@ ProfileConfigurationEditView.axaml + + + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Artemis.UI.csproj.DotSettings b/src/Avalonia/Artemis.UI/Artemis.UI.csproj.DotSettings index 9bdec1f7b..f3b6b6826 100644 --- a/src/Avalonia/Artemis.UI/Artemis.UI.csproj.DotSettings +++ b/src/Avalonia/Artemis.UI/Artemis.UI.csproj.DotSettings @@ -4,6 +4,7 @@ True True True + True True True True \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/MainWindow.axaml b/src/Avalonia/Artemis.UI/MainWindow.axaml index 2a507bddd..a3470a84d 100644 --- a/src/Avalonia/Artemis.UI/MainWindow.axaml +++ b/src/Avalonia/Artemis.UI/MainWindow.axaml @@ -1,13 +1,22 @@ - - + + + + Test + + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/MainWindow.axaml.cs b/src/Avalonia/Artemis.UI/MainWindow.axaml.cs index ad4cf0110..f1e173403 100644 --- a/src/Avalonia/Artemis.UI/MainWindow.axaml.cs +++ b/src/Avalonia/Artemis.UI/MainWindow.axaml.cs @@ -1,20 +1,30 @@ using Artemis.UI.Screens.Root; using Avalonia; +using Avalonia.Controls; using Avalonia.Markup.Xaml; using Avalonia.ReactiveUI; +using FluentAvalonia.Core.ApplicationModel; namespace Artemis.UI { - public class MainWindow : ReactiveWindow + public class MainWindow : ReactiveCoreWindow { public MainWindow() { InitializeComponent(); + SetupTitlebar(); #if DEBUG this.AttachDevTools(); #endif } + private void SetupTitlebar() + { + object? titleBar = this.FindResource("RootWindowTitlebar"); + if (titleBar != null) + SetTitleBar((IControl) titleBar); + } + private void InitializeComponent() { AvaloniaXamlLoader.Load(this); diff --git a/src/Avalonia/Artemis.UI/Ninject/Factories/IVMFactory.cs b/src/Avalonia/Artemis.UI/Ninject/Factories/IVMFactory.cs index bd173bd57..7285e9802 100644 --- a/src/Avalonia/Artemis.UI/Ninject/Factories/IVMFactory.cs +++ b/src/Avalonia/Artemis.UI/Ninject/Factories/IVMFactory.cs @@ -3,6 +3,7 @@ using Artemis.Core; using Artemis.UI.Screens.Device; using Artemis.UI.Screens.Plugins; using Artemis.UI.Screens.ProfileEditor; +using Artemis.UI.Screens.ProfileEditor.ProfileTree; using Artemis.UI.Screens.Settings; using Artemis.UI.Screens.Sidebar; using Artemis.UI.Screens.SurfaceEditor; @@ -54,5 +55,7 @@ namespace Artemis.UI.Ninject.Factories public interface IProfileEditorVmFactory : IVmFactory { ProfileEditorViewModel ProfileEditorViewModel(IScreen hostScreen); + FolderTreeItemViewModel FolderTreeItemViewModel(Folder folder); + LayerTreeItemViewModel LayerTreeItemViewModel(Layer layer); } } \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/ReactiveCoreWindow.cs b/src/Avalonia/Artemis.UI/ReactiveCoreWindow.cs new file mode 100644 index 000000000..5e5a8eb67 --- /dev/null +++ b/src/Avalonia/Artemis.UI/ReactiveCoreWindow.cs @@ -0,0 +1,80 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.LogicalTree; +using FluentAvalonia.Interop; +using FluentAvalonia.UI.Controls; +using ReactiveUI; + +namespace Artemis.UI +{ + /// + /// A ReactiveUI that implements the interface and will + /// activate your ViewModel automatically if the view model implements . When + /// the DataContext property changes, this class will update the ViewModel property with the new DataContext value, + /// and vice versa. + /// + /// ViewModel type. + public class ReactiveCoreWindow : CoreWindow, IViewFor where TViewModel : class + { + public static readonly StyledProperty ViewModelProperty = AvaloniaProperty + .Register, TViewModel?>(nameof(ViewModel)); + + /// + /// Initializes a new instance of the class. + /// + public ReactiveCoreWindow() + { + // This WhenActivated block calls ViewModel's WhenActivated + // block if the ViewModel implements IActivatableViewModel. + this.WhenActivated(disposables => { }); + this.GetObservable(DataContextProperty).Subscribe(OnDataContextChanged); + this.GetObservable(ViewModelProperty).Subscribe(OnViewModelChanged); + + // TODO Remove + Win32Interop.OSVERSIONINFOEX version = default; + Win32Interop.RtlGetVersion(ref version); + if (version.MajorVersion == 10) + PseudoClasses.Add(":windows10"); + } + + /// + /// The ViewModel. + /// + public TViewModel? ViewModel + { + get => GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } + + object? IViewFor.ViewModel + { + get => ViewModel; + set => ViewModel = (TViewModel?)value; + } + + private void OnDataContextChanged(object? value) + { + if (value is TViewModel viewModel) + { + ViewModel = viewModel; + } + else + { + ViewModel = null; + } + } + + private void OnViewModelChanged(object? value) + { + if (value == null) + { + ClearValue(DataContextProperty); + } + else if (DataContext != value) + { + DataContext = value; + } + } + } +} diff --git a/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml b/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml index 4cb14d0c0..6c7eff869 100644 --- a/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml +++ b/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml @@ -1,4 +1,4 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml.cs index 5d4428442..0709047e5 100644 --- a/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml.cs +++ b/src/Avalonia/Artemis.UI/Screens/Debugger/DebugView.axaml.cs @@ -12,7 +12,7 @@ using ReactiveUI; namespace Artemis.UI.Screens.Debugger { - public class DebugView : ReactiveWindow + public class DebugView : ReactiveCoreWindow { public DebugView() { diff --git a/src/Avalonia/Artemis.UI/Screens/Device/DevicePropertiesView.axaml b/src/Avalonia/Artemis.UI/Screens/Device/DevicePropertiesView.axaml index 861a997aa..96cdfc9b7 100644 --- a/src/Avalonia/Artemis.UI/Screens/Device/DevicePropertiesView.axaml +++ b/src/Avalonia/Artemis.UI/Screens/Device/DevicePropertiesView.axaml @@ -1,8 +1,9 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/Device/DevicePropertiesView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/Device/DevicePropertiesView.axaml.cs index d525d7c7f..b5fd26391 100644 --- a/src/Avalonia/Artemis.UI/Screens/Device/DevicePropertiesView.axaml.cs +++ b/src/Avalonia/Artemis.UI/Screens/Device/DevicePropertiesView.axaml.cs @@ -4,7 +4,7 @@ using Avalonia.ReactiveUI; namespace Artemis.UI.Screens.Device { - public partial class DevicePropertiesView : ReactiveWindow + public partial class DevicePropertiesView : ReactiveCoreWindow { public DevicePropertiesView() { diff --git a/src/Avalonia/Artemis.UI/Screens/Plugins/PluginSettingsWindowView.axaml b/src/Avalonia/Artemis.UI/Screens/Plugins/PluginSettingsWindowView.axaml index 30caafb04..988cb4734 100644 --- a/src/Avalonia/Artemis.UI/Screens/Plugins/PluginSettingsWindowView.axaml +++ b/src/Avalonia/Artemis.UI/Screens/Plugins/PluginSettingsWindowView.axaml @@ -1,7 +1,8 @@ - - + diff --git a/src/Avalonia/Artemis.UI/Screens/Plugins/PluginSettingsWindowView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/Plugins/PluginSettingsWindowView.axaml.cs index 67a67d977..5828b0d0b 100644 --- a/src/Avalonia/Artemis.UI/Screens/Plugins/PluginSettingsWindowView.axaml.cs +++ b/src/Avalonia/Artemis.UI/Screens/Plugins/PluginSettingsWindowView.axaml.cs @@ -8,7 +8,7 @@ using ReactiveUI; namespace Artemis.UI.Screens.Plugins { - public class PluginSettingsWindowView : ReactiveWindow + public class PluginSettingsWindowView : ReactiveCoreWindow { public PluginSettingsWindowView() { diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml new file mode 100644 index 000000000..bf7ae3c80 --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml @@ -0,0 +1,36 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml.cs new file mode 100644 index 000000000..cbd0ff111 --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemView.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree +{ + public partial class FolderTreeItemView : UserControl + { + public FolderTreeItemView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemViewModel.cs new file mode 100644 index 000000000..ae0f11a59 --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/FolderTreeItemViewModel.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using Artemis.Core; +using Artemis.UI.Ninject.Factories; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree +{ + public class FolderTreeItemViewModel : TreeItemViewModel + { + public Folder Folder { get; } + + public FolderTreeItemViewModel(Folder folder, IProfileEditorVmFactory profileEditorVmFactory) + { + Folder = folder; + Children = new List(); + + foreach (ProfileElement profileElement in folder.Children) + { + if (profileElement is Folder childFolder) + Children.Add(profileEditorVmFactory.FolderTreeItemViewModel(childFolder)); + else if (profileElement is Layer layer) + Children.Add(profileEditorVmFactory.LayerTreeItemViewModel(layer)); + } + } + + public List Children { get; } + } +} \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml new file mode 100644 index 000000000..5b360cb54 --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml @@ -0,0 +1,29 @@ + + + + + + + + + + diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml.cs new file mode 100644 index 000000000..362581616 --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemView.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree +{ + public partial class LayerTreeItemView : UserControl + { + public LayerTreeItemView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemViewModel.cs new file mode 100644 index 000000000..e38f373d2 --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/LayerTreeItemViewModel.cs @@ -0,0 +1,14 @@ +using Artemis.Core; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree +{ + public class LayerTreeItemViewModel : TreeItemViewModel + { + public Layer Layer { get; } + + public LayerTreeItemViewModel(Layer layer) + { + Layer = layer; + } + } +} diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml new file mode 100644 index 000000000..51a3df5ff --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml.cs new file mode 100644 index 000000000..8f74e4ba7 --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree +{ + public partial class ProfileTreeView : ReactiveUserControl + { + public ProfileTreeView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs new file mode 100644 index 000000000..1d1ddb99e --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reactive.Disposables; +using Artemis.Core; +using Artemis.UI.Ninject.Factories; +using Artemis.UI.Services; +using Artemis.UI.Shared; +using ReactiveUI; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree +{ + public class ProfileTreeViewModel : ActivatableViewModelBase + { + private readonly IProfileEditorVmFactory _profileEditorVmFactory; + + public ProfileTreeViewModel(IProfileEditorService profileEditorService, IProfileEditorVmFactory profileEditorVmFactory) + { + _profileEditorVmFactory = profileEditorVmFactory; + this.WhenActivated(d => profileEditorService.CurrentProfileConfiguration.WhereNotNull().Subscribe(Repopulate).DisposeWith(d)); + } + + public ObservableCollection TreeItems { get; } = new(); + + private void Repopulate(ProfileConfiguration profileConfiguration) + { + if (TreeItems.Any()) + TreeItems.Clear(); + + if (profileConfiguration.Profile == null) + return; + + foreach (ProfileElement profileElement in profileConfiguration.Profile.GetRootFolder().Children) + { + if (profileElement is Folder folder) + TreeItems.Add(_profileEditorVmFactory.FolderTreeItemViewModel(folder)); + else if (profileElement is Layer layer) + TreeItems.Add(_profileEditorVmFactory.LayerTreeItemViewModel(layer)); + } + + } + } +} diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs new file mode 100644 index 000000000..28397234e --- /dev/null +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/TreeItemViewModel.cs @@ -0,0 +1,8 @@ +using Artemis.UI.Shared; + +namespace Artemis.UI.Screens.ProfileEditor.ProfileTree +{ + public abstract class TreeItemViewModel : ActivatableViewModelBase + { + } +} \ 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 5c38fd817..a64869c3d 100644 --- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.axaml +++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.axaml @@ -253,7 +253,7 @@ - Profile elements + diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs index 73cd9f3f1..da3b0978b 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.ProfileTree; using Artemis.UI.Screens.ProfileEditor.VisualEditor; using Artemis.UI.Services; using ReactiveUI; @@ -12,13 +13,16 @@ namespace Artemis.UI.Screens.ProfileEditor private ProfileConfiguration? _profile; /// - public ProfileEditorViewModel(IScreen hostScreen, VisualEditorViewModel visualEditorViewModel, IProfileEditorService profileEditorService) : base(hostScreen, "profile-editor") + public ProfileEditorViewModel(IScreen hostScreen, IProfileEditorService profileEditorService, VisualEditorViewModel visualEditorViewModel, ProfileTreeViewModel profileTreeViewModel) + : base(hostScreen, "profile-editor") { VisualEditorViewModel = visualEditorViewModel; + ProfileTreeViewModel = profileTreeViewModel; this.WhenActivated(disposables => { profileEditorService.CurrentProfileConfiguration.WhereNotNull().Subscribe(p => Profile = p).DisposeWith(disposables); }); } public VisualEditorViewModel VisualEditorViewModel { get; } + public ProfileTreeViewModel ProfileTreeViewModel { get; } public ProfileConfiguration? Profile { diff --git a/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml b/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml index 6280b0825..eca9aa119 100644 --- a/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml +++ b/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml @@ -1,4 +1,4 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml.cs b/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml.cs index ce905a533..cb31ee232 100644 --- a/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml.cs +++ b/src/Avalonia/Artemis.UI/Screens/Sidebar/Dialogs/ProfileConfigurationEditView.axaml.cs @@ -4,7 +4,7 @@ using Avalonia.ReactiveUI; namespace Artemis.UI.Screens.Sidebar { - public partial class ProfileConfigurationEditView : ReactiveWindow + public partial class ProfileConfigurationEditView : ReactiveCoreWindow { public ProfileConfigurationEditView() { diff --git a/src/Avalonia/Artemis.UI/Styles/Artemis.axaml b/src/Avalonia/Artemis.UI/Styles/Artemis.axaml index 7c51cbf0f..de19a9df5 100644 --- a/src/Avalonia/Artemis.UI/Styles/Artemis.axaml +++ b/src/Avalonia/Artemis.UI/Styles/Artemis.axaml @@ -10,6 +10,7 @@ + \ No newline at end of file diff --git a/src/Avalonia/Artemis.UI/packages.lock.json b/src/Avalonia/Artemis.UI/packages.lock.json index fed744e4f..627d2a480 100644 --- a/src/Avalonia/Artemis.UI/packages.lock.json +++ b/src/Avalonia/Artemis.UI/packages.lock.json @@ -76,9 +76,9 @@ }, "FluentAvaloniaUI": { "type": "Direct", - "requested": "[1.1.6, )", - "resolved": "1.1.6", - "contentHash": "EJukyiTmEVhaYlHdntFMyQKI4+u772rSClKYQqJRfkTb1NoJXLqiIVqMjx8ZQ0pxnfih+6CZ7+x82lfrGHIPUw==", + "requested": "[1.1.7, )", + "resolved": "1.1.7", + "contentHash": "Hco3+M09A7rDknaYu5CcyGhUOqGj5mebrFzjZVGjW5YBYiMiV+x0vl2Fn6oIfXxhKgg1i70tTwQCtW/1GWFJeA==", "dependencies": { "Avalonia": "0.10.10", "Avalonia.Desktop": "0.10.10", @@ -126,12 +126,12 @@ }, "Splat.Ninject": { "type": "Direct", - "requested": "[13.1.63, )", - "resolved": "13.1.63", - "contentHash": "rTF0HSa6p8nxrXj2hwVgkutcTDJUXY34sY+zYK4ky65b7a0ROL8kdiYyxVVLE4Lq31N5Rcd4bBbqlPkgwZguww==", + "requested": "[14.1.1, )", + "resolved": "14.1.1", + "contentHash": "lmhjY5yRKL6SgkwY0kEtnHI8JERYhRwFiOk+NgvOUtGYzVm/RRm1OrgrN+kPKzmuvsUrodx6FYTHrSkHL2I8Yg==", "dependencies": { "Ninject": "3.3.4", - "Splat": "13.1.63" + "Splat": "14.1.1" } }, "Avalonia.Angle.Windows.Natives": { @@ -705,8 +705,8 @@ }, "Splat": { "type": "Transitive", - "resolved": "13.1.63", - "contentHash": "7iW45RA7AbSlQPCgdokmysva5PGd6iBUhuNkC0XD73LF9dxfTkKeo3wZkohU7nvspDhJ7PJsYHvDtxIt5bMQ8Q==" + "resolved": "14.1.1", + "contentHash": "bKQtKu57w+iJ1T+WDyDdNq+LBNVdmNu2i0vGNyUdtmg4TEIEFiX2GfPusNEAW2QOfxyDE7i4+xTxbOKZr/4jhg==" }, "Svg.Custom": { "type": "Transitive", @@ -1698,7 +1698,7 @@ "Avalonia.Xaml.Behaviors": "0.10.10.4", "Avalonia.Xaml.Interactions": "0.10.10.4", "Avalonia.Xaml.Interactivity": "0.10.10.4", - "FluentAvaloniaUI": "1.1.6", + "FluentAvaloniaUI": "1.1.7", "Material.Icons.Avalonia": "1.0.2", "ReactiveUI.Validation": "2.2.1" }