diff --git a/Dalamud/Interface/Windowing/Window.cs b/Dalamud/Interface/Windowing/Window.cs
index d4f0070db..44ff62199 100644
--- a/Dalamud/Interface/Windowing/Window.cs
+++ b/Dalamud/Interface/Windowing/Window.cs
@@ -55,6 +55,9 @@ public abstract class Window
private Vector2 fadeOutSize = Vector2.Zero;
private Vector2 fadeOutOrigin = Vector2.Zero;
+ private bool hasError = false;
+ private Exception? lastError;
+
///
/// Initializes a new instance of the class.
///
@@ -458,14 +461,24 @@ public abstract class Window
this.presetDirty = true;
}
- // Draw the actual window contents
- try
+ if (this.hasError)
{
- this.Draw();
+ this.DrawErrorMessage();
}
- catch (Exception ex)
+ else
{
- Log.Error(ex, "Error during Draw(): {WindowName}", this.WindowName);
+ // Draw the actual window contents
+ try
+ {
+ this.Draw();
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex, "Error during Draw(): {WindowName}", this.WindowName);
+
+ this.hasError = true;
+ this.lastError = ex;
+ }
}
}
@@ -793,7 +806,7 @@ public abstract class Window
hovered = true;
// We can't use ImGui native functions here, because they don't work with clickthrough
- if ((global::Windows.Win32.PInvoke.GetKeyState((int)VirtualKey.LBUTTON) & 0x8000) != 0)
+ if ((Windows.Win32.PInvoke.GetKeyState((int)VirtualKey.LBUTTON) & 0x8000) != 0)
{
held = true;
pressed = true;
@@ -871,6 +884,52 @@ public abstract class Window
ImGui.End();
}
+ private void DrawErrorMessage()
+ {
+ // TODO: Once window systems are services, offer to reload the plugin
+ ImGui.TextColoredWrapped(ImGuiColors.DalamudRed,Loc.Localize("WindowSystemErrorOccurred", "An error occurred while rendering this window. Please contact the developer for details."));
+
+ ImGuiHelpers.ScaledDummy(5);
+
+ if (ImGui.Button(Loc.Localize("WindowSystemErrorRecoverButton", "Attempt to retry")))
+ {
+ this.hasError = false;
+ this.lastError = null;
+ }
+
+ ImGui.SameLine();
+
+ if (ImGui.Button(Loc.Localize("WindowSystemErrorClose", "Close Window")))
+ {
+ this.IsOpen = false;
+ this.hasError = false;
+ this.lastError = null;
+ }
+
+ ImGuiHelpers.ScaledDummy(10);
+
+ if (this.lastError != null)
+ {
+ using var child = ImRaii.Child("##ErrorDetails", new Vector2(0, 200 * ImGuiHelpers.GlobalScale), true);
+ using (ImRaii.PushColor(ImGuiCol.Text, ImGuiColors.DalamudGrey))
+ {
+ ImGui.TextWrapped(Loc.Localize("WindowSystemErrorDetails", "Error Details:"));
+ ImGui.Separator();
+ ImGui.TextWrapped(this.lastError.ToString());
+ }
+
+ var childWindowSize = ImGui.GetWindowSize();
+ var copyText = Loc.Localize("WindowSystemErrorCopy", "Copy");
+ var buttonWidth = ImGuiComponents.GetIconButtonWithTextWidth(FontAwesomeIcon.Copy, copyText);
+ ImGui.SetCursorPos(new Vector2(childWindowSize.X - buttonWidth - ImGui.GetStyle().FramePadding.X,
+ ImGui.GetStyle().FramePadding.Y));
+ if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Copy, copyText))
+ {
+ ImGui.SetClipboardText(this.lastError.ToString());
+ }
+ }
+ }
+
///
/// Structure detailing the size constraints of a window.
///