package com.horstmann.violet.workspace.editorpart.behavior;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import javax.swing.SwingUtilities;
import com.horstmann.violet.framework.util.KeyModifierUtil;
import com.horstmann.violet.product.diagram.abstracts.IGraph;
import com.horstmann.violet.product.diagram.abstracts.IGridSticker;
import com.horstmann.violet.product.diagram.abstracts.Id;
import com.horstmann.violet.product.diagram.abstracts.node.INode;
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;
import com.horstmann.violet.workspace.sidebar.graphtools.IGraphToolsBarMouseListener;
public class AddNodeBehavior extends AbstractEditorPartBehavior implements IGraphToolsBarMouseListener
{
private static final int OUTSIDE_SCREEN_POSITION = -1000;
public AddNodeBehavior(IEditorPart editorPart, IGraphToolsBar graphToolsBar)
{
this.editorPart = editorPart;
this.graph = editorPart.getGraph();
this.selectionHandler = editorPart.getSelectionHandler();
this.behaviorManager = editorPart.getBehaviorManager();
this.graphToolsBar = graphToolsBar;
this.dragging = false;
this.draggedNode = null;
graphToolsBar.addMouseListener(this);
}
@Override
public void onMouseClicked(MouseEvent event)
{
this.draggedNode = null;
if (event.getClickCount() > 1)
{
return;
}
if (event.getButton() != MouseEvent.BUTTON1) {
return;
}
if (GraphTool.SELECTION_TOOL.equals(this.graphToolsBar.getSelectedTool()))
{
return;
}
GraphTool selectedTool = this.selectionHandler.getSelectedTool();
if (!INode.class.isInstance(selectedTool.getNodeOrEdge()))
{
return;
}
double zoom = editorPart.getZoomFactor();
final Point2D mousePoint = new Point2D.Double(event.getX() / zoom, event.getY() / zoom);
IGridSticker gridSticker = graph.getGridSticker();
Point2D newNodeLocation = gridSticker.snap(mousePoint);
INode prototype = (INode) selectedTool.getNodeOrEdge();
INode newNode = (INode) prototype.clone();
newNode.setId(new Id());
boolean added = addNodeAtPoint(newNode, newNodeLocation);
if (added)
{
selectionHandler.setSelectedElement(newNode);
if (!KeyModifierUtil.isCtrl(event)) {
selectionHandler.setSelectedTool(GraphTool.SELECTION_TOOL);
graphToolsBar.setSelectedTool(GraphTool.SELECTION_TOOL);
graphToolsBar.getAWTComponent().invalidate();
}
editorPart.getSwingComponent().invalidate();
}
}
/**
* Adds a new at a precise location
*
* @param newNode to be added
* @param location
* @return true if the node_old has been added
*/
public boolean addNodeAtPoint(INode newNode, Point2D location)
{
boolean isAdded = false;
this.behaviorManager.fireBeforeAddingNodeAtPoint(newNode, location);
try
{
if (graph.addNode(newNode, location))
{
newNode.incrementRevision();
isAdded = true;
}
}
finally
{
this.behaviorManager.fireAfterAddingNodeAtPoint(newNode, location);
}
return isAdded;
}
private IEditorPart editorPart;
private IGraph graph;
private IEditorPartSelectionHandler selectionHandler;
private IEditorPartBehaviorManager behaviorManager;
private IGraphToolsBar graphToolsBar;
private boolean dragging;
private INode draggedNode;
@Override
public void onMouseToolClicked(GraphTool selectedTool)
{
Object obj = selectedTool.getNodeOrEdge();
if (obj instanceof INode)
{
this.dragging = true;
INode prototype = (INode) selectedTool.getNodeOrEdge();
this.draggedNode = (INode) prototype.clone();
this.draggedNode.setId(new Id());
double zoom = editorPart.getZoomFactor();
final Point2D initialLocation = new Point2D.Double(OUTSIDE_SCREEN_POSITION / zoom, OUTSIDE_SCREEN_POSITION / zoom);
IGridSticker gridSticker = graph.getGridSticker();
Point2D newNodeLocation = gridSticker.snap(initialLocation);
boolean added = addNodeAtPoint(this.draggedNode, newNodeLocation);
if (added)
{
selectionHandler.setSelectedElement(this.draggedNode);
editorPart.getSwingComponent().invalidate();
}
}
}
@Override
public void onMouseToolDragged(MouseEvent event)
{
if (this.dragging) {
MouseEvent outEvent = SwingUtilities.convertMouseEvent((Component)event.getSource(), event, editorPart.getSwingComponent());
moveDraggedNode(outEvent);
}
}
@Override
public void onMouseToolReleased(MouseEvent event)
{
this.dragging = false;
if (this.draggedNode != null) {
MouseEvent outEvent = SwingUtilities.convertMouseEvent((Component)event.getSource(), event, editorPart.getSwingComponent());
if (outEvent.getX() < 0 || outEvent.getY() < 0) {
this.graph.removeNode(this.draggedNode);
editorPart.getSwingComponent().invalidate();
editorPart.getSwingComponent().repaint();
} else {
moveDraggedNode(outEvent);
}
this.draggedNode = null;
}
}
private void moveDraggedNode(MouseEvent convertedEvent) {
double zoom = editorPart.getZoomFactor();
final Point2D mousePoint = new Point2D.Double(convertedEvent.getX() / zoom, convertedEvent.getY() / zoom);
IGridSticker gridSticker = graph.getGridSticker();
Point2D newNodeLocation = gridSticker.snap(mousePoint);
draggedNode.setLocation(newNodeLocation);
selectionHandler.setSelectedElement(this.draggedNode);
editorPart.getSwingComponent().invalidate();
editorPart.getSwingComponent().repaint();
}
}