fix(input-preview): wire Inside-mode + Tooltip-mode render paths
InputPreview was only rendered for PreviewPosition.Top/Bottom (the DrawConditions IsWindowMode gate). Inside-mode (the default) and Tooltip-mode had no caller at all because v1.5.6's inline-render path lived on the deleted ChatLogWindow and was not migrated to the v1.7.0 Components-Layer. Wire Inside-mode by calling CalculatePreviewHeight + DrawPreview inline from MainWindow.DrawMainArea between the message-list child and the input bar, with the message-list height reserved for the preview block. Wire Tooltip-mode by sampling IsItemHovered() on the input text widget inside InputBar.DrawInputField (analog to the existing _isFocused = ImGui.IsItemFocused() idiom on the same line) and exposing it as WasInputTextHovered; MainWindow opens the tooltip after _input.Draw when both the hover-flag and PreviewPosition.Tooltip are active. Plan-drift acknowledged: the plan stated Plugin.InputPreview is statically reachable, but the property was declared as an instance member on Plugin.cs:101. Hoisted to internal static to match the plan's intention (analog to Plugin.Config); updated the single external instance-access site in PluginLifecycle.RegisterWindows to the type-qualified form. Verified in-game: Inside-mode preview block appears between message list and input bar on first keystroke; tooltip-mode shows preview on text-field hover only; Top/Bottom-mode unchanged; empty buffer hides the preview in all modes. dotnet build clean, dotnet csharpier check clean.
This commit is contained in:
@@ -98,7 +98,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
|
|||||||
internal Ui.Windows.MainWindow MainWindow { get; private set; } = null!;
|
internal Ui.Windows.MainWindow MainWindow { get; private set; } = null!;
|
||||||
internal Ui.Windows.SettingsWindow SettingsWindow { get; private set; } = null!;
|
internal Ui.Windows.SettingsWindow SettingsWindow { get; private set; } = null!;
|
||||||
public DbViewer DbViewer { get; private set; } = null!;
|
public DbViewer DbViewer { get; private set; } = null!;
|
||||||
internal InputPreview InputPreview { get; private set; } = null!;
|
internal static InputPreview InputPreview { get; private set; } = null!;
|
||||||
internal CommandHelpWindow CommandHelpWindow { get; private set; } = null!;
|
internal CommandHelpWindow CommandHelpWindow { get; private set; } = null!;
|
||||||
public SeStringDebugger SeStringDebugger { get; private set; } = null!;
|
public SeStringDebugger SeStringDebugger { get; private set; } = null!;
|
||||||
public FirstRunWizard FirstRunWizard { get; private set; } = null!;
|
public FirstRunWizard FirstRunWizard { get; private set; } = null!;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ internal sealed class PluginLifecycle : IAsyncDisposable
|
|||||||
plugin.WindowSystem.AddWindow(plugin.MainWindow);
|
plugin.WindowSystem.AddWindow(plugin.MainWindow);
|
||||||
plugin.WindowSystem.AddWindow(plugin.SettingsWindow);
|
plugin.WindowSystem.AddWindow(plugin.SettingsWindow);
|
||||||
plugin.WindowSystem.AddWindow(plugin.DbViewer);
|
plugin.WindowSystem.AddWindow(plugin.DbViewer);
|
||||||
plugin.WindowSystem.AddWindow(plugin.InputPreview);
|
plugin.WindowSystem.AddWindow(Plugin.InputPreview);
|
||||||
plugin.WindowSystem.AddWindow(plugin.CommandHelpWindow);
|
plugin.WindowSystem.AddWindow(plugin.CommandHelpWindow);
|
||||||
plugin.WindowSystem.AddWindow(plugin.SeStringDebugger);
|
plugin.WindowSystem.AddWindow(plugin.SeStringDebugger);
|
||||||
plugin.WindowSystem.AddWindow(plugin.DebuggerWindow);
|
plugin.WindowSystem.AddWindow(plugin.DebuggerWindow);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ internal sealed class InputBar
|
|||||||
|
|
||||||
private string _pendingMessage = string.Empty;
|
private string _pendingMessage = string.Empty;
|
||||||
private bool _isFocused;
|
private bool _isFocused;
|
||||||
|
private bool _wasInputTextHovered;
|
||||||
private bool? _isFocusedOverride; // Test-only; null = honour per-frame Draw() value.
|
private bool? _isFocusedOverride; // Test-only; null = honour per-frame Draw() value.
|
||||||
|
|
||||||
public bool Activate;
|
public bool Activate;
|
||||||
@@ -74,6 +75,10 @@ internal sealed class InputBar
|
|||||||
// rest of the component doesn't need.
|
// rest of the component doesn't need.
|
||||||
public bool IsFocused => _isFocusedOverride ?? _isFocused;
|
public bool IsFocused => _isFocusedOverride ?? _isFocused;
|
||||||
|
|
||||||
|
// Sampled in DrawInputField() right after ImGui.InputText so the value
|
||||||
|
// reflects the text widget, not a later QuickButton item.
|
||||||
|
public bool WasInputTextHovered => _wasInputTextHovered;
|
||||||
|
|
||||||
public void ClearBuffer() => _pendingMessage = string.Empty;
|
public void ClearBuffer() => _pendingMessage = string.Empty;
|
||||||
|
|
||||||
// BufferCapacity is an ImGui UX limit, not a protocol constraint. We
|
// BufferCapacity is an ImGui UX limit, not a protocol constraint. We
|
||||||
@@ -235,6 +240,7 @@ internal sealed class InputBar
|
|||||||
TrySend(activeTab);
|
TrySend(activeTab);
|
||||||
}
|
}
|
||||||
_isFocused = ImGui.IsItemFocused();
|
_isFocused = ImGui.IsItemFocused();
|
||||||
|
_wasInputTextHovered = ImGui.IsItemHovered();
|
||||||
}
|
}
|
||||||
|
|
||||||
// v1.5.6 character-level slash-detect: fires on every edit so CommandHelpWindow
|
// v1.5.6 character-level slash-detect: fires on every edit so CommandHelpWindow
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ internal sealed class InputPreview : Window
|
|||||||
DrawPreview();
|
DrawPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CalculatePreviewHeight()
|
internal void CalculatePreviewHeight()
|
||||||
{
|
{
|
||||||
// Pre-draw offscreen once to measure actual rendered height; value is
|
// Pre-draw offscreen once to measure actual rendered height; value is
|
||||||
// consumed next frame by PreDraw() for window sizing.
|
// consumed next frame by PreDraw() for window sizing.
|
||||||
@@ -162,7 +162,7 @@ internal sealed class InputPreview : Window
|
|||||||
PreviewHeight += IsWindowMode ? ImGui.GetStyle().WindowPadding.Y * 2 : 0;
|
PreviewHeight += IsWindowMode ? ImGui.GetStyle().WindowPadding.Y * 2 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawPreview()
|
internal void DrawPreview()
|
||||||
{
|
{
|
||||||
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero))
|
using (ImRaii.PushStyle(ImGuiStyleVar.ItemSpacing, Vector2.Zero))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface.Utility;
|
||||||
using Dalamud.Interface.Utility.Raii;
|
using Dalamud.Interface.Utility.Raii;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using HellionChat.Util;
|
using HellionChat.Util;
|
||||||
@@ -138,12 +139,51 @@ internal sealed class MainWindow : Window
|
|||||||
{
|
{
|
||||||
var inputHeight = Components.InputBar.Height;
|
var inputHeight = Components.InputBar.Height;
|
||||||
|
|
||||||
using (var messages = ImRaii.Child("##hellion-main-area", new Vector2(-1f, -inputHeight)))
|
// Shrink the message child when Inside-mode preview is active so the
|
||||||
|
// inline preview block does not overlap the message list. PreviewHeight
|
||||||
|
// lags one frame behind on the very first keystroke (same as v1.5.6).
|
||||||
|
var previewHeight =
|
||||||
|
Plugin.Config.PreviewPosition is PreviewPosition.Inside
|
||||||
|
&& Plugin.InputPreview.IsDrawable
|
||||||
|
? Plugin.InputPreview.PreviewHeight
|
||||||
|
: 0f;
|
||||||
|
|
||||||
|
using (
|
||||||
|
var messages = ImRaii.Child(
|
||||||
|
"##hellion-main-area",
|
||||||
|
new Vector2(-1f, -(inputHeight + previewHeight))
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (messages.Success)
|
if (messages.Success)
|
||||||
_messages.Draw(_activeTab!);
|
_messages.Draw(_activeTab!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inside-mode inline render: measure first so PreviewHeight is fresh
|
||||||
|
// for the next frame's reservation, then draw between messages and input.
|
||||||
|
if (
|
||||||
|
Plugin.Config.PreviewPosition is PreviewPosition.Inside
|
||||||
|
&& Plugin.InputPreview.IsDrawable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Plugin.InputPreview.CalculatePreviewHeight();
|
||||||
|
Plugin.InputPreview.DrawPreview();
|
||||||
|
}
|
||||||
|
|
||||||
_input.Draw(_activeTab);
|
_input.Draw(_activeTab);
|
||||||
|
|
||||||
|
// Tooltip-mode: sampled hover-state from InputBar reflects the actual
|
||||||
|
// InputText widget (after-Draw IsItemHovered would target a QuickButton).
|
||||||
|
// ImRaii.Tooltip has no Success guard — BeginTooltip always runs in ctor.
|
||||||
|
if (
|
||||||
|
Plugin.Config.PreviewPosition is PreviewPosition.Tooltip
|
||||||
|
&& Plugin.InputPreview.IsDrawable
|
||||||
|
&& _input.WasInputTextHovered
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ImGui.SetNextWindowSize(new Vector2(500 * ImGuiHelpers.GlobalScale, -1));
|
||||||
|
using var tooltip = ImRaii.Tooltip();
|
||||||
|
Plugin.InputPreview.DrawPreview();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user