@@ -78,7 +78,7 @@ struct AboutCommands: Commands {
7878struct DocumentCommands : Commands
7979{
8080 @FocusedBinding ( \. document) var document : FabricDocument ?
81-
81+
8282 var body : some Commands {
8383 CommandGroup ( before: . pasteboard)
8484 {
@@ -91,6 +91,38 @@ struct DocumentCommands:Commands
9191 . keyboardShortcut ( KeyEquivalent ( " a " ) , modifiers: . command)
9292 . disabled ( self . document? . graph. nodes. isEmpty ?? true )
9393 }
94+
95+ CommandGroup ( replacing: . pasteboard)
96+ {
97+ let graph = self . document? . graph. activeSubGraph ?? self . document? . graph
98+ let hasSelection = graph? . nodes. contains ( where: { $0. isSelected } ) ?? false
99+ let hasPasteData = NSPasteboard . general. data ( forType: Graph . nodeClipboardType) != nil
100+
101+ Button ( " Copy " )
102+ {
103+ guard let graph else { return }
104+ let selected = graph. nodes. filter { $0. isSelected }
105+ graph. copyNodesToPasteboard ( selected)
106+ }
107+ . keyboardShortcut ( " c " , modifiers: . command)
108+ . disabled ( !hasSelection)
109+
110+ Button ( " Paste " )
111+ {
112+ graph? . pasteNodesFromPasteboard ( )
113+ }
114+ . keyboardShortcut ( " v " , modifiers: . command)
115+ . disabled ( !hasPasteData)
116+
117+ Button ( " Duplicate " )
118+ {
119+ guard let graph else { return }
120+ let selected = graph. nodes. filter { $0. isSelected }
121+ graph. duplicateNodes ( selected)
122+ }
123+ . keyboardShortcut ( " d " , modifiers: . command)
124+ . disabled ( !hasSelection)
125+ }
94126 }
95127}
96128
0 commit comments