package com.horstmann.violet.workspace.editorpart.behavior;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import com.horstmann.violet.product.diagram.abstracts.IGridSticker;
import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
import com.horstmann.violet.workspace.editorpart.IEditorPart;
import com.horstmann.violet.workspace.editorpart.IEditorPartBehaviorManager;
import com.horstmann.violet.workspace.editorpart.IEditorPartSelectionHandler;
import com.horstmann.violet.workspace.sidebar.graphtools.GraphTool;
import com.horstmann.violet.workspace.sidebar.graphtools.IGraphToolsBar;
public class DragTransitionPointBehavior extends AbstractEditorPartBehavior
{
public DragTransitionPointBehavior(IEditorPart editorPart, IGraphToolsBar graphToolsBar)
{
this.editorPart = editorPart;
this.selectionHandler = editorPart.getSelectionHandler();
this.graphToolsBar = graphToolsBar;
this.behaviorManager = editorPart.getBehaviorManager();
}
@Override
public void onMousePressed(MouseEvent event)
{
if (event.getClickCount() > 1)
{
return;
}
if (event.getButton() != MouseEvent.BUTTON1)
{
return;
}
if (!isPrerequisitesOK())
{
return;
}
if (!isSelectedToolOK())
{
return;
}
double zoom = editorPart.getZoomFactor();
final Point2D mousePoint = new Point2D.Double(event.getX() / zoom, event.getY() / zoom);
isReadyForDragging = true;
// As transition points are added on dragging action but with the mouse
// location saved on onMousePressed, we look for transition points from
// this first mouse location
firstMousePoint = mousePoint;
lastMousePoint = mousePoint;
}
@Override
public void onMouseDragged(MouseEvent event)
{
if (!isReadyForDragging)
{
return;
}
if (this.edgeTransitionPointToDrag == null)
{
// As transition points are added on dragging action, we look for transition points from
// on dragging event too
this.edgeTransitionPointToDrag = getEdgeTransitionPointToDrag();
if (this.edgeTransitionPointToDrag != null)
{
startUndoRedoCapture();
}
}
if (this.edgeTransitionPointToDrag == null)
{
return;
}
double zoom = editorPart.getZoomFactor();
Point2D mousePoint = new Point2D.Double(event.getX() / zoom, event.getY() / zoom);
double dx = mousePoint.getX() - lastMousePoint.getX();
double dy = mousePoint.getY() - lastMousePoint.getY();
IGridSticker gridSticker = editorPart.getGraph().getGridSticker();
// Drag specific transition point on selected edge
if (this.edgeTransitionPointToDrag != null)
{
double newTransitionPointLocationX = this.edgeTransitionPointToDrag.getX() + dx;
double newTransitionPointLocationY = this.edgeTransitionPointToDrag.getY() + dy;
Point2D newTransitionPoint = new Point2D.Double(newTransitionPointLocationX, newTransitionPointLocationY);
newTransitionPoint = gridSticker.snap(newTransitionPoint);
this.edgeTransitionPointToDrag.setLocation(newTransitionPoint.getX(), newTransitionPoint.getY());
// Save mouse location for next dragging sequence
Point2D snappedMousePoint = gridSticker.snap(mousePoint);
if (!snappedMousePoint.equals(lastMousePoint)) {
editorPart.getSwingComponent().invalidate();
editorPart.getSwingComponent().repaint();
}
lastMousePoint = snappedMousePoint;
return;
}
}
@Override
public void onMouseReleased(MouseEvent event)
{
stopUndoRedoCapture();
firstMousePoint = null;
lastMousePoint = null;
isReadyForDragging = false;
selectedEdge = null;
edgeTransitionPointToDrag = null;
}
private IEdge getSelectedEdge()
{
if (this.selectedEdge == null)
{
if (this.selectionHandler.getSelectedEdges().size() == 1)
{
this.selectedEdge = this.selectionHandler.getSelectedEdges().get(0);
}
}
return this.selectedEdge;
}
private boolean isPrerequisitesOK()
{
if (getSelectedEdge() == null)
{
return false;
}
if (getSelectedEdge().isTransitionPointsSupported())
{
return true;
}
return false;
}
private boolean isSelectedToolOK()
{
if (getSelectedEdge() == null)
{
return false;
}
GraphTool selectedTool = this.graphToolsBar.getSelectedTool();
if (GraphTool.SELECTION_TOOL.equals(selectedTool))
{
return true;
}
if (selectedTool.getNodeOrEdge().getClass().isInstance(getSelectedEdge()))
{
return true;
}
return false;
}
private Point2D getEdgeTransitionPointToDrag()
{
if (getSelectedEdge() == null)
{
return null;
}
if (!getSelectedEdge().isTransitionPointsSupported())
{
return null;
}
final double MAX_DIST = 5;
for (Point2D aTransitionPoint : getSelectedEdge().getTransitionPoints())
{
if (aTransitionPoint.distance(this.firstMousePoint) <= MAX_DIST)
{
return aTransitionPoint;
}
}
return null;
}
private void startUndoRedoCapture()
{
if (getSelectedEdge() == null)
{
return;
}
this.behaviorManager.fireBeforeChangingTransitionPointsOnEdge(getSelectedEdge());
}
private void stopUndoRedoCapture()
{
if (getSelectedEdge() == null)
{
return;
}
this.behaviorManager.fireAfterChangingTransitionPointsOnEdge(getSelectedEdge());
}
private IEditorPartBehaviorManager behaviorManager;
private Point2D firstMousePoint = null;
private Point2D lastMousePoint = null;
private IEditorPartSelectionHandler selectionHandler;
private IEditorPart editorPart;
private IGraphToolsBar graphToolsBar;
private boolean isReadyForDragging = false;
private Point2D edgeTransitionPointToDrag = null;
private IEdge selectedEdge = null;
}