1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Updated ReactiveUI

Added order to render element ctors
This commit is contained in:
Robert 2021-12-30 23:33:26 +01:00
parent 6569558df4
commit 34757716aa
46 changed files with 838 additions and 370 deletions

View File

@ -22,7 +22,8 @@ namespace Artemis.Core
/// </summary>
/// <param name="parent">The parent of the folder</param>
/// <param name="name">The name of the folder</param>
public Folder(ProfileElement parent, string name) : base(parent.Profile)
/// <param name="order">The order where to place the child (0-based), defaults to the end of the collection</param>
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);
}
/// <summary>

View File

@ -29,7 +29,8 @@ namespace Artemis.Core
/// </summary>
/// <param name="parent">The parent of the layer</param>
/// <param name="name">The name of the layer</param>
public Layer(ProfileElement parent, string name) : base(parent.Profile)
/// <param name="order">The order where to place the child (0-based), defaults to the end of the collection</param>
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);
}
/// <summary>

View File

@ -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
{

View File

@ -44,6 +44,9 @@ namespace Artemis.Core
/// <param name="extraArgs">A list of extra arguments to pass to Artemis when restarting</param>
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()));
}

View File

@ -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();

View File

@ -14,6 +14,7 @@
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.11" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.11" />
<PackageReference Include="ReactiveUI" Version="17.1.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Artemis.Core\Artemis.Core.csproj" />

View File

@ -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"
}
}

View File

@ -14,6 +14,7 @@
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="0.10.11" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.11" />
<PackageReference Include="ReactiveUI" Version="17.1.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Artemis.Core\Artemis.Core.csproj" />

View File

@ -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"
}
}

View File

@ -24,6 +24,7 @@
<PackageReference Include="Avalonia.Xaml.Interactivity" Version="0.10.11.5" />
<PackageReference Include="FluentAvaloniaUI" Version="1.1.8" />
<PackageReference Include="Material.Icons.Avalonia" Version="1.0.2" />
<PackageReference Include="ReactiveUI" Version="17.1.9" />
<PackageReference Include="ReactiveUI.Validation" Version="2.2.1" />
<PackageReference Include="RGB.NET.Core" Version="1.0.0-prerelease1" />
</ItemGroup>

View File

@ -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};
}
}

View File

@ -27,6 +27,10 @@
<Setter Property="ClipToBounds" Value="True" />
</Style>
<Style Selector="Window:windows Border.router-container">
<Setter Property="Margin" Value="0 31 0 0"></Setter>
</Style>
<Style Selector="Border.card">
<Setter Property="Padding" Value="25" />
<Setter Property="Background" Value="{DynamicResource ControlFillColorDefaultBrush}" />

View File

@ -10,6 +10,9 @@
<Button Classes="icon-button">
<avalonia:MaterialIcon Kind="Cog" />
</Button>
<Button Classes="icon-button" IsEnabled="False">
<avalonia:MaterialIcon Kind="Cog" />
</Button>
<TextBlock Margin="0 5 0 0">Button.icon-button icon-button-small</TextBlock>
<Button Classes="icon-button icon-button-small">
@ -40,9 +43,18 @@
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="5.5" />
</Style>
<Style Selector=":is(Button).icon-button:pointerover /template/ Border#BorderElement">
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
<Style Selector=":is(Button).icon-button:disabled /template/ Border#BorderElement">
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
<Style Selector=":is(Button).icon-button[IsEnabled=False] /template/ Border#BorderElement">
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
<Style Selector=":is(Button).icon-button-small">
<Setter Property="Padding" Value="2" />
<Setter Property="Padding" Value="4" />
</Style>
<Style Selector=":is(Button).icon-button-small avalonia|MaterialIcon">
<Setter Property="Width" Value="14" />

View File

@ -91,6 +91,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, )",
@ -221,8 +235,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"
}
@ -510,15 +524,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.Layout": {
"type": "Transitive",
"resolved": "1.0.0-prerelease1",
@ -720,8 +725,8 @@
},
"Splat": {
"type": "Transitive",
"resolved": "13.1.1",
"contentHash": "Hv41NNJwYEoxjpCrUw0BdzN17YLZrduhrnHgJyXatSgT6Dq/N/viVkPLfohCeoXf7MqA6ppB/AxtUGU3vJ7YEA=="
"resolved": "14.1.1",
"contentHash": "bKQtKu57w+iJ1T+WDyDdNq+LBNVdmNu2i0vGNyUdtmg4TEIEFiX2GfPusNEAW2QOfxyDE7i4+xTxbOKZr/4jhg=="
},
"Svg.Custom": {
"type": "Transitive",
@ -884,6 +889,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",
@ -1364,6 +1377,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",

View File

@ -7,6 +7,7 @@ using System.Net.Http;
using System.Security.Principal;
using System.Threading;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared.Services.Interfaces;
using Artemis.UI.Windows.Utilities;
using Avalonia;
@ -41,6 +42,9 @@ namespace Artemis.UI.Windows
kernel.Dispose();
};
}
// Inform the Core about elevation status
kernel.Get<ICoreService>().IsElevated = IsElevated;
}
public string[] StartupArguments { get; }

View File

@ -17,6 +17,7 @@
<PackageReference Include="Avalonia.Win32" Version="0.10.11" />
<PackageReference Include="Microsoft.Win32" Version="2.0.1" />
<PackageReference Include="RawInput.Sharp" Version="0.0.4" />
<PackageReference Include="ReactiveUI" Version="17.1.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Artemis.Core\Artemis.Core.csproj" />

View File

@ -80,6 +80,20 @@
"NETStandard.Library": "1.6.1"
}
},
"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",
@ -207,8 +221,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"
}
@ -538,15 +552,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",
@ -934,6 +939,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",
@ -1414,6 +1427,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",
@ -1773,6 +1795,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"
}
@ -1790,6 +1813,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"
}
}

View File

@ -23,6 +23,7 @@
<PackageReference Include="Flurl.Http" Version="3.2.0" />
<PackageReference Include="Live.Avalonia" Version="1.3.1" />
<PackageReference Include="Material.Icons.Avalonia" Version="1.0.2" />
<PackageReference Include="ReactiveUI" Version="17.1.9" />
<PackageReference Include="ReactiveUI.Validation" Version="2.2.1" />
<PackageReference Include="RGB.NET.Core" Version="1.0.0-prerelease1" />
<PackageReference Include="RGB.NET.Layout" Version="1.0.0-prerelease1" />
@ -58,4 +59,9 @@
<ItemGroup>
<Folder Include="Screens\ProfileEditor\Tools\" />
</ItemGroup>
<ItemGroup>
<Reference Include="HistoricalReactiveCommand">
<HintPath>..\..\..\..\HistoricalReactiveCommand\HistoricalReactiveCommand\bin\Debug\netstandard2.1\HistoricalReactiveCommand.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -7,16 +7,12 @@
x:Class="Artemis.UI.MainWindow"
Icon="/Assets/Images/Logo/bow.ico"
Title="Artemis 2.0">
<controls:CoreWindow.Resources>
<ResourceDictionary>
<Panel x:Key="RootWindowTitlebar" Height="31" HorizontalAlignment="Stretch" Background="Red">
<TextBlock>Test</TextBlock>
</Panel>
</ResourceDictionary>
</controls:CoreWindow.Resources>
<!-- Use a panel here so the main window can host ContentDialogs -->
<Panel>
<ContentControl Content="{Binding}" />
<Border Background="Transparent" x:Name="TitleBar" VerticalAlignment="Top" MinHeight="31" >
<ContentControl Content="{Binding TitleBarViewModel}" Margin="240 0 150 0"/>
</Border>
</Panel>
</controls:CoreWindow>

View File

@ -1,6 +1,8 @@
using Artemis.UI.Screens.Root;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using FluentAvalonia.Core.ApplicationModel;
@ -20,9 +22,13 @@ namespace Artemis.UI
private void SetupTitlebar()
{
//object? titleBar = this.FindResource("RootWindowTitlebar");
//if (titleBar != null)
// SetTitleBar((IControl) titleBar);
ICoreApplicationView coreAppTitleBar = this;
if (coreAppTitleBar.TitleBar != null)
{
coreAppTitleBar.TitleBar.ExtendViewIntoTitleBar = true;
SetTitleBar(this.Get<Border>("TitleBar"));
}
}
private void InitializeComponent()

View File

@ -55,7 +55,7 @@ namespace Artemis.UI.Ninject.Factories
public interface IProfileEditorVmFactory : IVmFactory
{
ProfileEditorViewModel ProfileEditorViewModel(IScreen hostScreen);
FolderTreeItemViewModel FolderTreeItemViewModel(Folder folder);
LayerTreeItemViewModel LayerTreeItemViewModel(Layer layer);
FolderTreeItemViewModel FolderTreeItemViewModel(TreeItemViewModel? parent, Folder folder);
LayerTreeItemViewModel LayerTreeItemViewModel(TreeItemViewModel? parent, Layer layer);
}
}

View File

@ -1,8 +1,6 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.LogicalTree;
using FluentAvalonia.Interop;
using FluentAvalonia.UI.Controls;
using ReactiveUI;
@ -30,12 +28,21 @@ namespace Artemis.UI
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");
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;
}
/// <summary>
@ -52,29 +59,5 @@ namespace Artemis.UI
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;
}
}
}
}

View File

@ -16,5 +16,7 @@ namespace Artemis.UI.Screens
/// <inheritdoc />
public IScreen HostScreen { get; }
public ViewModelBase? TitleBarViewModel { get; protected set; }
}
}

View File

@ -7,6 +7,8 @@ using Artemis.Core.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.Interfaces;
using Avalonia;
using Avalonia.Threading;
using ReactiveUI;
namespace Artemis.UI.Screens.Plugins
@ -56,7 +58,7 @@ namespace Artemis.UI.Screens.Plugins
public bool IsEnabled
{
get => FeatureInfo.Instance != null && FeatureInfo.Instance.IsEnabled;
set => Task.Run(() => UpdateEnabled(value));
set => Dispatcher.UIThread.InvokeAsync(() => UpdateEnabled(value));
}
public bool CanToggleEnabled => FeatureInfo.Plugin.IsEnabled && !FeatureInfo.AlwaysEnabled;
@ -159,7 +161,7 @@ namespace Artemis.UI.Screens.Plugins
}
}
await Task.Run(() => _pluginManagementService.EnablePluginFeature(FeatureInfo.Instance!, true));
await Dispatcher.UIThread.InvokeAsync(() => _pluginManagementService.EnablePluginFeature(FeatureInfo.Instance!, true));
}
catch (Exception e)
{

View File

@ -0,0 +1,198 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.Panels.MenuBar.MenuBarView">
<Menu Grid.Row="0" Grid.Column="0" Margin="0 2" VerticalAlignment="Top">
<MenuItem Header="_File">
<MenuItem Header="New">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Plus" />
</MenuItem.Icon>
<MenuItem Header="Folder" Command="{Binding AddFolder}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Folder" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Layer" Command="{Binding AddLayer}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Layers" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<Separator />
<MenuItem Header="View Properties" Command="{Binding ViewProperties}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Settings" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_View Scripts" Command="{Binding ViewScripts}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="BookEdit" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Adapt Profile" Command="{Binding AdaptProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Magic" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Suspend Profile">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding ProfileConfiguration.IsSuspended}" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Export Profile" Command="{Binding ExportProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Export" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Duplicate Profile" Command="{Binding DuplicateProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentDuplicate" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Delete Profile" Command="{Binding DeleteProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Trash" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Edit" SubmenuOpened="MenuItem_OnSubmenuOpened">
<MenuItem Header="_Duplicate"
Command="{Binding Duplicate}"
HotKey="Ctrl+D"
IsEnabled="{Binding HasSelectedElement}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentDuplicate" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Copy"
Command="{Binding Copy}"
HotKey="Ctrl+C"
IsEnabled="{Binding HasSelectedElement}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentCopy" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Paste"
Command="{Binding Paste}"
HotKey="Ctrl+V">
<MenuItem.Icon>
<avalonia:MaterialIconExt Kind="ContentPaste" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Run">
<MenuItem Header="_Switch run mode"
Command="{Binding ToggleSuspend}"
HotKey="F5">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="SwapHorizontal" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Run Profile on Focus Loss"
ToolTip.Tip="If enabled, run mode is set to normal on focus loss"
HotKey="Shift+F5">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding StopOnFocusLoss.Value}" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Options">
<MenuItem Header="Focus Selected Layer"
ToolTip.Tip="If enabled, displays only the layer you currently have selected"
IsEnabled="False">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding FocusSelectedLayer.Value}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Display Data Model Values">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding ShowDataModelValues.Value}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Display Full Condition Paths">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding ShowFullPaths.Value}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Always Display Cable Values" ToolTip.Tip="If enabled, cable values are always shown instead of only on hover">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding AlwaysShowValues.Value}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Apply All Data Bindings During Edit" ToolTip.Tip="If enabled, updates all data bindings instead of only the one you are editing">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding AlwaysApplyDataBindings.Value}" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="Artemis Wiki" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="BookEdit" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Editor" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/profiles">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Edit" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Layers" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/layers">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Layers" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Display Conditions" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/conditions">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="NotEqual" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Timeline" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/timeline">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Stopwatch" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Data Bindings" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/data-bindings">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="VectorLink" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Scripting" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/scripting">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="CodeJson" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Report a Bug" Command="{Binding OpenUrl}" CommandParameter="https://github.com/Artemis-RGB/Artemis/issues">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Github" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Get Help on Discord" Command="{Binding OpenUrl}" CommandParameter="https://discord.gg/S3MVaC9">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Discord" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
</UserControl>

View File

@ -0,0 +1,25 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.ProfileEditor.Panels.MenuBar
{
public partial class MenuBarView : UserControl
{
public MenuBarView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void MenuItem_OnSubmenuOpened(object? sender, RoutedEventArgs e)
{
}
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.ProfileEditor.Panels.MenuBar
{
public class MenuBarViewModel : ViewModelBase
{
}
}

View File

@ -29,7 +29,8 @@
Classes="icon-button icon-button-small"
ToolTip.Tip="Toggle suspended state"
IsChecked="{Binding !Folder.Suspended}"
VerticalAlignment="Center">
VerticalAlignment="Center"
Margin="4 0">
<avalonia:MaterialIcon Kind="Pause" />
</ToggleButton>
</Grid>

View File

@ -1,27 +1,23 @@
using System.Collections.Generic;
using Artemis.Core;
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)
public FolderTreeItemViewModel(TreeItemViewModel? parent, Folder folder, IProfileEditorVmFactory profileEditorVmFactory) : base(parent, folder)
{
Folder = folder;
Children = new List<TreeItemViewModel>();
foreach (ProfileElement profileElement in folder.Children)
{
if (profileElement is Folder childFolder)
Children.Add(profileEditorVmFactory.FolderTreeItemViewModel(childFolder));
Children.Add(profileEditorVmFactory.FolderTreeItemViewModel(this, childFolder));
else if (profileElement is Layer layer)
Children.Add(profileEditorVmFactory.LayerTreeItemViewModel(layer));
Children.Add(profileEditorVmFactory.LayerTreeItemViewModel(this, layer));
}
}
public List<TreeItemViewModel> Children { get; }
public Folder Folder { get; }
}
}

View File

@ -10,9 +10,7 @@
ToolTip.Tip="{Binding BrokenState}"
IsVisible="{Binding BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
Classes="icon-button icon-button-small"
Foreground="White"
Background="#E74C4C"
BorderBrush="#E74C4C"
Foreground="#E74C4C"
Command="{Binding ShowBrokenStateExceptions}">
<avalonia:MaterialIcon Kind="AlertCircle" />
</Button>
@ -22,7 +20,8 @@
Classes="icon-button icon-button-small"
ToolTip.Tip="Toggle suspended state"
IsChecked="{Binding Layer.Suspended}"
VerticalAlignment="Center">
VerticalAlignment="Center"
Margin="4 0">
<avalonia:MaterialIcon Kind="Pause" />
</ToggleButton>
</Grid>

View File

@ -4,11 +4,11 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
{
public class LayerTreeItemViewModel : TreeItemViewModel
{
public Layer Layer { get; }
public LayerTreeItemViewModel(Layer layer)
public LayerTreeItemViewModel(TreeItemViewModel? parent, Layer layer) : base(parent, layer)
{
Layer = layer;
}
public Layer Layer { get; }
}
}

View File

@ -2,14 +2,30 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:profileTree="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.ProfileTreeView">
<TreeView Items="{Binding TreeItems}" Classes="no-right-margin">
<Grid RowDefinitions="*,Auto">
<TreeView Classes="no-right-margin" Items="{Binding TreeItems}" SelectedItem="{Binding SelectedTreeItem}">
<TreeView.Styles>
<Style Selector="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
</Style>
</TreeView.Styles>
<TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Children}">
<ContentControl Content="{Binding}" />
</TreeDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Classes="icon-button" ToolTip.Tip="Add new folder to root" Command="{Binding AddFolder}">
<avalonia:MaterialIcon Kind="FolderAdd" />
</Button>
<Button Classes="icon-button" ToolTip.Tip="Add new layer to root" Command="{Binding AddLayer}" Margin="2 0 0 0">
<avalonia:MaterialIcon Kind="LayersPlus" />
</Button>
</StackPanel>
</Grid>
</UserControl>

View File

@ -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<Unit, Unit>? AddLayer { get; set; }
public ReactiveCommandWithHistory<Unit, Unit>? AddFolder { get; set; }
public ObservableCollection<TreeItemViewModel> 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<TreeItemViewModel> 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<TreeItemViewModel> GetAllTreeItems(ObservableCollection<TreeItemViewModel> treeItems)
{
List<TreeItemViewModel> result = new();
foreach (TreeItemViewModel treeItemViewModel in treeItems)
{
result.Add(treeItemViewModel);
if (treeItemViewModel.Children.Any())
result.AddRange(GetAllTreeItems(treeItemViewModel.Children));
}
return result;
}
}
}

View File

@ -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<int, Layer>("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<int, Folder>("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<int, Layer> AddLayerAtIndex { get; set; }
public ReactiveCommandWithHistory<int, Folder> AddFolderAtIndex { get; set; }
public RenderProfileElement ProfileElement { get; }
public TreeItemViewModel? Parent { get; set; }
public ObservableCollection<TreeItemViewModel> Children { get; } = new();
public bool IsExpanded
{
get => _isExpanded;
set => this.RaiseAndSetIfChanged(ref _isExpanded, value);
}
}
}

View File

@ -0,0 +1,18 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileEditorTitleBarView">
<Grid ColumnDefinitions="Auto,*,Auto">
<ContentControl Grid.Row="0" Grid.Column="0" Content="{Binding MenuBarViewModel}"></ContentControl>
<!-- This border enables dragging the window in between the menu and the buttons-->
<Border Grid.Row="0" Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Transparent" IsHitTestVisible="False" />
<Button Grid.Column="2" Classes="icon-button icon-button-small" Command="{Binding ShowDebugger}" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 6 0 0">
<avalonia:MaterialIcon Kind="Bug"></avalonia:MaterialIcon>
</Button>
</Grid>
</UserControl>

View File

@ -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)
{
}
}
}

View File

@ -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();
}
}
}

View File

@ -24,204 +24,19 @@
<Setter Property="Width" Value="18" />
<Setter Property="Height" Value="18" />
</Style>
<Style Selector="Window:windows Grid.editor-grid">
<Setter Property="Margin" Value="0 0 4 4"></Setter>
</Style>
<Style Selector="Window:windows Grid.editor-grid">
<Setter Property="Margin" Value="0 41 4 4"></Setter>
</Style>
</UserControl.Styles>
<Grid ColumnDefinitions="4*,Auto,*" RowDefinitions="Auto,*" Margin="0 0 4 4">
<Menu Grid.Row="0" Grid.ColumnSpan="3" VerticalAlignment="Top">
<MenuItem Header="_File">
<MenuItem Header="New">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Plus" />
</MenuItem.Icon>
<MenuItem Header="Folder" Command="{Binding AddFolder}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Folder" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Layer" Command="{Binding AddLayer}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Layers" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<Separator />
<MenuItem Header="View Properties" Command="{Binding ViewProperties}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Settings" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_View Scripts" Command="{Binding ViewScripts}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="BookEdit" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Adapt Profile" Command="{Binding AdaptProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Magic" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Suspend Profile">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding ProfileConfiguration.IsSuspended}" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Export Profile" Command="{Binding ExportProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Export" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Duplicate Profile" Command="{Binding DuplicateProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentDuplicate" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Delete Profile" Command="{Binding DeleteProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Trash" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Edit" SubmenuOpened="MenuItem_OnSubmenuOpened">
<MenuItem Header="_Duplicate"
Command="{Binding Duplicate}"
HotKey="Ctrl+D"
IsEnabled="{Binding HasSelectedElement}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentDuplicate" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Copy"
Command="{Binding Copy}"
HotKey="Ctrl+C"
IsEnabled="{Binding HasSelectedElement}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentCopy" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Paste"
Command="{Binding Paste}"
HotKey="Ctrl+V">
<MenuItem.Icon>
<avalonia:MaterialIconExt Kind="ContentPaste" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Run">
<MenuItem Header="_Switch run mode"
Command="{Binding ToggleSuspend}"
HotKey="F5">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="SwapHorizontal" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Run Profile on Focus Loss"
ToolTip.Tip="If enabled, run mode is set to normal on focus loss"
HotKey="Shift+F5">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding StopOnFocusLoss.Value}" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Options">
<MenuItem Header="Focus Selected Layer"
ToolTip.Tip="If enabled, displays only the layer you currently have selected"
IsEnabled="False">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding FocusSelectedLayer.Value}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Display Data Model Values">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding ShowDataModelValues.Value}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Display Full Condition Paths">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding ShowFullPaths.Value}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Always Display Cable Values" ToolTip.Tip="If enabled, cable values are always shown instead of only on hover">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding AlwaysShowValues.Value}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Apply All Data Bindings During Edit" ToolTip.Tip="If enabled, updates all data bindings instead of only the one you are editing">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
IsChecked="{Binding AlwaysApplyDataBindings.Value}" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="Artemis Wiki" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="BookEdit" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Editor" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/en/guides/user/profiles">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Edit" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Layers" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/layers">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Layers" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Display Conditions" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/conditions">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="NotEqual" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Timeline" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/timeline">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Stopwatch" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Data Bindings" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/data-bindings">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="VectorLink" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Scripting" Command="{Binding OpenUrl}" CommandParameter="https://wiki.artemis-rgb.com/guides/user/profiles/scripting">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="CodeJson" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Report a Bug" Command="{Binding OpenUrl}" CommandParameter="https://github.com/Artemis-RGB/Artemis/issues">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Github" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Get Help on Discord" Command="{Binding OpenUrl}" CommandParameter="https://discord.gg/S3MVaC9">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Discord" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
<Grid Grid.Row="1" Grid.Column="0" RowDefinitions="3*,Auto,*">
<Grid ColumnDefinitions="4*,Auto,*" Classes="editor-grid">
<ContentControl Content="{Binding MenuBarViewModel}"></ContentControl>
<Grid Grid.Column="0" RowDefinitions="3*,Auto,*">
<Border Grid.Row="0" Classes="card" Padding="0" Margin="4 0 4 4" ClipToBounds="True">
<Grid ColumnDefinitions="Auto,*">
<Border Grid.Column="0" Background="{DynamicResource CardStrokeColorDefaultSolidBrush}">
<StackPanel Orientation="Vertical">
<ToggleButton Classes="icon-button editor-sidebar-button">
<avalonia:MaterialIcon Kind="HandLeft" />
@ -239,7 +54,6 @@
</Border>
<ContentControl Grid.Column="1" Content="{Binding VisualEditorViewModel}" />
</Grid>
</Border>
<GridSplitter Grid.Row="1" Classes="editor-grid-splitter-horizontal" />
@ -249,9 +63,9 @@
</Border>
</Grid>
<GridSplitter Grid.Row="1" Grid.Column="1" Classes="editor-grid-splitter-vertical" />
<GridSplitter Grid.Row="0" Grid.Column="1" Classes="editor-grid-splitter-vertical" />
<Grid Grid.Row="1" Grid.Column="2" RowDefinitions="*,Auto,*">
<Grid Grid.Row="0" Grid.Column="2" RowDefinitions="*,Auto,*">
<Border Grid.Row="0" Classes="card card-condensed" Margin="4 0 4 4">
<ContentControl Content="{Binding ProfileTreeViewModel}" />
</Border>

View File

@ -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;
/// <inheritdoc />
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
{

View File

@ -0,0 +1,11 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Root.DefaultTitleBarView">
<Button Classes="icon-button icon-button-small" Command="{Binding ShowDebugger}" HorizontalAlignment="Right">
<avalonia:MaterialIcon Kind="Bug"></avalonia:MaterialIcon>
</Button>
</UserControl>

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -11,7 +11,7 @@
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ContentControl Grid.Column="0" Content="{Binding SidebarViewModel}" />
<ContentControl x:Name="SidebarContentControl" Grid.Column="0" Content="{Binding SidebarViewModel}" />
<reactiveUi:RoutedViewHost Grid.Column="1" Router="{Binding Router}">
<reactiveUi:RoutedViewHost.PageTransition>
<CrossFade Duration="0.1" />

View File

@ -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;

View File

@ -23,7 +23,6 @@ namespace Artemis.UI.Services
CurrentProfileElement = Observable.Defer(() => Observable.Return(_currentProfileElement)).Concat(_changeCurrentProfileElement);
}
public IObservable<ProfileConfiguration?> CurrentProfileConfiguration { get; }
public IObservable<RenderProfileElement?> CurrentProfileElement { get; }

View File

@ -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"
}
}