diff --git a/src/Artemis.Core/Exceptions/ArtemisPluginException.cs b/src/Artemis.Core/Exceptions/ArtemisPluginException.cs
index 8e49b0e19..53f9fd30f 100644
--- a/src/Artemis.Core/Exceptions/ArtemisPluginException.cs
+++ b/src/Artemis.Core/Exceptions/ArtemisPluginException.cs
@@ -10,7 +10,7 @@ public class ArtemisPluginException : Exception
///
/// Creates a new instance of the class
///
- public ArtemisPluginException(Plugin plugin)
+ internal ArtemisPluginException(Plugin plugin)
{
Plugin = plugin;
}
@@ -18,7 +18,7 @@ public class ArtemisPluginException : Exception
///
/// Creates a new instance of the class
///
- public ArtemisPluginException(Plugin plugin, string message) : base(message)
+ internal ArtemisPluginException(Plugin plugin, string message) : base(message)
{
Plugin = plugin;
}
@@ -26,7 +26,7 @@ public class ArtemisPluginException : Exception
///
/// Creates a new instance of the class
///
- public ArtemisPluginException(Plugin plugin, string message, Exception inner) : base(message, inner)
+ internal ArtemisPluginException(Plugin plugin, string message, Exception inner) : base(message, inner)
{
Plugin = plugin;
}
@@ -44,9 +44,31 @@ public class ArtemisPluginException : Exception
public ArtemisPluginException(string message, Exception inner) : base(message, inner)
{
}
+
+ ///
+ /// Creates a new instance of the class
+ ///
+ public ArtemisPluginException(string message, string helpDocument) : base(message)
+ {
+ HelpDocument = helpDocument;
+ }
+
+ ///
+ /// Creates a new instance of the class
+ ///
+ public ArtemisPluginException(string message, Exception inner, string helpDocument) : base(message, inner)
+ {
+ HelpDocument = helpDocument;
+ }
///
/// Gets the plugin the error is related to
///
public Plugin? Plugin { get; }
+
+ ///
+ /// Gets or sets the help document related to this exception.
+ ///
+ public string? HelpDocument { get; }
+
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs b/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
index 209158529..8e0faf564 100644
--- a/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
@@ -127,6 +127,13 @@ public interface IPluginManagementService : IArtemisService, IDisposable
/// If the current call stack contains a plugin, the plugin. Otherwise null
Plugin? GetCallingPlugin();
+ ///
+ /// Returns the plugin that threw the provided exception.
+ ///
+ ///
+ /// If the exception was thrown by a plugin, the plugin. Otherwise null
+ Plugin? GetPluginFromException(Exception exception);
+
///
/// Gets the plugin that defined the specified device
///
diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs
index 06b9b6368..c03aec7bb 100644
--- a/src/Artemis.Core/Services/PluginManagementService.cs
+++ b/src/Artemis.Core/Services/PluginManagementService.cs
@@ -192,7 +192,19 @@ internal class PluginManagementService : IPluginManagementService
public Plugin? GetCallingPlugin()
{
- StackTrace stackTrace = new(); // get call stack
+ return GetPluginFromStackTrace(new StackTrace());
+ }
+
+ public Plugin? GetPluginFromException(Exception exception)
+ {
+ if (exception is ArtemisPluginException pluginException && pluginException.Plugin != null)
+ return pluginException.Plugin;
+
+ return GetPluginFromStackTrace(new StackTrace(exception));
+ }
+
+ private Plugin? GetPluginFromStackTrace(StackTrace stackTrace)
+ {
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
foreach (StackFrame stackFrame in stackFrames)
diff --git a/src/Artemis.UI.Shared/Controls/HotkeyBox.axaml b/src/Artemis.UI.Shared/Controls/HotkeyBox.axaml
index 0e53282e1..6b7e0c0c1 100644
--- a/src/Artemis.UI.Shared/Controls/HotkeyBox.axaml
+++ b/src/Artemis.UI.Shared/Controls/HotkeyBox.axaml
@@ -10,8 +10,16 @@
diff --git a/src/Artemis.UI.Shared/Controls/HotkeyBox.axaml.cs b/src/Artemis.UI.Shared/Controls/HotkeyBox.axaml.cs
index d87e02d70..555d21320 100644
--- a/src/Artemis.UI.Shared/Controls/HotkeyBox.axaml.cs
+++ b/src/Artemis.UI.Shared/Controls/HotkeyBox.axaml.cs
@@ -8,6 +8,8 @@ using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
+using Avalonia.Threading;
+using DryIoc;
using FluentAvalonia.Core;
using Humanizer;
using Material.Icons;
@@ -19,44 +21,62 @@ namespace Artemis.UI.Shared;
///
public partial class HotkeyBox : UserControl
{
+ private readonly IInputService _inputService;
+
///
/// Creates a new instance of the class
///
public HotkeyBox()
{
+ _inputService = UI.Locator.Resolve();
+
InitializeComponent();
PropertyChanged += OnPropertyChanged;
- DisplayTextBox.KeyDown += DisplayTextBoxOnKeyDown;
- DisplayTextBox.KeyUp += DisplayTextBoxOnKeyUp;
UpdateDisplayTextBox();
}
+ protected override void OnGotFocus(GotFocusEventArgs e)
+ {
+ _inputService.KeyboardKeyDown += InputServiceOnKeyboardKeyDown;
+ _inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp;
+
+ base.OnGotFocus(e);
+ }
+
+ protected override void OnLostFocus(RoutedEventArgs e)
+ {
+ _inputService.KeyboardKeyDown -= InputServiceOnKeyboardKeyDown;
+ _inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp;
+
+ base.OnLostFocus(e);
+ }
+
private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == HotkeyProperty)
UpdateDisplayTextBox();
}
- private void DisplayTextBoxOnKeyDown(object? sender, KeyEventArgs e)
+ private void InputServiceOnKeyboardKeyDown(object? sender, ArtemisKeyboardKeyEventArgs e)
{
- if (e.Key >= Key.LeftShift && e.Key <= Key.RightAlt)
+ if (e.Key >= KeyboardKey.LeftShift && e.Key <= KeyboardKey.RightAlt)
return;
Hotkey ??= new Hotkey();
- Hotkey.Key = (KeyboardKey?) e.Key;
- Hotkey.Modifiers = (KeyboardModifierKey?) e.KeyModifiers;
- UpdateDisplayTextBox();
- HotkeyChanged?.Invoke(this, EventArgs.Empty);
-
- e.Handled = true;
+ Hotkey.Key = e.Key;
+ Hotkey.Modifiers = e.Modifiers;
+
+ Dispatcher.UIThread.Post(() =>
+ {
+ UpdateDisplayTextBox();
+ HotkeyChanged?.Invoke(this, EventArgs.Empty);
+ });
}
- private void DisplayTextBoxOnKeyUp(object? sender, KeyEventArgs e)
+ private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
{
- if (e.KeyModifiers == KeyModifiers.None)
- FocusManager.Instance?.Focus(null);
-
- e.Handled = true;
+ if (e.Modifiers == KeyboardModifierKey.None)
+ Dispatcher.UIThread.Post(() => FocusManager.Instance?.Focus(null));
}
private void UpdateDisplayTextBox()
diff --git a/src/Artemis.UI.Shared/DryIoc/ContainerExtensions.cs b/src/Artemis.UI.Shared/DryIoc/ContainerExtensions.cs
index 4c4711b02..1c86ecf84 100644
--- a/src/Artemis.UI.Shared/DryIoc/ContainerExtensions.cs
+++ b/src/Artemis.UI.Shared/DryIoc/ContainerExtensions.cs
@@ -17,5 +17,7 @@ public static class ContainerExtensions
{
Assembly artemisShared = typeof(IArtemisSharedUIService).GetAssembly();
container.RegisterMany(new[] { artemisShared }, type => type.IsAssignableTo(), Reuse.Singleton);
+
+ UI.Locator = container;
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Utilities.cs b/src/Artemis.UI.Shared/Utilities.cs
new file mode 100644
index 000000000..35abef7db
--- /dev/null
+++ b/src/Artemis.UI.Shared/Utilities.cs
@@ -0,0 +1,8 @@
+using DryIoc;
+
+namespace Artemis.UI.Shared;
+
+internal static class UI
+{
+ public static IContainer Locator { get; set; } = null!;
+}
\ No newline at end of file