Gum Delete Logic Reference

SkillDev tools

Gum delete architecture. Triggers: delete commands, IEditCommands delete methods, IDeleteLogic, DeleteLogic, DeleteOptionsWindow, HandleDeleteCommand, AskToDeleteState, AskToDeleteStateCategory, DeleteSelection.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Gum Delete Logic Reference skill

What this skill tells your AI

The instructions your AI receives, as published by vchelaru/gum in .claude/skills/gum-tool-delete-logic/SKILL.md and read by ahel’s review.

Two Delete Patterns

There are two distinct delete flows depending on the object type being deleted.

Pattern 1 — AskTo* (states and categories)

Used for states and state categories. These types have blocking conditions that must be checked before any dialog is shown, so they have their own typed methods on IEditCommands.

Flow: IEditCommands.AskTo* → validate (behavior deps, plugin hooks, default-state check) → simple Yes/No dialog → undo lock → IDeleteLogic.Remove*

Entry points:

  • IEditCommands.AskToDeleteState(stateSave, stateContainer)
  • IEditCommands.AskToDeleteStateCategory(category, container)

Why not DeleteOptionsWindow: States and categories are in-memory only — no XML files, no child hierarchy — so plugins have nothing to contribute to the delete dialog.

Pattern 2 — DeleteSelection (elements, behaviors, instances)

Used for screens, components, behaviors, and instances. All go through one shared entry point that dispatches based on what is currently selected.

Flow: IEditCommands.DeleteSelection → undo lock → IDeleteLogic.HandleDeleteCommandDoDeletingLogicShowDeleteDialog (creates DeleteOptionsWindow) → IDeleteLogic.Remove*

Entry point: IEditCommands.DeleteSelection()

Why DeleteOptionsWindow: Plugins contribute runtime UI to this dialog (e.g. DeleteObjectPlugin adds "Delete XML file?" and "Delete children?" options via the DeleteOptionsWindowShow plugin event).

Responsibility Split

ClassResponsibility
IEditCommands / EditCommandsAll user-triggered deletes. Shows dialogs, acquires undo locks, then delegates to IDeleteLogic. Only entry point callers should use.
IDeleteLogic / DeleteLogicPure data mutation after confirmation. Remove* methods do not show dialogs. HandleDeleteCommand is the exception — it orchestrates the DeleteOptionsWindow flow and is only called from EditCommands.DeleteSelection.

Contributing an option to DeleteOptionsWindow

DeleteOptionsWindowShow and DeleteConfirmed are declared on WpfPluginBase, not PluginBase — a plugin contributing a delete option must derive from it.

Both fire once per batch with the full objectsToDelete array, while ElementDelete fires once per element. Their relative order is not stable either: NotifyConfirmed runs before removal in PerformConfirmedMixedTypeDelete and after it in DoDeletingLogic's elements-only branch. Keep both handlers pure functions of the element rather than relying on ordering across them.

A checkbox cached in a plugin field leaks state across deletes: a cancelled delete never fires DeleteConfirmed, and DeleteOptionsWindow.CloseWithResultFalse clears MainStackPanel.Children without touching the plugin's field, so the next delete reads a stale checked value. Reset the field at the top of DeleteOptionsWindowShow.

Post-delete selection

After removing instances, selection must fall back to a surviving sibling → parent instance → owning element, or the editor goes blank. Both the single-instance (PerformConfirmedSingleInstanceDelete) and multi-instance (PerformConfirmedMixedTypeDelete) paths funnel through one helper, SelectAfterInstanceRemoval.

Callers

All delete actions funnel through IEditCommands:

  • Delete keyHotkeyManagerIEditCommands.DeleteSelection
  • Element tree right-click DeleteElementTreeViewManagerIEditCommands.DeleteSelection
  • State tree right-click Delete stateStateTreeViewRightClickServiceIEditCommands.AskToDeleteState
  • State tree right-click Delete categoryStateTreeViewRightClickServiceIEditCommands.AskToDeleteStateCategory
  • Menu strip Remove > ElementMenuStripManagerIEditCommands.DeleteSelection
  • Menu strip Remove > State/CategoryMenuStripManagerIEditCommands.AskToDeleteState / AskToDeleteStateCategory

Do not call IDeleteLogic methods directly from UI code — always go through IEditCommands.

Testability

DeleteLogic (headless, Tools/Gum.Presentation/Managers/DeleteLogic.cs) delegates dialog display to the WPF-shell IDeleteDialogService, whose implementation DeleteDialogService (Gum/Services/Dialogs/DeleteDialogService.cs) creates the DeleteOptionsWindow and calls ShowDialog() — that class cannot be unit-tested directly. The internal BuildDeleteDialogMessage(Array, List<InstanceSave>?) method on DeleteLogic is the testable seam for asserting dialog message content (InternalsVisibleTo("GumToolUnitTests") is already configured).

Key Files

FilePurpose
Gum/Commands/IEditCommands.csInterface with architecture overview comment
Gum/Commands/EditCommands.csImplementation; AskTo* dialog logic lives here
Tools/Gum.Presentation/Managers/IDeleteLogic.csInterface for pure data-mutation operations
Tools/Gum.Presentation/Managers/DeleteLogic.csData mutation + delete-dialog orchestration via IDeleteDialogService
Gum/Services/Dialogs/DeleteDialogService.csWPF shell: creates/shows DeleteOptionsWindow, calls the concrete PluginManager
Tools/Gum.Presentation/Logic/ReferenceTypes.csElementReferences class; GetDeleteImpactDetails() and ExcludeContainersBeingDeleted() used to build impact warnings in the delete dialog
Tools/Gum.Presentation/Logic/ReferenceFinder.csGetReferencesToVariable() — enumerates every instance-level assignment of a variable project-wide, including through the inheritance chain; used by DeleteVariableService.GetIfCanDeleteVariable to block variable deletes today
Gum/Plugins/InternalPlugins/Delete/DeleteObjectPlugin.csContributes "Delete XML?" and "Delete children?" to DeleteOptionsWindow
Gum/Plugins/InternalPlugins/StatePlugin/StateTreeViewRightClickService.csState/category right-click menu; calls AskTo* methods
Gum/Plugins/InternalPlugins/TreeView/ElementTreeViewManager.RightClick.csElement tree right-click; calls DeleteSelection
Gum/Managers/HotkeyManager.csDelete key handler; calls DeleteSelection

Signals

GitHub stars
620
Forks
80
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
gum-tool-delete-logic
Source
github.com/vchelaru/gum