package com.horstmann.violet.workspace.editorpart.behavior; import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import java.beans.PropertyChangeEvent; import java.util.ArrayList; import java.util.List; import javax.swing.undo.CompoundEdit; import javax.swing.undo.UndoManager; import com.horstmann.violet.product.diagram.abstracts.IColorable; 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; /** * This behavior for undo/redo actions is composed of sub-behaviors * * @author Alexandre de Pellegrin * */ public class UndoRedoCompoundBehavior extends AbstractEditorPartBehavior { /** * The concerned workspace */ private IEditorPart editorPart; /** * Current composed undoable edit */ private CompoundEdit currentCapturedEdit; /** * Undo/redo manager */ private UndoManager undoManager = new UndoManager(); /** * List of individual undo/redo behaviors */ private List<IEditorPartBehavior> behaviors = new ArrayList<IEditorPartBehavior>(); /** * Default constructor * @param editorPart */ public UndoRedoCompoundBehavior(IEditorPart editorPart) { this.editorPart = editorPart; behaviors.add(new UndoRedoOnAddBehavior(editorPart, this)); behaviors.add(new UndoRedoOnDragBehavior(editorPart, this)); behaviors.add(new UndoRedoOnEditBehavior(this)); behaviors.add(new UndoRedoOnRemoveBehavior(editorPart, this)); behaviors.add(new UndoRedoOnTransitionPointChangeBehavior(this)); behaviors.add(new UndoRedoOnColorizeBehavior(this)); } @Override public void onMousePressed(MouseEvent event) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.onMousePressed(event); } } @Override public void onMouseDragged(MouseEvent event) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.onMouseDragged(event); } } @Override public void onMouseReleased(MouseEvent event) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.onMouseReleased(event); } } @Override public void beforeRemovingSelectedElements() { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.beforeRemovingSelectedElements(); } } @Override public void afterRemovingSelectedElements() { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.afterRemovingSelectedElements(); } } @Override public void beforeAddingNodeAtPoint(INode node, Point2D location) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.beforeAddingNodeAtPoint(node, location); } } @Override public void afterAddingNodeAtPoint(final INode node, final Point2D location) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.afterAddingNodeAtPoint(node, location); } } @Override public void beforeAddingEdgeAtPoints(IEdge edge, Point2D startPoint, Point2D endPoint) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.beforeAddingEdgeAtPoints(edge, startPoint, endPoint); } } @Override public void afterAddingEdgeAtPoints(final IEdge edge, final Point2D startPoint, final Point2D endPoint) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.afterAddingEdgeAtPoints(edge, startPoint, endPoint); } } @Override public void beforeChangingTransitionPointsOnEdge(IEdge edge) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.beforeChangingTransitionPointsOnEdge(edge); } } @Override public void afterChangingTransitionPointsOnEdge(IEdge edge) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.afterChangingTransitionPointsOnEdge(edge); } } @Override public void beforeChangingColorOnElement(IColorable element) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.beforeChangingColorOnElement(element); } } @Override public void afterChangingColorOnElement(IColorable element) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.afterChangingColorOnElement(element); } } @Override public void beforeEditingNode(INode node) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.beforeEditingNode(node); } } @Override public void whileEditingNode(INode node, PropertyChangeEvent event) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.whileEditingNode(node, event); } } @Override public void afterEditingNode(INode node) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.afterEditingNode(node); } } @Override public void beforeEditingEdge(IEdge edge) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.beforeEditingEdge(edge); } } @Override public void whileEditingEdge(IEdge edge, final PropertyChangeEvent event) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.whileEditingEdge(edge, event); } } @Override public void afterEditingEdge(IEdge edge) { for (IEditorPartBehavior aBehavior : this.behaviors) { aBehavior.afterEditingEdge(edge); } } /** * Restores previous graph action from the history cursor location */ public void undo() { if (undoManager.canUndo()) { undoManager.undo(); editorPart.getSwingComponent().invalidate(); editorPart.getSwingComponent().repaint(); } } /** * Restores next graph action from the history cursor location */ public void redo() { if (undoManager.canRedo()) { undoManager.redo(); editorPart.getSwingComponent().invalidate(); editorPart.getSwingComponent().repaint(); } } /** * Starts capturing actions on graph */ protected void startHistoryCapture() { if (this.currentCapturedEdit == null) { this.currentCapturedEdit = new CompoundEdit(); } } /** * @return current composed undoable edit */ protected CompoundEdit getCurrentCapturedEdit() { return this.currentCapturedEdit; } /** * Stops capturing actions on graph and adds an entry to history */ protected void stopHistoryCapture() { if (this.currentCapturedEdit == null) return; this.currentCapturedEdit.end(); this.undoManager.addEdit(this.currentCapturedEdit); this.currentCapturedEdit = null; } }