Exemple #1
0
        //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));
        }