Skip to content

feat(app): experimental AvaloniaEdit renderer for Raw XML and Stream windows - #296

Merged
monil2233 merged 12 commits into
GenieClient:mainfrom
simtel12:worktree-avaloniaedit-rawxml-stream
Aug 23, 2026
Merged

feat(app): experimental AvaloniaEdit renderer for Raw XML and Stream windows#296
monil2233 merged 12 commits into
GenieClient:mainfrom
simtel12:worktree-avaloniaedit-rawxml-stream

Conversation

@simtel12

Copy link
Copy Markdown
Contributor

Summary

  • Generalizes the experimental AvaloniaEdit-backed GameTextEditor control (previously game-window-only, behind useeditorgamewindow) behind a new ITextEditorHost contract, and extends it to the Raw XML and Stream windows.
  • Adds useeditorrawxmlwindow and useeditorstreamwindow config keys (default off, read once at dock-layout build time, same experimental contract as the existing game-window flag). GenieDockFactory selects EditorRawXmlTool/EditorStreamTool vs. the legacy RawXmlTool/StreamTool per flag — one useeditorstreamwindow flag governs all 12 Stream instances.
  • Colorizing and link generation are opt-in per host (ITextEditorHost.EnableColorizing / EnableLinks): on for Game/Stream, off for Raw XML, which stays a plain verbatim dump.
  • RawXmlViewModel.Lines moves from ObservableCollection<string> to ObservableCollection<TextLine>, matching GameTextViewModel/StreamBuffer, so the shared renderer has one consistent line type across all three window kinds.
  • Adds MainWindowViewModel's dataDirectoryOverride test seam (isolates data-dir discovery for tests without touching real per-user AppData) and new coverage: DataDirectoryOverrideTests, DockFactoryEditorWindowTests, EditorRawXmlWindowConfigTests, EditorStreamWindowConfigTests.

All flags default off — with them off, the legacy per-line ItemsControl rendering is untouched and byte-for-byte the same code path as before.

Test plan

  • dotnet build src/Genie.App/Genie.App.csproj — succeeds
  • dotnet test tests/Genie.Core.Tests — 1147 passed
  • dotnet test tests/Genie.App.Tests — 81 passed, including the new editor-window/dock-factory/data-directory-override coverage

RawXmlViewModel.Lines is now ObservableCollection<TextLine> (plain,
Color = StreamColor.Main) instead of ObservableCollection<string>,
matching GameTextViewModel.Lines/StreamBuffer.Lines so a later task
can generalize the AvaloniaEdit renderer to Raw XML. Raw XML's own
visual behavior is unchanged (still plain green, unstyled).

Also updates the two GenieDockFactory.cs call sites (CopyAll, SaveAs)
that fed rx.ViewModel.Lines directly into IEnumerable<string> APIs —
they now .Select(l => l.Text), matching the pattern already used for
every other TextLine-backed tool in the same switch expressions.
@simtel12
simtel12 requested a review from monil2233 as a code owner August 18, 2026 06:52

@monil2233 monil2233 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed against source and verified locally — build 0 warnings, full suites green (Core 1147, App 81). The generalization follows the #200 pattern faithfully: type-based template selection with the editor templates placed above the legacy ones, flags read once at layout build, config keys registered in the dump/categories/setter, and with both flags off the legacy path is untouched (the only legacy-path edit is the Raw XML ItemsControl retarget from x:String to TextLine, visually identical).

What I checked beyond the diff:

  • Per-window highlight scoping survives the shared renderer: GameLineEntry passes each line's own Window into DefaultHighlights.BuildStyleMap, so editor-mode Stream windows keep the same scoping semantics as the legacy renderer.
  • The CopyAll/SaveAs call sites correctly follow the Lines type change.
  • The dataDirectoryOverride seam mirrors GenieCore's existing UseExplicitRoot — good to finally have dock-factory coverage that can't touch real AppData.

Three notes, none blocking:

  1. The one real caution before these flags ever default on: GameLineEntry builds its style map eagerly, and BuildStyleMap fires highlight sound/TTS as a side effect. RebuildAll (re-attach / Reset) and ReplaceLine (rules repaint) reconstruct every entry, which can re-fire alerts for the whole scrollback. That trait came with #200, but this PR multiplies the exposure across 12 stream windows — Combat especially. Worth a follow-up where only Append fires alerts.
  2. The new RawXmlViewModel.Lines doc comment cites "(#274)" — that's the automapper config-keys issue; should read #296 (or #200). I'll fix that in a follow-up.
  3. Heads-up: this overlaps your draft #258 in GameTextEditor.cs (Subscribe/Unsubscribe and Find wiring) — whichever lands second needs a small rebase, and once #258 is ready, its search-panel behavior on editor Stream windows is worth a re-look.

Merging. Thanks — this is exactly the follow-on flagged in #200, and the flag-off isolation story held up under review.

@monil2233
monil2233 merged commit 7d9182f into GenieClient:main Aug 23, 2026
3 checks passed
monil2233 added a commit that referenced this pull request Aug 23, 2026
The TextLine unification note cited #274 (the automapper config keys), not
the editor-renderer work it belongs to.
monil2233 added a commit that referenced this pull request Aug 23, 2026
The static Bitmap caches were plain Dictionaries — fine for the app, which
only touches them from the UI thread, but the App test suite now constructs
two MainWindowViewModels from parallel xUnit collections (#296's
DataDirectoryOverrideTests joined DockFactoryEditorWindowTests), and
concurrent writes intermittently corrupt a plain Dictionary
("Operations that change non-concurrent collections must have exclusive
access", seen once in a full-suite run). ConcurrentDictionary; a benign
double-load races to last-wins, which is fine for identical sprites.
monil2233 added a commit that referenced this pull request Aug 23, 2026
…indow keys

The #296 editor-renderer flags landed with #config help entries but no rows in
the settings reference, which documents the sibling useeditorgamewindow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants