mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Windows - Added input provider
Debugger - Fixed data model list display
This commit is contained in:
parent
d594ed7951
commit
b801de1f30
@ -27,7 +27,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// The base path for Artemis application data folder
|
||||
/// </summary>
|
||||
public static readonly string BaseFolder = Environment.GetFolderPath(OperatingSystem.IsWindows() ? Environment.SpecialFolder.ApplicationData : Environment.SpecialFolder.LocalApplicationData);
|
||||
public static readonly string BaseFolder = Environment.GetFolderPath(OperatingSystem.IsWindows() ? Environment.SpecialFolder.CommonApplicationData : Environment.SpecialFolder.LocalApplicationData);
|
||||
|
||||
/// <summary>
|
||||
/// The full path to the Artemis data folder
|
||||
|
||||
@ -25,7 +25,11 @@ namespace Artemis.Core.Services
|
||||
public void Dispose()
|
||||
{
|
||||
while (_inputProviders.Any())
|
||||
RemoveInputProvider(_inputProviders.First());
|
||||
{
|
||||
InputProvider provider = _inputProviders.First();
|
||||
RemoveInputProvider(provider);
|
||||
provider.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -374,67 +374,39 @@
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelEventViewModel.ToString">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="T:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel">
|
||||
<summary>
|
||||
Represents a view model that wraps a regular <see cref="T:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelPropertiesViewModel" /> but contained in
|
||||
a <see cref="T:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListViewModel" />
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel.Index">
|
||||
<summary>
|
||||
Gets the index of the element within the list
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel.ListType">
|
||||
<summary>
|
||||
Gets the type of elements contained in the list
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel.DisplayValue">
|
||||
<summary>
|
||||
Gets the value of the property that is being visualized
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel.DisplayViewModel">
|
||||
<summary>
|
||||
Gets the view model that handles displaying the property
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel.DisplayPath">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel.Update(Artemis.UI.Shared.Services.Interfaces.IDataModelUIService,Artemis.UI.Shared.DataModelVisualization.Shared.DataModelUpdateConfiguration)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel.GetCurrentValue">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertiesViewModel.ToString">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="T:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertyViewModel">
|
||||
<member name="T:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListItemViewModel">
|
||||
<summary>
|
||||
Represents a view model that visualizes a single data model property contained in a
|
||||
<see cref="T:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListViewModel" />
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertyViewModel.Index">
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListItemViewModel.DisplayViewModel">
|
||||
<summary>
|
||||
Gets the view model used to display the display value
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListItemViewModel.Index">
|
||||
<summary>
|
||||
Gets the index of the element within the list
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertyViewModel.ListType">
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListItemViewModel.ListType">
|
||||
<summary>
|
||||
Gets the type of elements contained in the list
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertyViewModel.GetCurrentValue">
|
||||
<member name="P:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListItemViewModel.DisplayValue">
|
||||
<summary>
|
||||
Gets the value of the property that is being visualized
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListItemViewModel.GetCurrentValue">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertyViewModel.Update(Artemis.UI.Shared.Services.Interfaces.IDataModelUIService,Artemis.UI.Shared.DataModelVisualization.Shared.DataModelUpdateConfiguration)">
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListItemViewModel.Update(Artemis.UI.Shared.Services.Interfaces.IDataModelUIService,Artemis.UI.Shared.DataModelVisualization.Shared.DataModelUpdateConfiguration)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListPropertyViewModel.ToString">
|
||||
<member name="M:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListItemViewModel.ToString">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="T:Artemis.UI.Shared.DataModelVisualization.Shared.DataModelListViewModel">
|
||||
|
||||
@ -9,22 +9,33 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
/// Represents a view model that visualizes a single data model property contained in a
|
||||
/// <see cref="DataModelListViewModel" />
|
||||
/// </summary>
|
||||
public class DataModelListPropertyViewModel : DataModelPropertyViewModel
|
||||
public class DataModelListItemViewModel : DataModelVisualizationViewModel
|
||||
{
|
||||
private int _index;
|
||||
private Type? _listType;
|
||||
private object? _displayValue;
|
||||
private DataModelDisplayViewModel? _displayViewModel;
|
||||
|
||||
internal DataModelListPropertyViewModel(Type listType, DataModelDisplayViewModel displayViewModel, string? name) : base(null, null, null)
|
||||
internal DataModelListItemViewModel(Type listType, DataModelDisplayViewModel displayViewModel, string? name) : base(null, null, null)
|
||||
{
|
||||
ListType = listType;
|
||||
DisplayViewModel = displayViewModel;
|
||||
}
|
||||
|
||||
internal DataModelListPropertyViewModel(Type listType, string? name) : base(null, null, null)
|
||||
internal DataModelListItemViewModel(Type listType, string? name) : base(null, null, null)
|
||||
{
|
||||
ListType = listType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view model used to display the display value
|
||||
/// </summary>
|
||||
public DataModelDisplayViewModel? DisplayViewModel
|
||||
{
|
||||
get => _displayViewModel;
|
||||
internal set => this.RaiseAndSetIfChanged(ref _displayViewModel, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the element within the list
|
||||
/// </summary>
|
||||
@ -43,6 +54,15 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
private set => this.RaiseAndSetIfChanged(ref _listType, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the property that is being visualized
|
||||
/// </summary>
|
||||
public object? DisplayValue
|
||||
{
|
||||
get => _displayValue;
|
||||
internal set => this.RaiseAndSetIfChanged(ref _displayValue, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? GetCurrentValue()
|
||||
{
|
||||
@ -66,7 +86,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[List item {Index}] {DisplayPath ?? Path} - {DisplayValue}";
|
||||
return $"[List item {Index}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a view model that wraps a regular <see cref="DataModelPropertiesViewModel" /> but contained in
|
||||
/// a <see cref="DataModelListViewModel" />
|
||||
/// </summary>
|
||||
public class DataModelListPropertiesViewModel : DataModelPropertiesViewModel
|
||||
{
|
||||
private object? _displayValue;
|
||||
private int _index;
|
||||
private Type? _listType;
|
||||
|
||||
internal DataModelListPropertiesViewModel(Type listType, string? name) : base(null, null, null)
|
||||
{
|
||||
ListType = listType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the index of the element within the list
|
||||
/// </summary>
|
||||
public int Index
|
||||
{
|
||||
get => _index;
|
||||
set => this.RaiseAndSetIfChanged(ref _index, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of elements contained in the list
|
||||
/// </summary>
|
||||
public Type? ListType
|
||||
{
|
||||
get => _listType;
|
||||
set => this.RaiseAndSetIfChanged(ref _listType, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the property that is being visualized
|
||||
/// </summary>
|
||||
public new object? DisplayValue
|
||||
{
|
||||
get => _displayValue;
|
||||
set => this.RaiseAndSetIfChanged(ref _displayValue, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view model that handles displaying the property
|
||||
/// </summary>
|
||||
public DataModelVisualizationViewModel? DisplayViewModel => Children.FirstOrDefault();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string? DisplayPath => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration? configuration)
|
||||
{
|
||||
PopulateProperties(dataModelUIService, configuration);
|
||||
if (DisplayViewModel == null)
|
||||
return;
|
||||
|
||||
if (IsVisualizationExpanded && !DisplayViewModel.IsVisualizationExpanded)
|
||||
DisplayViewModel.IsVisualizationExpanded = IsVisualizationExpanded;
|
||||
DisplayViewModel.Update(dataModelUIService, null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? GetCurrentValue()
|
||||
{
|
||||
return DisplayValue;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[List item {Index}] {DisplayPath ?? Path}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -98,22 +98,15 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
ListChildren.Add(child);
|
||||
}
|
||||
else
|
||||
{
|
||||
child = ListChildren[index];
|
||||
}
|
||||
|
||||
if (child is DataModelListPropertiesViewModel dataModelListClassViewModel)
|
||||
{
|
||||
dataModelListClassViewModel.DisplayValue = item;
|
||||
dataModelListClassViewModel.Index = index;
|
||||
}
|
||||
else if (child is DataModelListPropertyViewModel dataModelListPropertyViewModel)
|
||||
if (child is DataModelListItemViewModel dataModelListPropertyViewModel)
|
||||
{
|
||||
dataModelListPropertyViewModel.DisplayValue = item;
|
||||
dataModelListPropertyViewModel.Index = index;
|
||||
dataModelListPropertyViewModel.Update(dataModelUIService, configuration);
|
||||
}
|
||||
|
||||
child.Update(dataModelUIService, configuration);
|
||||
index++;
|
||||
}
|
||||
|
||||
@ -135,16 +128,10 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
{
|
||||
// If a display VM was found, prefer to use that in any case
|
||||
DataModelDisplayViewModel? typeViewModel = dataModelUIService.GetDataModelDisplayViewModel(listType, PropertyDescription);
|
||||
if (typeViewModel != null)
|
||||
return new DataModelListPropertyViewModel(listType, typeViewModel, name);
|
||||
// For primitives, create a property view model, it may be null that is fine
|
||||
if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string))
|
||||
return new DataModelListPropertyViewModel(listType, name);
|
||||
// For other value types create a child view model
|
||||
if (listType.IsClass || listType.IsStruct())
|
||||
return new DataModelListPropertiesViewModel(listType, name);
|
||||
|
||||
return null;
|
||||
return typeViewModel != null
|
||||
? new DataModelListItemViewModel(listType, typeViewModel, name)
|
||||
: new DataModelListItemViewModel(listType, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,7 +215,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(t => t.MetadataToken))
|
||||
{
|
||||
string childPath = AppendToPath(propertyInfo.Name);
|
||||
if (Children.Any(c => c.Path != null && c.Path.Equals(childPath)))
|
||||
if (Children.Any(c => c?.Path != null && c.Path.Equals(childPath)))
|
||||
continue;
|
||||
if (propertyInfo.GetCustomAttribute<DataModelIgnoreAttribute>() != null)
|
||||
continue;
|
||||
|
||||
@ -13,17 +13,8 @@
|
||||
Margin="0 0 5 0" />
|
||||
|
||||
<!-- Value -->
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding DisplayValue, Mode=OneWay}"
|
||||
HorizontalAlignment="Right"
|
||||
IsVisible="{Binding ShowToString}"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="null"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right"
|
||||
Foreground="{DynamicResource MaterialDesignCheckBoxDisabled}"
|
||||
IsVisible="{Binding ShowNull}"/>
|
||||
|
||||
<TextBlock Grid.Column="1" Text="{Binding Display, Mode=OneWay}" HorizontalAlignment="Right"/>
|
||||
|
||||
<!-- Affix -->
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding PropertyDescription.Affix}"
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared.DataModelVisualization;
|
||||
using Newtonsoft.Json;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Shared.DefaultTypes.DataModel.Display
|
||||
@ -11,33 +12,32 @@ namespace Artemis.UI.Shared.DefaultTypes.DataModel.Display
|
||||
/// </summary>
|
||||
internal class DefaultDataModelDisplayViewModel : DataModelDisplayViewModel<object>
|
||||
{
|
||||
private bool _showNull;
|
||||
private bool _showToString;
|
||||
private readonly JsonSerializerSettings _serializerSettings;
|
||||
private string _display;
|
||||
|
||||
internal DefaultDataModelDisplayViewModel()
|
||||
public DefaultDataModelDisplayViewModel()
|
||||
{
|
||||
ShowNull = true;
|
||||
_serializerSettings = new JsonSerializerSettings()
|
||||
{
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||
PreserveReferencesHandling = PreserveReferencesHandling.None
|
||||
};
|
||||
}
|
||||
|
||||
public bool ShowToString
|
||||
public string Display
|
||||
{
|
||||
get => _showToString;
|
||||
private set => this.RaiseAndSetIfChanged(ref _showToString, value);
|
||||
get => _display;
|
||||
set => this.RaiseAndSetIfChanged(ref _display, value);
|
||||
}
|
||||
|
||||
public bool ShowNull
|
||||
{
|
||||
get => _showNull;
|
||||
set => this.RaiseAndSetIfChanged(ref _showNull, value);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnDisplayValueUpdated()
|
||||
{
|
||||
if (DisplayValue is Enum enumDisplayValue)
|
||||
DisplayValue = EnumUtilities.HumanizeValue(enumDisplayValue);
|
||||
|
||||
ShowToString = DisplayValue != null;
|
||||
ShowNull = DisplayValue == null;
|
||||
Display = EnumUtilities.HumanizeValue(enumDisplayValue);
|
||||
else if (DisplayValue is not string)
|
||||
Display = JsonConvert.SerializeObject(DisplayValue, _serializerSettings);
|
||||
else
|
||||
Display = DisplayValue?.ToString() ?? "null";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,9 @@
|
||||
|
||||
<!-- Add Styles Here -->
|
||||
<Style Selector="ListBox.sidebar-listbox ListBoxItem">
|
||||
<Setter Property="Margin" Value="0 2.5" />
|
||||
<Setter Property="MinHeight" Value="35" />
|
||||
</Style>
|
||||
<Style Selector="ListBox.sidebar-listbox ContentPresenter">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
</Style>
|
||||
</Styles>
|
||||
@ -1,3 +1,6 @@
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Windows.Providers;
|
||||
using Artemis.UI.Windows.Providers.Input;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
@ -9,16 +12,13 @@ namespace Artemis.UI.Windows
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
// ReSharper disable NotAccessedField.Local
|
||||
private StandardKernel? _kernel;
|
||||
private ApplicationStateManager? _applicationStateManager;
|
||||
// ReSharper restore NotAccessedField.Local
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_kernel = ArtemisBootstrapper.Bootstrap(this);
|
||||
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
RegisterProviders(_kernel);
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
@ -27,5 +27,17 @@ namespace Artemis.UI.Windows
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
_applicationStateManager = new ApplicationStateManager(_kernel!, desktop.Args);
|
||||
}
|
||||
|
||||
private void RegisterProviders(StandardKernel standardKernel)
|
||||
{
|
||||
IInputService inputService = standardKernel.Get<IInputService>();
|
||||
inputService.AddInputProvider(standardKernel.Get<WindowsInputProvider>());
|
||||
}
|
||||
|
||||
// ReSharper disable NotAccessedField.Local
|
||||
private StandardKernel? _kernel;
|
||||
|
||||
private ApplicationStateManager? _applicationStateManager;
|
||||
// ReSharper restore NotAccessedField.Local
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,9 @@
|
||||
<!--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.10" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.10" />
|
||||
<PackageReference Include="Avalonia.Win32" Version="0.10.10" />
|
||||
<PackageReference Include="Microsoft.Win32" Version="2.0.1" />
|
||||
<PackageReference Include="RawInput.Sharp" Version="0.0.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Artemis.Core\Artemis.Core.csproj" />
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using Avalonia.Win32;
|
||||
|
||||
namespace Artemis.UI.Windows.Providers.Input
|
||||
{
|
||||
public class SpongeWindow : WindowImpl
|
||||
{
|
||||
#region Overrides of WindowImpl
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
OnWndProcCalled(new SpongeWindowEventArgs(hWnd, msg, wParam, lParam));
|
||||
return base.WndProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public event EventHandler<SpongeWindowEventArgs>? WndProcCalled;
|
||||
|
||||
protected virtual void OnWndProcCalled(SpongeWindowEventArgs e)
|
||||
{
|
||||
WndProcCalled?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.UI.Windows.Providers.Input
|
||||
{
|
||||
public class SpongeWindowEventArgs : EventArgs
|
||||
{
|
||||
public IntPtr HWnd { get; }
|
||||
public uint Msg { get; }
|
||||
public IntPtr WParam { get; }
|
||||
public IntPtr LParam { get; }
|
||||
|
||||
public SpongeWindowEventArgs(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
HWnd = hWnd;
|
||||
Msg = msg;
|
||||
WParam = wParam;
|
||||
LParam = lParam;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,281 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Timers;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Windows.Utilities;
|
||||
using Linearstar.Windows.RawInput;
|
||||
using Linearstar.Windows.RawInput.Native;
|
||||
using Serilog;
|
||||
using MouseButton = Artemis.Core.Services.MouseButton;
|
||||
|
||||
namespace Artemis.UI.Windows.Providers.Input
|
||||
{
|
||||
public class WindowsInputProvider : InputProvider
|
||||
{
|
||||
private const int WM_INPUT = 0x00FF;
|
||||
|
||||
private readonly IInputService _inputService;
|
||||
private readonly ILogger _logger;
|
||||
private DateTime _lastMouseUpdate;
|
||||
private int _lastProcessId;
|
||||
private SpongeWindow _sponge;
|
||||
private readonly Timer _taskManagerTimer;
|
||||
|
||||
public WindowsInputProvider(ILogger logger, IInputService inputService)
|
||||
{
|
||||
_logger = logger;
|
||||
_inputService = inputService;
|
||||
|
||||
_sponge = new SpongeWindow();
|
||||
_sponge.WndProcCalled += SpongeOnWndProcCalled;
|
||||
|
||||
_taskManagerTimer = new Timer(500);
|
||||
_taskManagerTimer.Elapsed += TaskManagerTimerOnElapsed;
|
||||
_taskManagerTimer.Start();
|
||||
|
||||
RawInputDevice.RegisterDevice(HidUsageAndPage.Keyboard, RawInputDeviceFlags.InputSink, _sponge.Handle.Handle);
|
||||
RawInputDevice.RegisterDevice(HidUsageAndPage.Mouse, RawInputDeviceFlags.InputSink, _sponge.Handle.Handle);
|
||||
}
|
||||
|
||||
|
||||
#region Overrides of InputProvider
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnKeyboardToggleStatusRequested()
|
||||
{
|
||||
UpdateToggleStatus();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_sponge.Dispose();
|
||||
_taskManagerTimer.Dispose();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void SpongeOnWndProcCalled(object? sender, SpongeWindowEventArgs message)
|
||||
{
|
||||
if (message.Msg != WM_INPUT)
|
||||
return;
|
||||
|
||||
RawInputData data = RawInputData.FromHandle(message.LParam);
|
||||
switch (data)
|
||||
{
|
||||
case RawInputMouseData mouse:
|
||||
HandleMouseData(data, mouse);
|
||||
break;
|
||||
case RawInputKeyboardData keyboard:
|
||||
HandleKeyboardData(data, keyboard);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void TaskManagerTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
int processId = WindowUtilities.GetActiveProcessId();
|
||||
if (processId == _lastProcessId)
|
||||
return;
|
||||
|
||||
_lastProcessId = processId;
|
||||
|
||||
// If task manager has focus then we can't track keys properly, release everything to avoid them getting stuck
|
||||
// Same goes for Idle which is what you get when you press Ctrl+Alt+Del
|
||||
Process active = Process.GetProcessById(processId);
|
||||
if (active?.ProcessName == "Taskmgr" || active?.ProcessName == "Idle")
|
||||
_inputService.ReleaseAll();
|
||||
}
|
||||
|
||||
#region Keyboard
|
||||
|
||||
private void HandleKeyboardData(RawInputData data, RawInputKeyboardData keyboardData)
|
||||
{
|
||||
KeyboardKey key = InputUtilities.KeyFromVirtualKey(keyboardData.Keyboard.VirutalKey);
|
||||
// Debug.WriteLine($"VK: {key} ({keyboardData.Keyboard.VirutalKey}), Flags: {keyboardData.Keyboard.Flags}, Scan code: {keyboardData.Keyboard.ScanCode}");
|
||||
|
||||
// Sometimes we get double hits and they resolve to None, ignore those
|
||||
if (key == KeyboardKey.None)
|
||||
return;
|
||||
|
||||
// Right alt triggers LeftCtrl with a different scan code for some reason, ignore those
|
||||
if (key == KeyboardKey.LeftCtrl && keyboardData.Keyboard.ScanCode == 56)
|
||||
return;
|
||||
|
||||
string identifier = data.Device?.DevicePath;
|
||||
|
||||
// Let the core know there is an identifier so it can store new identifications if applicable
|
||||
if (identifier != null)
|
||||
OnIdentifierReceived(identifier, InputDeviceType.Keyboard);
|
||||
|
||||
ArtemisDevice device = null;
|
||||
if (identifier != null)
|
||||
try
|
||||
{
|
||||
device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Keyboard);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Warning(e, "Failed to retrieve input device by its identifier");
|
||||
}
|
||||
|
||||
// Duplicate keys with different positions can be identified by the LeftKey flag (even though its set of the key that's physically on the right)
|
||||
if (keyboardData.Keyboard.Flags == RawKeyboardFlags.KeyE0 || keyboardData.Keyboard.Flags == (RawKeyboardFlags.KeyE0 | RawKeyboardFlags.Up))
|
||||
{
|
||||
if (key == KeyboardKey.Enter)
|
||||
key = KeyboardKey.NumPadEnter;
|
||||
if (key == KeyboardKey.LeftCtrl)
|
||||
key = KeyboardKey.RightCtrl;
|
||||
if (key == KeyboardKey.LeftAlt)
|
||||
key = KeyboardKey.RightAlt;
|
||||
}
|
||||
|
||||
if (key == KeyboardKey.LeftShift && keyboardData.Keyboard.ScanCode == 54)
|
||||
key = KeyboardKey.RightShift;
|
||||
|
||||
bool isDown = keyboardData.Keyboard.Flags != RawKeyboardFlags.Up &&
|
||||
keyboardData.Keyboard.Flags != (RawKeyboardFlags.Up | RawKeyboardFlags.KeyE0) &&
|
||||
keyboardData.Keyboard.Flags != (RawKeyboardFlags.Up | RawKeyboardFlags.KeyE1);
|
||||
|
||||
OnKeyboardDataReceived(device, key, isDown);
|
||||
UpdateToggleStatus();
|
||||
}
|
||||
|
||||
private void UpdateToggleStatus()
|
||||
{
|
||||
OnKeyboardToggleStatusReceived(new KeyboardToggleStatus(
|
||||
InputUtilities.IsKeyToggled(KeyboardKey.NumLock),
|
||||
InputUtilities.IsKeyToggled(KeyboardKey.CapsLock),
|
||||
InputUtilities.IsKeyToggled(KeyboardKey.Scroll)
|
||||
));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mouse
|
||||
|
||||
private int _mouseDeltaX;
|
||||
private int _mouseDeltaY;
|
||||
|
||||
private void HandleMouseData(RawInputData data, RawInputMouseData mouseData)
|
||||
{
|
||||
// Only submit mouse movement 25 times per second but increment the delta
|
||||
// This can create a small inaccuracy of course, but Artemis is not a shooter :')
|
||||
if (mouseData.Mouse.Buttons == RawMouseButtonFlags.None)
|
||||
{
|
||||
_mouseDeltaX += mouseData.Mouse.LastX;
|
||||
_mouseDeltaY += mouseData.Mouse.LastY;
|
||||
if (DateTime.Now - _lastMouseUpdate < TimeSpan.FromMilliseconds(40))
|
||||
return;
|
||||
}
|
||||
|
||||
ArtemisDevice device = null;
|
||||
string identifier = data.Device?.DevicePath;
|
||||
if (identifier != null)
|
||||
try
|
||||
{
|
||||
device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Keyboard);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Warning(e, "Failed to retrieve input device by its identifier");
|
||||
}
|
||||
|
||||
// Debug.WriteLine($"Buttons: {mouseData.Mouse.Buttons}, Data: {mouseData.Mouse.ButtonData}, Flags: {mouseData.Mouse.Flags}, XY: {mouseData.Mouse.LastX},{mouseData.Mouse.LastY}");
|
||||
|
||||
// Movement
|
||||
if (mouseData.Mouse.Buttons == RawMouseButtonFlags.None)
|
||||
{
|
||||
Win32Point cursorPosition = GetCursorPosition();
|
||||
OnMouseMoveDataReceived(device, cursorPosition.X, cursorPosition.Y, _mouseDeltaX, _mouseDeltaY);
|
||||
_mouseDeltaX = 0;
|
||||
_mouseDeltaY = 0;
|
||||
_lastMouseUpdate = DateTime.Now;
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we know its not movement, let the core know there is an identifier so it can store new identifications if applicable
|
||||
if (identifier != null)
|
||||
OnIdentifierReceived(identifier, InputDeviceType.Mouse);
|
||||
|
||||
// Scrolling
|
||||
if (mouseData.Mouse.ButtonData != 0)
|
||||
{
|
||||
if (mouseData.Mouse.Buttons == RawMouseButtonFlags.MouseWheel)
|
||||
OnMouseScrollDataReceived(device, MouseScrollDirection.Vertical, mouseData.Mouse.ButtonData);
|
||||
else if (mouseData.Mouse.Buttons == RawMouseButtonFlags.MouseHorizontalWheel)
|
||||
OnMouseScrollDataReceived(device, MouseScrollDirection.Horizontal, mouseData.Mouse.ButtonData);
|
||||
return;
|
||||
}
|
||||
|
||||
// Button presses
|
||||
MouseButton button = MouseButton.Left;
|
||||
bool isDown = false;
|
||||
|
||||
// Left
|
||||
if (DetermineMouseButton(mouseData, RawMouseButtonFlags.LeftButtonDown, RawMouseButtonFlags.LeftButtonUp, ref isDown))
|
||||
button = MouseButton.Left;
|
||||
// Middle
|
||||
else if (DetermineMouseButton(mouseData, RawMouseButtonFlags.MiddleButtonDown, RawMouseButtonFlags.MiddleButtonUp, ref isDown))
|
||||
button = MouseButton.Middle;
|
||||
// Right
|
||||
else if (DetermineMouseButton(mouseData, RawMouseButtonFlags.RightButtonDown, RawMouseButtonFlags.RightButtonUp, ref isDown))
|
||||
button = MouseButton.Right;
|
||||
// Button 4
|
||||
else if (DetermineMouseButton(mouseData, RawMouseButtonFlags.Button4Down, RawMouseButtonFlags.Button4Up, ref isDown))
|
||||
button = MouseButton.Button4;
|
||||
else if (DetermineMouseButton(mouseData, RawMouseButtonFlags.Button5Down, RawMouseButtonFlags.Button5Up, ref isDown))
|
||||
button = MouseButton.Button5;
|
||||
|
||||
OnMouseButtonDataReceived(device, button, isDown);
|
||||
}
|
||||
|
||||
private bool DetermineMouseButton(RawInputMouseData data, RawMouseButtonFlags downButton, RawMouseButtonFlags upButton, ref bool isDown)
|
||||
{
|
||||
if (data.Mouse.Buttons == downButton || data.Mouse.Buttons == upButton)
|
||||
{
|
||||
isDown = data.Mouse.Buttons == downButton;
|
||||
return true;
|
||||
}
|
||||
|
||||
isDown = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Native
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool GetCursorPos(ref Win32Point pt);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct Win32Point
|
||||
{
|
||||
public readonly int X;
|
||||
public readonly int Y;
|
||||
}
|
||||
|
||||
private static Win32Point GetCursorPosition()
|
||||
{
|
||||
Win32Point w32Mouse = new();
|
||||
GetCursorPos(ref w32Mouse);
|
||||
|
||||
return w32Mouse;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
1400
src/Avalonia/Artemis.UI.Windows/Utilities/InputUtilities.cs
Normal file
1400
src/Avalonia/Artemis.UI.Windows/Utilities/InputUtilities.cs
Normal file
File diff suppressed because it is too large
Load Diff
23
src/Avalonia/Artemis.UI.Windows/Utilities/WindowUtilities.cs
Normal file
23
src/Avalonia/Artemis.UI.Windows/Utilities/WindowUtilities.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Artemis.UI.Windows.Utilities
|
||||
{
|
||||
public static class WindowUtilities
|
||||
{
|
||||
public static int GetActiveProcessId()
|
||||
{
|
||||
// Get foreground window handle
|
||||
IntPtr hWnd = GetForegroundWindow();
|
||||
|
||||
GetWindowThreadProcessId(hWnd, out uint processId);
|
||||
return (int) processId;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
||||
}
|
||||
}
|
||||
@ -53,6 +53,33 @@
|
||||
"System.Reactive": "5.0.0"
|
||||
}
|
||||
},
|
||||
"Avalonia.Win32": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.10.10, )",
|
||||
"resolved": "0.10.10",
|
||||
"contentHash": "6AS6yIB+OS8+g96mj+ShJihjxqhVH6v7jfdqLwjQfGAsqqqN7zBNsFdvoVVCnutuVx0g/9FhCnBTIZyZDlwqkA==",
|
||||
"dependencies": {
|
||||
"Avalonia": "0.10.10",
|
||||
"Avalonia.Angle.Windows.Natives": "2.1.0.2020091801",
|
||||
"System.Drawing.Common": "4.5.0",
|
||||
"System.Numerics.Vectors": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Win32": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.0.1, )",
|
||||
"resolved": "2.0.1",
|
||||
"contentHash": "V1I3Mvj0g6YFoVywl0uoPh7fJ4y7xTewBGrW9FN70dr9LruFnC4rJ/bJ2wxIvZyeVrsj2JaqxvkuSw9fhk9UKA=="
|
||||
},
|
||||
"RawInput.Sharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[0.0.4, )",
|
||||
"resolved": "0.0.4",
|
||||
"contentHash": "JAHC4oBBzvwvehjiWTUW0UAjptprQuX+21d/7LrsMAjBSrT9GB6q6JiEm0bQi69uTkBPohHNF7O8Wgcz3oVXkA==",
|
||||
"dependencies": {
|
||||
"NETStandard.Library": "1.6.1"
|
||||
}
|
||||
},
|
||||
"Avalonia.Angle.Windows.Natives": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.1.0.2020091801",
|
||||
@ -122,17 +149,6 @@
|
||||
"Svg.Skia": "0.5.10"
|
||||
}
|
||||
},
|
||||
"Avalonia.Win32": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.10.10",
|
||||
"contentHash": "6AS6yIB+OS8+g96mj+ShJihjxqhVH6v7jfdqLwjQfGAsqqqN7zBNsFdvoVVCnutuVx0g/9FhCnBTIZyZDlwqkA==",
|
||||
"dependencies": {
|
||||
"Avalonia": "0.10.10",
|
||||
"Avalonia.Angle.Windows.Natives": "2.1.0.2020091801",
|
||||
"System.Drawing.Common": "4.5.0",
|
||||
"System.Numerics.Vectors": "4.5.0"
|
||||
}
|
||||
},
|
||||
"Avalonia.X11": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.10.10",
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
using Artemis.Core.Services;
|
||||
|
||||
namespace Artemis.UI.Providers
|
||||
{
|
||||
public class AvaloniaInputProvider : InputProvider
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ using System;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.UI.Shared.Events;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
@ -16,6 +17,10 @@ namespace Artemis.UI.Screens.Debugger
|
||||
public DebugView()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
|
||||
NavigationView navigation = this.Get<NavigationView>("Navigation");
|
||||
|
||||
this.WhenActivated(d =>
|
||||
|
||||
@ -7,23 +7,25 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Debugger.Tabs.DataModel.DataModelDebugView">
|
||||
<UserControl.Resources>
|
||||
<converters:TypeToStringConverter x:Key="TypeToStringConverter" />
|
||||
<converters:TypeToStringConverter x:Key="TypeToStringConverter" />
|
||||
</UserControl.Resources>
|
||||
<StackPanel>
|
||||
<TextBlock Classes="h3">Data Model</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
On this page you can view the contents of the Artemis data model.
|
||||
</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap" Classes="subtitle" Margin="0 10">
|
||||
Please note that having this window open can have a performance impact on your system.
|
||||
</TextBlock>
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<StackPanel Grid.Row="0">
|
||||
<TextBlock Classes="h3">Data Model</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
On this page you can view the contents of the Artemis data model.
|
||||
</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap" Classes="subtitle" Margin="0 10">
|
||||
Please note that having this window open can have a performance impact on your system.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<TreeView Items="{Binding MainDataModel.Children}">
|
||||
<TreeView.Styles>
|
||||
<Style Selector="TreeViewItem">
|
||||
<Setter Property="IsExpanded" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
||||
</Style>
|
||||
</TreeView.Styles>
|
||||
<TreeView Grid.Row="1" Items="{Binding MainDataModel.Children}">
|
||||
<TreeView.Styles>
|
||||
<Style Selector="TreeViewItem">
|
||||
<Setter Property="IsExpanded" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
||||
</Style>
|
||||
</TreeView.Styles>
|
||||
<TreeView.DataTemplates>
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelPropertiesViewModel}" ItemsSource="{Binding Children}">
|
||||
<Grid ColumnDefinitions="Auto,Auto,*">
|
||||
@ -35,9 +37,9 @@
|
||||
|
||||
<TextBlock Grid.Column="1" Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding DisplayValue}"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right" />
|
||||
Text="{Binding DisplayValue}"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
|
||||
</TreeDataTemplate>
|
||||
@ -50,9 +52,9 @@
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Column="1" Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding CountDisplay, Mode=OneWay}"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right" />
|
||||
Text="{Binding CountDisplay, Mode=OneWay}"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</TreeDataTemplate>
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
|
||||
@ -70,22 +72,20 @@
|
||||
<ContentControl Grid.Column="2" Content="{Binding DisplayViewModel}" FontFamily="Consolas" />
|
||||
</Grid>
|
||||
</TreeDataTemplate>
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelListPropertyViewModel}">
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelListItemViewModel}">
|
||||
<Grid ColumnDefinitions="Auto,Auto,*">
|
||||
|
||||
<!-- Value description -->
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" Margin="0 0 5 0">
|
||||
<TextBlock FontWeight="Bold">[</TextBlock>
|
||||
<TextBlock FontWeight="Bold" Text="{Binding ListType, Converter={StaticResource TypeToStringConverter}, Mode=OneWay}" />
|
||||
<TextBlock FontWeight="Bold" Text="{Binding ListType, Converter={StaticResource TypeToStringConverter}}" />
|
||||
<TextBlock FontWeight="Bold">]</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Margin="0 0 5 0">
|
||||
<TextBlock>List item [</TextBlock>
|
||||
<TextBlock Text="{Binding Index, Mode=OneWay}" />
|
||||
<TextBlock>]</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Margin="0 0 5 0">
|
||||
<TextBlock>List item #</TextBlock>
|
||||
<TextBlock Text="{Binding Index, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Value display -->
|
||||
<!-- Value display -->
|
||||
<ContentControl Grid.Column="2" Content="{Binding DisplayViewModel}" FontFamily="Consolas" />
|
||||
</Grid>
|
||||
</TreeDataTemplate>
|
||||
@ -99,20 +99,13 @@
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Column="1" Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding CountDisplay, Mode=OneWay}"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right" />
|
||||
Text="{Binding CountDisplay, Mode=OneWay}"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</TreeDataTemplate>
|
||||
</TreeView.DataTemplates>
|
||||
</TreeView>
|
||||
</Grid>
|
||||
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelListPropertiesViewModel}" ItemsSource="{Binding DisplayViewModel.Children}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock>List item [</TextBlock>
|
||||
<TextBlock Text="{Binding Index, Mode=OneWay}" />
|
||||
<TextBlock>]</TextBlock>
|
||||
</StackPanel>
|
||||
</TreeDataTemplate>
|
||||
</TreeView.DataTemplates>
|
||||
</TreeView>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@ -5,22 +5,25 @@
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Debugger.Tabs.Performance.PerformanceDebugView">
|
||||
<StackPanel>
|
||||
<TextBlock Classes="h3">Performance</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
On this page you can see how much CPU time different plugin features are taking. If you are having performance issues, below you can find out which plugin might be the culprit.
|
||||
</TextBlock>
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBlock TextWrapping="Wrap" Classes="subtitle" Margin="0 10">
|
||||
These performance stats are rather basic, for advanced performance profiling check out the wiki.
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<StackPanel Grid.Row="0">
|
||||
<TextBlock Classes="h3">Performance</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
On this page you can see how much CPU time different plugin features are taking. If you are having performance issues, below you can find out which plugin might be the culprit.
|
||||
</TextBlock>
|
||||
<controls:HyperlinkButton Grid.Column="1" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins/profiling">
|
||||
JetBrains Profiling Guide
|
||||
</controls:HyperlinkButton>
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBlock TextWrapping="Wrap" Classes="subtitle" Margin="0 10">
|
||||
These performance stats are rather basic, for advanced performance profiling check out the wiki.
|
||||
</TextBlock>
|
||||
<controls:HyperlinkButton Grid.Column="1" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins/profiling">
|
||||
JetBrains Profiling Guide
|
||||
</controls:HyperlinkButton>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl Items="{Binding Items}" Margin="0 0 10 0" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||
<ItemsControl Items="{Binding Items}" Margin="0 0 10 0" />
|
||||
</ScrollViewer>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@ -4,11 +4,7 @@ using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.Home;
|
||||
using Artemis.UI.Screens.Root.Sidebar;
|
||||
using Artemis.UI.Screens.Settings;
|
||||
using Artemis.UI.Screens.SurfaceEditor;
|
||||
using Artemis.UI.Screens.Workshop;
|
||||
using Artemis.UI.Services.Interfaces;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
@ -18,21 +14,19 @@ using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Threading;
|
||||
using Ninject;
|
||||
using Ninject.Parameters;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Root
|
||||
{
|
||||
public class RootViewModel : ActivatableViewModelBase, IScreen, IMainWindowProvider
|
||||
{
|
||||
private readonly IClassicDesktopStyleApplicationLifetime _lifeTime;
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IWindowService _windowService;
|
||||
private readonly IDebugService _debugService;
|
||||
private readonly IAssetLoader _assetLoader;
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IDebugService _debugService;
|
||||
private readonly IClassicDesktopStyleApplicationLifetime _lifeTime;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ISidebarVmFactory _sidebarVmFactory;
|
||||
private readonly IWindowService _windowService;
|
||||
private SidebarViewModel? _sidebarViewModel;
|
||||
private TrayIcon? _trayIcon;
|
||||
private TrayIcons? _trayIcons;
|
||||
@ -58,7 +52,6 @@ namespace Artemis.UI.Screens.Root
|
||||
|
||||
coreService.StartupArguments = _lifeTime.Args.ToList();
|
||||
mainWindowService.ConfigureMainWindowProvider(this);
|
||||
registrationService.RegisterProviders();
|
||||
|
||||
DisplayAccordingToSettings();
|
||||
Task.Run(coreService.Initialize);
|
||||
@ -70,9 +63,6 @@ namespace Artemis.UI.Screens.Root
|
||||
set => this.RaiseAndSetIfChanged(ref _sidebarViewModel, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public RoutingState Router { get; }
|
||||
|
||||
private void CurrentMainWindowOnClosed(object? sender, EventArgs e)
|
||||
{
|
||||
_lifeTime.MainWindow = null;
|
||||
@ -113,7 +103,7 @@ namespace Artemis.UI.Screens.Root
|
||||
{
|
||||
_trayIcon = new TrayIcon
|
||||
{
|
||||
Icon = new WindowIcon(_assetLoader.Open(new Uri("avares://Artemis.UI/Assets/Images/Logo/bow.ico"))),
|
||||
Icon = new WindowIcon(_assetLoader.Open(new Uri("avares://Artemis.UI/Assets/Images/Logo/bow.ico"))),
|
||||
Command = ReactiveCommand.Create(OpenMainWindow)
|
||||
};
|
||||
_trayIcon.Menu = (NativeMenu?) Application.Current.FindResource("TrayIconMenu");
|
||||
@ -130,6 +120,9 @@ namespace Artemis.UI.Screens.Root
|
||||
_trayIcons = null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public RoutingState Router { get; }
|
||||
|
||||
#region Tray commands
|
||||
|
||||
public void OpenScreen(string displayName)
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
void RegisterBuiltInDataModelDisplays();
|
||||
void RegisterBuiltInDataModelInputs();
|
||||
void RegisterBuiltInPropertyEditors();
|
||||
void RegisterProviders();
|
||||
void RegisterControllers();
|
||||
void ApplyPreferredGraphicsContext();
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Providers;
|
||||
using Artemis.UI.Services.Interfaces;
|
||||
|
||||
namespace Artemis.UI.Services
|
||||
@ -24,11 +23,6 @@ namespace Artemis.UI.Services
|
||||
{
|
||||
}
|
||||
|
||||
public void RegisterProviders()
|
||||
{
|
||||
_inputService.AddInputProvider(new AvaloniaInputProvider());
|
||||
}
|
||||
|
||||
public void RegisterControllers()
|
||||
{
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user