public override Tuple <IEnumerable <GraphAndUI <NodeUIData> >, IEnumerable <NodeGroup>, PointF, object> Duplicate(IEnumerable <ConversationNode> nodes, IEnumerable <NodeGroup> groups, IDataSource datasource) { var area = NodeSet.GetArea(nodes.Concat <IRenderable <IGui> >(groups)); PointF loc = (new PointF(50, 50)).Plus(area.Center()); using (MemoryStream m = new MemoryStream()) { CopyToStream(nodes, groups, m); m.Position = 0; var nodesAndGroups = ReadFromStream(datasource, m); return(Tuple.Create(nodesAndGroups.Item1, nodesAndGroups.Item2, loc, nodesAndGroups.Item3)); } }
public Tuple <IEnumerable <ConversationNode>, IEnumerable <NodeGroup> > InsertInto(IEnumerable <GraphAndUI <NodeUIData> > nodeData, IEnumerable <NodeGroup> groups, PointF location, ILocalizationEngine localization) { var nodes = nodeData.Select(gnu => MakeNode(gnu.GraphData, gnu.UIData)).Evaluate(); var area = NodeSet.GetArea(nodes.Concat <IRenderable <IGui> >(groups)); PointF offset = location.Take(area.Center()); foreach (var node in nodes) { node.Renderer.Offset(offset); } foreach (var group in groups) { group.Renderer.Offset(offset); } SimpleUndoPair addActions = InnerAddNodes(nodes, groups, localization); UndoableFile.Change(new GenericUndoAction(addActions, "Pasted")); return(Tuple.Create(nodes, groups)); }
//TODO: Duplicate the IEditable with a new ID (must be deep copy of parameters) public Tuple <IEnumerable <ConversationNode>, IEnumerable <NodeGroup> > DuplicateInto(IEnumerable <GraphAndUI <NodeUIData> > nodeData, IEnumerable <NodeGroup> groups, PointF location, ILocalizationEngine localization) { var nodes = nodeData.Select(gnu => MakeNode(gnu.GraphData, gnu.UIData)).Evaluate(); IEnumerable <IDynamicEnumParameter> localDynamicEnumerationParameters = nodes.SelectMany(n => n.Data.Parameters.OfType <IDynamicEnumParameter>().Where(p => p.Local)); foreach (var ldep in localDynamicEnumerationParameters) { ldep.MergeInto(m_getDocumentSource(ldep)); } if (nodes.Any() || groups.Any()) { List <Action> undoActions = new List <Action>(); List <Action> redoActions = new List <Action>(); //Changes to these nodes don't need to be undoable as they're new nodes foreach (var node in nodes) { //Duplicate the id of any localized string parameters to avoid the new node using the same id(s) as the old one foreach (var p in node.Data.Parameters.OfType <LocalizedStringParameter>()) { var result = localization.DuplicateActions(p.Value); var action = p.SetValueAction(result.Item1); if (action != null) { //Don't this node is a duplicate of another. The old node's localization data is irrelevant. We should never return to it. //undoActions.Add(action.Value.Undo); redoActions.Add(action.Value.Redo); action.Value.Redo(); //Change the value immediately. The old value is irrelevant and we should never return to it. } result.Item2.Redo(); //Add the localization immediately. Otherwise when adding the node we won't know how to undo deletion of the node's localization data. undoActions.Add(result.Item2.Undo); redoActions.Add(result.Item2.Redo); } //TODO: AUDIO: Do we want to treat audio parameters like strings in that they have a meaningful value // or like localized strings in that they are a key into another system? //foreach (var p in node.Data.Parameters.OfType<IAudioParameter>()) //{ // //No need to update audio usage as this will occur when the node is added/removed // var audio = m_generateAudio(this); // var actions = p.SetValueAction(audio); //TODO: AUDIO: Investigate what happens to Audio parameter usage if you duplicate a node and then undo // undoActions.Add(actions.Value.Undo); // redoActions.Add(actions.Value.Redo); //} //foreach (var p in node.Data.Parameters.OfType<IAudioParameter>()) //{ // var action = p.SetValueAction(new Audio(Guid.NewGuid().ToString())); // if (action != null) // action.Value.Redo(); //If we undo the whole operation the parameter wont exist so no need to ever undo this value change. //} var oldID = node.Data.NodeId; node.Data.ChangeId(Id <NodeTemp> .New()); foreach (var group in groups) { if (group.Contents.Contains(oldID)) { group.Contents.Remove(oldID); group.Contents.Add(node.Data.NodeId); } } } var area = NodeSet.GetArea(nodes.Concat <IRenderable <IGui> >(groups)); PointF offset = location.Take(area.Center()); foreach (var node in nodes) { node.Renderer.Offset(offset); } foreach (var group in groups) { group.Renderer.Offset(offset); } SimpleUndoPair addActions = InnerAddNodes(nodes, groups, localization); Action undo = () => { undoActions.ForEach(a => a()); addActions.Undo(); }; Action redo = () => { redoActions.ForEach(a => a()); addActions.Redo(); }; UndoableFile.Change(new GenericUndoAction(undo, redo, "Pasted")); } return(Tuple.Create(nodes, groups)); }