gum-tool-copy-paste

$npx mdskill add vchelaru/Gum/gum-tool-copy-paste

Manage Gum's in-memory copy/paste logic without system clipboard.

  • Handles copying, cutting, and pasting within Gum's instance system.
  • Depends on CopyPasteLogic, ICopyPasteLogic, and IDeleteLogic APIs.
  • Uses CopyType to determine valid operations and bail early.
  • Executes immediate deletion for cut actions via RemoveInstance.

SKILL.md

.github/skills/gum-tool-copy-pasteView on GitHub ↗
---
name: gum-tool-copy-paste
description: Reference guide for Gum's copy/paste system. Load this when working on CopyPasteLogic, ICopyPasteLogic, OnCopy, OnPaste, OnCut, PasteInstanceSaves, CopiedData, clipboard behavior, or multi-paste selection tracking.
---

# Gum Copy/Paste Reference

## In-Memory, Not System Clipboard

Gum's copy/paste does **not** use the system clipboard. Copied data lives in `CopyPasteLogic.CopiedData` (an in-memory instance). `MonoGameGum/Clipboard/ClipboardImplementation.cs` is a separate text-only clipboard used elsewhere in the app — not part of this system.

## CopyType Dispatch

`CopyType` drives the entire operation:
- `InstanceOrElement` — copies selected instances within an element, or a whole element if nothing is selected
- `State` — copies the selected state within a state category

Copy, cut, and paste each accept a `CopyType` parameter and bail out early if it doesn't match what's stored.

## TopOrRecursive

Paste offers two modes: `Recursive` (instances + all descendants) vs `Top` (only top-level instances). The UI exposes both as separate "Paste" and "Paste Top Level Instance(s)" menu items.

## Cut Is Immediate

Cut calls `StoreCopiedObject()` (same as copy) then immediately deletes the source instances via `IDeleteLogic.RemoveInstance()`. The deletion happens at cut time, not deferred to paste. This means cutting and then not pasting still destroys the original.

## Multi-Paste Selection Tracking

`_hasChangedSelectionSinceCopy` is the key flag for multi-paste behavior. It starts `false` after a copy and flips `true` when `SelectionChangedMessage` fires (unless the selection change was triggered by the paste itself — `isSelectionCausedByPaste` guards against that false-positive).

During paste, this flag drives parent assignment:
- `false` — re-use the parent from `lastPasteOriginalToParentAssociation` (repeat-paste to same location)
- `true` — attach to current selection (user moved to a new target)

## Paste Creates New Instances, Does Not Clone

`PasteInstanceSaves()` creates fresh `InstanceSave` objects and assigns properties from the copied states. It does **not** simply clone the stored instances. Name uniqueness is enforced via `StringFunctions.MakeStringUnique()`, and an `oldNewNameDictionary` is built to remap parent references throughout the copied hierarchy.

## Undo Integration

Only paste acquires an undo lock (`_undoManager.RequestLock()`). The entire paste — all instances, state variable copies, parent assignments — records as a single undo action. Cut's deletion goes through `IDeleteLogic.RemoveInstance()` which handles its own undo internally.

## State Paste Validation

Pasting a state runs `ValidateStatePaste()` first. It checks that all variables in the copied state exist in the target category and are supported by the target element. Paste is silently blocked (or shows a dialog) if incompatible.

## Plugin Hook

`PluginManager.InstanceAdd()` is called for each newly pasted instance, allowing plugins to react to paste-created instances the same way they react to manually added ones.

## Animation Copy/Paste

`AnimationCopyPasteManager.cs` is a **separate, independent** copy/paste system for animations. It has its own `CopiedData` class, stores a single `AnimationViewModel`, and does not interact with `CopyPasteLogic`.

## Entry Points

All copy/paste is triggered through:
- `HotkeyManager` — routes `Ctrl+C / Ctrl+X / Ctrl+V` → `ICopyPasteLogic.OnCopy / OnCut / OnPaste`
- `ElementTreeViewManager.RightClick` — right-click context menu items

Do not call `CopyPasteLogic` methods directly from outside these entry points.

## Key Files

| File | Purpose |
|------|---------|
| `Gum/Logic/CopyPasteLogic.cs` | All copy/paste orchestration; `CopiedData` nested class defined here |
| `Gum/Logic/ICopyPasteLogic.cs` | Interface |
| `Gum/Commands/EditCommands.cs` | Thin wrappers that delegate to `ICopyPasteLogic` |
| `Gum/Managers/HotkeyManager.cs` | Keyboard entry point |
| `Gum/Plugins/InternalPlugins/TreeView/ElementTreeViewManager.RightClick.cs` | Context menu entry point |
| `Gum/StateAnimationPlugin/Managers/AnimationCopyPasteManager.cs` | Separate animation copy/paste |
| `Tool/Tests/GumToolUnitTests/Logic/CopyPasteLogicTests.cs` | Unit tests |

More from vchelaru/Gum

SkillDescription
bump-nuget-versionBump the NuGet package versions for all 12 Gum projects (11 libraries + GumCli). Queries NuGet to check if a version exists for today, then sets the new version to YYYY.M.D.V where V increments from the latest published version today (or starts at 1). Creates a release branch named ReleaseCode_YYYY_M_D_V, commits the changes, and pushes. Run this before triggering the nuget release workflow.
gum-cliReference guide for GumCli — the headless command-line tool for Gum projects. Load this when working on gumcli commands (new, check, codegen, codegen-init), Gum.ProjectServices, HeadlessErrorChecker, ProjectLoader, HeadlessCodeGenerationService, CodeGenerationAutoSetupService, or the FormsTemplateCreator.
gum-docs-writingReference guide for writing Gum documentation in GitBook markdown. Load when writing or editing docs/ files, adding pages to SUMMARY.md, using GitBook hints/figures, linking between pages, or adding images.
gum-forms-behaviorsCovers Gum's behaviors system and the design-time → runtime Forms wrapping lifecycle. Load this when working on BehaviorSave, ElementBehaviorReference, StandardFormsBehaviorNames, FormsUtilities.RegisterFromFileFormRuntimeDefaults, DefaultFromFileXxxRuntime classes, or when investigating why Forms properties cannot be set at design time in the Gum tool.
gum-forms-controlsReference guide for Forms controls — classes inheriting from FrameworkElement. Load this when working on Button, CheckBox, ListBox, ComboBox, TextBox, ScrollViewer, or any class in Gum.Forms.Controls (or FlatRedBall.Forms.Controls). Also load when working on FrameworkElement itself, the Visual/InteractiveGue relationship, state machines, DefaultVisuals, or ReactToVisualChanged.
gum-forms-default-visualsReference guide for Forms DefaultVisuals — the code-only visual classes that back Forms controls. Load when working on ButtonVisual, any *Visual class in DefaultVisuals/, Styling, DefaultFormsTemplates registration, or building custom code-only Forms visuals.
gum-forms-itemscontrolReference guide for ItemsControl and ListBox — the Items/ListBoxItems relationship, templates, InnerPanel sync, and gotchas. Load this when working on ItemsControl, ListBox, ListBoxItem, VisualTemplate, FrameworkElementTemplate, Items collection behavior, ListBoxItems desync, or adding/removing items from a list box.
gum-layout>
gum-layout-engine>
gum-localizationReference guide for Gum's runtime localization system — ILocalizationService, CSV/RESX loading, Text vs TextNoTranslate paths, Forms control localization patterns, and gotchas.