User reported wanting to mark text in-game and copy it out (item names,
coordinates, NPC dialogue, etc). ImGui doesn't natively let you select
across multiple TextColored widgets, but a read-only multi-line
InputText is fully click-drag selectable + Ctrl+C copyable. This
commit adds a "Copy mode" toggle to ChatPanel that swaps the chat
tail's render path between the colored-line view and a single
selectable text region.
New IPanelRenderer primitive:
void TextMultilineReadOnly(string id, string content, Vector2 size);
ImGui maps this to InputTextMultiline with the ReadOnly flag — same
selection + Ctrl+C UX a user expects from any text-input widget.
FakePanelRenderer records the call for tests. The future D.2b
custom retail-look backend implements its own equivalent (likely
the same widget pattern with retail font/skin).
ChatPanel rendering:
· A "Copy mode (select text to Ctrl+C)" Checkbox at the top of
the panel toggles _copyMode.
· Off (default) — current per-line render with colored combat
entries. Visually unchanged from before.
· On — the chat tail becomes a single TextMultilineReadOnly
widget holding every visible line joined with newlines. Loses
per-line color, gains arbitrary-span text selection.
· Footer (separator + input field) renders identically in both
modes so the user can still type while in copy mode.
Existing ChatPanelLayoutTests's footer-separator probe was using
IndexOf("Separator") — which now matches the new pre-tail separator
between the Checkbox and the chat tail. Switched to LastIndexOf
which still pins the footer separator (between EndChild and
InputTextSubmit). Behaviour and intent unchanged.
DisplaySettingsTests' With_expression test was still asserting the
old "1920x1080" Default.Resolution; updated to the new "1280x720"
that the previous wire-up commit introduced (the earlier commit
forgot this one).
dotnet build green (0 warnings); dotnet test 1,309 / 1,309 green
(243 Core.Net + 393 UI.Abstractions + 673 Core).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
76 lines
2.6 KiB
C#
76 lines
2.6 KiB
C#
using AcDream.UI.Abstractions.Panels.Settings;
|
||
|
||
namespace AcDream.UI.Abstractions.Tests.Panels.Settings;
|
||
|
||
/// <summary>
|
||
/// L.0: <see cref="DisplaySettings"/> is the immutable record of
|
||
/// display-tab preferences. Defaults are pinned here so a regression
|
||
/// (e.g. someone changing the default FOV out from under users)
|
||
/// surfaces immediately.
|
||
/// </summary>
|
||
public sealed class DisplaySettingsTests
|
||
{
|
||
[Fact]
|
||
public void Default_values_match_pre_L0_runtime_state()
|
||
{
|
||
// Defaults pinned to match the actual pre-L.0 startup state:
|
||
// · Resolution matches WindowOptions (1280×720 in GameWindow.Run)
|
||
// · FieldOfView matches camera FovY (60° = π/3)
|
||
// · VSync matches WindowOptions (false during dev)
|
||
// · ShowFps true preserves the perf string in the title bar
|
||
// Net effect: opening Display + Save with no edits is a visual
|
||
// no-op (no window resize, no camera FovY change, no title
|
||
// bar change).
|
||
var d = DisplaySettings.Default;
|
||
Assert.Equal("1280x720", d.Resolution);
|
||
Assert.False(d.Fullscreen);
|
||
Assert.False(d.VSync);
|
||
Assert.Equal(60f, d.FieldOfView);
|
||
Assert.Equal(1.0f, d.Gamma);
|
||
Assert.True(d.ShowFps);
|
||
}
|
||
|
||
[Fact]
|
||
public void AvailableResolutions_includes_common_16_9_options()
|
||
{
|
||
var list = DisplaySettings.AvailableResolutions;
|
||
Assert.Contains("1280x720", list);
|
||
Assert.Contains("1920x1080", list);
|
||
Assert.Contains("2560x1440", list);
|
||
Assert.Contains("3840x2160", list);
|
||
// List should be ascending so the dropdown reads naturally.
|
||
for (int i = 1; i < list.Count; i++)
|
||
{
|
||
int prevW = ParseWidth(list[i - 1]);
|
||
int curW = ParseWidth(list[i]);
|
||
Assert.True(curW >= prevW, $"Resolutions not sorted: {list[i - 1]} >= {list[i]}");
|
||
}
|
||
}
|
||
|
||
[Fact]
|
||
public void Equality_is_value_based()
|
||
{
|
||
var a = DisplaySettings.Default;
|
||
var b = DisplaySettings.Default with { Fullscreen = true };
|
||
var c = DisplaySettings.Default with { Fullscreen = true };
|
||
Assert.NotEqual(a, b);
|
||
Assert.Equal(b, c);
|
||
}
|
||
|
||
[Fact]
|
||
public void With_expression_clones_one_field()
|
||
{
|
||
var d = DisplaySettings.Default with { FieldOfView = 90f };
|
||
Assert.Equal(90f, d.FieldOfView);
|
||
// Other fields untouched.
|
||
Assert.Equal("1280x720", d.Resolution);
|
||
Assert.False(d.VSync);
|
||
Assert.True(d.ShowFps);
|
||
}
|
||
|
||
private static int ParseWidth(string res)
|
||
{
|
||
int x = res.IndexOf('x');
|
||
return int.Parse(res.AsSpan(0, x));
|
||
}
|
||
}
|