internal static void PasteSerializedData(IGraphModel graph, Vector2 delta, GraphViewStateComponent.StateUpdater graphViewUpdater, SelectionStateComponent.StateUpdater selectionStateUpdater, CopyPasteData copyPasteData) { var elementMapping = new Dictionary <string, IGraphElementModel>(); if (copyPasteData.variableDeclarations.Any()) { List <IVariableDeclarationModel> variableDeclarationModels = copyPasteData.variableDeclarations.ToList(); List <IVariableDeclarationModel> duplicatedModels = new List <IVariableDeclarationModel>(); foreach (var sourceModel in variableDeclarationModels) { duplicatedModels.Add(graph.DuplicateGraphVariableDeclaration(sourceModel)); } graphViewUpdater?.MarkNew(duplicatedModels); selectionStateUpdater?.SelectElements(duplicatedModels, true); } var nodeMapping = new Dictionary <INodeModel, INodeModel>(); foreach (var originalModel in copyPasteData.nodes) { if (!graph.Stencil.CanPasteNode(originalModel, graph)) { continue; } var pastedNode = graph.DuplicateNode(originalModel, delta); graphViewUpdater?.MarkNew(pastedNode); selectionStateUpdater?.SelectElements(new[] { pastedNode }, true); nodeMapping[originalModel] = pastedNode; } // PF FIXME we could do this in the foreach above foreach (var nodeModel in nodeMapping) { elementMapping.Add(nodeModel.Key.Guid.ToString(), nodeModel.Value); } foreach (var edge in copyPasteData.edges) { elementMapping.TryGetValue(edge.ToPort.NodeModel.Guid.ToString(), out var newInput); elementMapping.TryGetValue(edge.FromPort.NodeModel.Guid.ToString(), out var newOutput); var copiedEdge = graph.DuplicateEdge(edge, newInput as INodeModel, newOutput as INodeModel); if (copiedEdge != null) { elementMapping.Add(edge.Guid.ToString(), copiedEdge); graphViewUpdater?.MarkNew(copiedEdge); selectionStateUpdater?.SelectElements(new[] { copiedEdge }, true); } } foreach (var stickyNote in copyPasteData.stickyNotes) { var newPosition = new Rect(stickyNote.PositionAndSize.position + delta, stickyNote.PositionAndSize.size); var pastedStickyNote = graph.CreateStickyNote(newPosition); pastedStickyNote.Title = stickyNote.Title; pastedStickyNote.Contents = stickyNote.Contents; pastedStickyNote.Theme = stickyNote.Theme; pastedStickyNote.TextSize = stickyNote.TextSize; graphViewUpdater?.MarkNew(pastedStickyNote); selectionStateUpdater?.SelectElements(new[] { pastedStickyNote }, true); elementMapping.Add(stickyNote.Guid.ToString(), pastedStickyNote); } List <IPlacematModel> pastedPlacemats = new List <IPlacematModel>(); // Keep placemats relative order foreach (var placemat in copyPasteData.placemats.OrderBy(p => p.ZOrder)) { var newPosition = new Rect(placemat.PositionAndSize.position + delta, placemat.PositionAndSize.size); var newTitle = "Copy of " + placemat.Title; var pastedPlacemat = graph.CreatePlacemat(newPosition); pastedPlacemat.Title = newTitle; pastedPlacemat.Color = placemat.Color; pastedPlacemat.Collapsed = placemat.Collapsed; pastedPlacemat.HiddenElements = placemat.HiddenElements; graphViewUpdater?.MarkNew(pastedPlacemat); selectionStateUpdater?.SelectElements(new[] { pastedPlacemat }, true); pastedPlacemats.Add(pastedPlacemat); elementMapping.Add(placemat.Guid.ToString(), pastedPlacemat); } // Update hidden content to new node ids. foreach (var pastedPlacemat in pastedPlacemats) { if (pastedPlacemat.Collapsed) { List <IGraphElementModel> pastedHiddenContent = new List <IGraphElementModel>(); foreach (var elementGUID in pastedPlacemat.HiddenElements.Select(t => t.Guid.ToString())) { if (elementMapping.TryGetValue(elementGUID, out var pastedElement)) { pastedHiddenContent.Add(pastedElement); } } pastedPlacemat.HiddenElements = pastedHiddenContent; } } }