package com.horstmann.violet.workspace.editorpart.behavior;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoableEdit;
import com.horstmann.violet.product.diagram.abstracts.IGraph;
import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
import com.horstmann.violet.product.diagram.abstracts.node.INode;
import com.horstmann.violet.workspace.editorpart.IEditorPart;
/**
* Undo/Redo behavior triggered when node and edges are added
*
* @author Alexandre de Pellegrin
*
*/
public class UndoRedoOnAddBehavior extends AbstractEditorPartBehavior
{
/**
* The concerned workspace
*/
private IEditorPart editorPart;
/**
* The global undo/redo behavior which contains all individual undo/redo behaviors
*/
private UndoRedoCompoundBehavior compoundBehavior;
/**
* Keeps all the node attached to the graph before the add action
*/
private List<INode> nodesOnGraphBeforeAdd = new ArrayList<INode>();
/**
* Keeps all the edges attached to the graph before the add action
*/
private List<IEdge> edgesOnGraphBeforeAdd = new ArrayList<IEdge>();
/**
* Default constructor
* @param editorPart
* @param compoundBehavior
*/
public UndoRedoOnAddBehavior(IEditorPart editorPart, UndoRedoCompoundBehavior compoundBehavior)
{
this.editorPart = editorPart;
this.compoundBehavior = compoundBehavior;
}
@Override
public void beforeAddingNodeAtPoint(INode node, Point2D location)
{
this.nodesOnGraphBeforeAdd.clear();
this.edgesOnGraphBeforeAdd.clear();
this.nodesOnGraphBeforeAdd.addAll(this.editorPart.getGraph().getAllNodes());
this.edgesOnGraphBeforeAdd.addAll(this.editorPart.getGraph().getAllEdges());
}
@Override
public void afterAddingNodeAtPoint(final INode node, final Point2D location)
{
List<INode> nodesOnGraphAfterAction = new ArrayList<INode>(this.editorPart.getGraph().getAllNodes());
List<IEdge> edgesOnGraphAfterAction = new ArrayList<IEdge>(this.editorPart.getGraph().getAllEdges());
List<INode> nodesReallyAdded = new ArrayList<INode>();
nodesReallyAdded.addAll(nodesOnGraphAfterAction);
nodesReallyAdded.removeAll(this.nodesOnGraphBeforeAdd);
List<IEdge> edgesReallyAdded = new ArrayList<IEdge>();
edgesReallyAdded.addAll(edgesOnGraphAfterAction);
edgesReallyAdded.removeAll(this.edgesOnGraphBeforeAdd);
this.compoundBehavior.startHistoryCapture();
CompoundEdit capturedEdit = this.compoundBehavior.getCurrentCapturedEdit();
for (final INode aSelectedNode : nodesReallyAdded)
{
UndoableEdit edit = new AbstractUndoableEdit()
{
@Override
public void undo() throws CannotUndoException
{
IGraph graph = editorPart.getGraph();
graph.removeNode(aSelectedNode);
super.undo();
}
@Override
public void redo() throws CannotRedoException
{
super.redo();
IGraph graph = editorPart.getGraph();
graph.addNode(aSelectedNode, aSelectedNode.getLocationOnGraph());
}
};
capturedEdit.addEdit(edit);
}
for (final IEdge aSelectedEdge : edgesReallyAdded)
{
UndoableEdit edit = new AbstractUndoableEdit()
{
@Override
public void undo() throws CannotUndoException
{
IGraph graph = editorPart.getGraph();
graph.removeEdge(aSelectedEdge);
super.undo();
}
@Override
public void redo() throws CannotRedoException
{
super.redo();
IGraph graph = editorPart.getGraph();
graph.connect(aSelectedEdge, aSelectedEdge.getStartNode(), aSelectedEdge.getStartLocation(), aSelectedEdge.getEndNode(), aSelectedEdge.getEndLocation(), aSelectedEdge.getTransitionPoints());
}
};
capturedEdit.addEdit(edit);
}
this.compoundBehavior.stopHistoryCapture();
this.nodesOnGraphBeforeAdd.clear();
this.edgesOnGraphBeforeAdd.clear();
}
@Override
public void beforeAddingEdgeAtPoints(IEdge edge, Point2D startPoint, Point2D endPoint)
{
this.nodesOnGraphBeforeAdd.clear();
this.edgesOnGraphBeforeAdd.clear();
this.nodesOnGraphBeforeAdd.addAll(this.editorPart.getGraph().getAllNodes());
this.edgesOnGraphBeforeAdd.addAll(this.editorPart.getGraph().getAllEdges());
}
@Override
public void afterAddingEdgeAtPoints(final IEdge edge, final Point2D startPoint, final Point2D endPoint)
{
List<INode> nodesOnGraphAfterAction = new ArrayList<INode>(this.editorPart.getGraph().getAllNodes());
List<IEdge> edgesOnGraphAfterAction = new ArrayList<IEdge>(this.editorPart.getGraph().getAllEdges());
List<INode> nodesReallyAdded = new ArrayList<INode>();
nodesReallyAdded.addAll(nodesOnGraphAfterAction);
nodesReallyAdded.removeAll(this.nodesOnGraphBeforeAdd);
List<IEdge> edgesReallyAdded = new ArrayList<IEdge>();
edgesReallyAdded.addAll(edgesOnGraphAfterAction);
edgesReallyAdded.removeAll(this.edgesOnGraphBeforeAdd);
this.compoundBehavior.startHistoryCapture();
CompoundEdit capturedEdit = this.compoundBehavior.getCurrentCapturedEdit();
for (final INode aSelectedNode : nodesReallyAdded)
{
UndoableEdit edit = new AbstractUndoableEdit()
{
@Override
public void undo() throws CannotUndoException
{
IGraph graph = editorPart.getGraph();
graph.removeNode(aSelectedNode);
super.undo();
}
@Override
public void redo() throws CannotRedoException
{
super.redo();
IGraph graph = editorPart.getGraph();
graph.addNode(aSelectedNode, aSelectedNode.getLocationOnGraph());
}
};
capturedEdit.addEdit(edit);
}
for (final IEdge aSelectedEdge : edgesReallyAdded)
{
UndoableEdit edit = new AbstractUndoableEdit()
{
@Override
public void undo() throws CannotUndoException
{
IGraph graph = editorPart.getGraph();
graph.removeEdge(aSelectedEdge);
super.undo();
}
@Override
public void redo() throws CannotRedoException
{
super.redo();
IGraph graph = editorPart.getGraph();
graph.connect(aSelectedEdge, aSelectedEdge.getStartNode(), aSelectedEdge.getStartLocation(), aSelectedEdge.getEndNode(), aSelectedEdge.getEndLocation(), aSelectedEdge.getTransitionPoints());
}
};
capturedEdit.addEdit(edit);
}
this.compoundBehavior.stopHistoryCapture();
this.nodesOnGraphBeforeAdd.clear();
this.edgesOnGraphBeforeAdd.clear();
}
}