Skip to content

Relocate concrete UndoManager + AfterUndoMessage into headless Gum.Presentation (ADR-0005 Phase 3)#3357

Merged
vchelaru merged 1 commit into
mainfrom
undomanager-move
Jun 25, 2026
Merged

Relocate concrete UndoManager + AfterUndoMessage into headless Gum.Presentation (ADR-0005 Phase 3)#3357
vchelaru merged 1 commit into
mainfrom
undomanager-move

Conversation

@vchelaru

Copy link
Copy Markdown
Owner

What

Relocates the concrete UndoManager class — the first piece of actual logic, not just a contract — across the headless boundary into Gum.Presentation, plus its AfterUndoMessage. This is the payoff move of the ADR-0005 Phase 3 undo extraction, unblocked by #3355 (IUndoPluginNotifier) and #3356 (IUndoRenameLogic), which drained UndoManager's last two tool-coupled constructor dependencies. All 6 ctor deps are now headless interfaces (ISelectedState, IUndoRenameLogic, IGuiCommands, IFileCommands, IMessenger, IUndoPluginNotifier).

Changes

  • git mv Gum/Undo/UndoManager.cs and AfterUndoMessage.csTools/Gum.Presentation/Undo/. The Gum.Undo namespace is preserved, so Builder.cs DI registration and every consumer (including PluginManager's AfterUndoMessage handler) compile unchanged.
  • Dropped now-stale usings Gum.Managers and Gum.Wireframe.
  • Localized the tool-only StateSave.SetFrom extension as a private UndoManager.SetStateContentsFrom helper. The standalone headless compile surfaced this as UndoManager's last hidden tool-only dependency (it lived in the tool-only StateSaveExtensionMethodsGumTool partial). UndoManager was its only caller in the entire repo, so it was never a shared extension; the orphan is removed from the tool partial. FixEnumerations() is now called unconditionally — matching prior tool behavior, where the extension's #if GUM-guarded call was always active (GUM is defined in the tool build).
  • Deleted dead code: the never-called GetWhatToApplyTo method and its only-consumer UndoObject.cs.
  • Granted Gum.Presentation InternalsVisibleTo("GumToolUnitTests") so UndoManagerTests keeps reaching UndoManager's internal UndoLocks. Gum.csproj already granted this via AssemblyInfo.cs, so the grant simply moves with the class.

Behavior

Behavior-preserving (move + dead-code deletion + single-caller helper relocation).

Verification

  • Gum.Presentation compiles standalone — 0 errors (the headless proof: no WPF/WinForms leak crossed the boundary).
  • GumFull.sln builds — 0 errors.
  • GumToolUnitTests — 1000 passed, 0 failed, 4 skipped (incl. UndoManagerTests and CompositeMemberLogicApplyTests).

Follow-up

UndoManager being headless now unlocks headless undo/redo unit tests (no UI needed) in a future Gum.Presentation.Tests project — the InternalsVisibleTo("Gum.Presentation.Tests") grant is already in place for that.

🤖 Generated with Claude Code

…esentation (ADR-0005 Phase 3)

First concrete logic class (not just a contract) to cross the headless boundary, unblocked by #3355 (IUndoPluginNotifier) and #3356 (IUndoRenameLogic), which drained UndoManager's last two tool-coupled ctor deps. All 6 ctor deps are now headless interfaces and the body references no tool-only types.

- git mv Gum/Undo/UndoManager.cs and AfterUndoMessage.cs -> Tools/Gum.Presentation/Undo/. Namespace stays Gum.Undo, so Builder.cs DI and all consumers (incl. PluginManager's AfterUndoMessage handler) compile unchanged.

- Drop now-stale usings Gum.Managers and Gum.Wireframe.

- Localize the tool-only StateSave.SetFrom extension as a private UndoManager.SetStateContentsFrom helper (UndoManager was its only caller in the repo); remove the orphan from StateSaveExtensionMethodsGumTool. FixEnumerations is now unconditional, matching prior tool behavior (the extension guarded it with #if GUM, and GUM is defined in the tool build).

- Delete the dead GetWhatToApplyTo method and its only-consumer UndoObject.cs.

- Grant Gum.Presentation InternalsVisibleTo GumToolUnitTests so UndoManagerTests keeps reaching the internal UndoLocks; Gum.csproj already granted this via AssemblyInfo, so the grant moves with the class.

Behavior-preserving. Verified: Gum.Presentation compiles standalone (0 errors, no WPF/WinForms leak); GumFull.sln builds (0 errors); GumToolUnitTests 1000 passed / 0 failed / 4 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vchelaru vchelaru enabled auto-merge (squash) June 25, 2026 20:13
@vchelaru vchelaru merged commit 5c47b15 into main Jun 25, 2026
3 checks passed
@vchelaru vchelaru deleted the undomanager-move branch June 25, 2026 20:23
vchelaru added a commit that referenced this pull request Jun 25, 2026
…005 Phase 3) (#3358)

Stand up the headless test suite that realizes the point of the undo migration: testing undo/redo logic with zero UI. The new Gum.Presentation.Tests project references Gum.Presentation alone (no WPF/WinForms), so a green run proves the relocated UndoManager is fully headless.

Migrate the entire UndoManagerTests suite out of the WPF GumToolUnitTests into Gum.Presentation.Tests. All 20 tests port unchanged (only the namespace and base class move) — none secretly needed the tool. They reach UndoManager's internal UndoLocks, and that InternalsVisibleTo grant moved with the class, so the port is minimal-churn. Removed from GumToolUnitTests to avoid duplicates (git detects it as a rename).

Add 7 new tests covering core undo/redo branches the ported suite missed, all against mocked ports: empty-history early-outs (CanUndo/CanRedo/PerformUndo), the RequestLock defer-until-disposed contract, redo-stack truncation on a divergent edit, ClearAll, and the post-undo IFileCommands autosave interaction.

Add BaseTestClass + TestAssemblyInitialize (DisableTestParallelization, required because the suite uses the StandardElementsManager/ObjectFinder GumCommon singletons), mirroring the headless Gum.ProjectServices.Tests conventions.

Wire Gum.Presentation.Tests into AllLibraries.sln (under Tests) and add a Bucket-A CI step next to Gum.ProjectServices.Tests, so the suite keeps running in CI after leaving the GumToolUnitTests job. dotnet sln add also pulled Gum.Presentation in as a first-class AllLibraries project (nested under Tools to match its sibling Gum.ProjectServices). GumFull.sln and Gum.sln were already wired by the move PR (#3357).

Drop the now-dead InternalsVisibleTo("GumToolUnitTests") grant from Gum.Presentation.csproj — UndoLocks was the only internal it reached, and that suite moved. Verified: GumFull.sln still builds, GumToolUnitTests still compiles.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant