// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
package graphtea.plugins.main.core.actions.edge;
import graphtea.graph.GraphUtils;
import graphtea.graph.atributeset.GraphAttrSet;
import graphtea.graph.event.GraphEvent;
import graphtea.graph.event.VertexEvent;
import graphtea.graph.graph.*;
import graphtea.graph.old.AcceleratedRenderer;
import graphtea.graph.old.GStroke;
import graphtea.library.util.Pair;
import graphtea.platform.core.AbstractAction;
import graphtea.platform.core.BlackBoard;
import graphtea.plugins.main.select.Select;
import graphtea.plugins.main.select.SelectPluginMethods;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* @author azin azadi
*/
public class AddEdge extends AbstractAction implements PaintHandler {
// private double lasty;
// private double lastx;
private GPoint lastPos;
private SelectPluginMethods selMethods;
/**
* constructor
*
* @param bb the blackboard of the action
*/
public AddEdge(BlackBoard bb) {
super(bb);
selMethods = new SelectPluginMethods(bb);
listen4Event(VertexEvent.EVENT_KEY);
// listen4Event(GraphEvent.name);
// listen4Event(VertexDropData.event);
// listen4Event(VertexSelectData.name);
}
protected Vertex v1, vc1;
protected GraphModel g;
protected AbstractGraphRenderer gv;
protected boolean isClick = false;
protected boolean isDrag = false;
/**
* used for determining whether user has exited a vertex while dragging
*/
boolean exitedFromV1;
public void track(){}
public void performAction(String eventName, Object value) {
// our old lovely Add Edge
// if (name == VertexSelectData.name) {
// VertexSelectData vsd = blackboard.getLog(VertexSelectData.name).getLast();
// if (!isClick) {
// vc1 = vsd.v;
// v1=vc1;
// startPainting();
// } else {
// Vertex v2=vsd.v;
// Edge e = doJob(v2.g, v2, vc1);
// addUndoData(e);
// stopPainting();
// }
// isClick=true;
// isDrag=false;
// }
VertexEvent ve = blackboard.getData(VertexEvent.EVENT_KEY);
if ((ve.modifiers & MouseEvent.SHIFT_DOWN_MASK) == MouseEvent.SHIFT_DOWN_MASK)
return;
SubGraph sd = Select.getSelection(blackboard);
g = blackboard.getData(GraphAttrSet.name);
gv = blackboard.getData(AbstractGraphRenderer.EVENT_KEY);
if (eventName == VertexEvent.EVENT_KEY) {
if (ve.eventType == VertexEvent.DRAGGING_STARTED) {
if (!sd.vertices.contains(ve.v)) { //start if the vertex is not selected
// VertexDragData vdrag = blackboard.get(VertexDragData.name);
v1 = ve.v;
startPainting();
exitedFromV1 = false;
// if (!selMethods.getSelectedVertices().contains(v1)) {
// //the vertex doesn't selected
// } else
// v1 = null;
}
}
if (ve.eventType == VertexEvent.DROPPED) {
if (v1 != null) {
Vertex v2 = ve.v;
if (v2 != null && isDrag) //!it was released on empty space
if (!v1.equals(v2) || exitedFromV1) {
doJob(g, v1, v2);
super.track();
}
// unListenEvent(VertexMouseDraggingData.event);
}
stopPainting();
v1 = null;
}
if (ve.eventType == VertexEvent.DRAGGING) {
lastPos = ve.mousePos;
GPoint absPosOnGraph = GraphUtils.createGraphPoint(g, x1, y1);
absPosOnGraph.add(lastPos);
if (g.getVerticesCount() < 300) {
Pair<Vertex, Double> p = GraphControl.mindistv(g, absPosOnGraph);
if (p.first != null)
curVertexUnderMouse = GraphControl.isPointOnVertex(g, p.first, absPosOnGraph) ? p.first : null;
}
if (!(gv instanceof AcceleratedRenderer))
gv.repaint();
isDrag = true;
isClick = false;
if (v1 != null) {
if (curVertexUnderMouse == null)
exitedFromV1 = true;
}
}
if (ve.eventType == VertexEvent.RELEASED) { //mouse released on a blank area of graph
v1 = null;
stopPainting();
}
} else if (eventName == GraphEvent.EVENT_KEY) {
// if (ge.eventType == GraphEvent.) {
// stopPainting();
// }
}
}
protected void stopPainting() {
gv.removePaintHandler(this);
// g.view.repaint();
}
protected void startPainting() {
GPoint location = v1.getLocation();
Point viewPoint = GraphUtils.createViewPoint(g, location);
cx = v1.getCenter().x / 2;
x1 = viewPoint.x;
cy = v1.getCenter().y / 2;
y1 = viewPoint.y;
// listen4Event(VertexMouseDraggingData.event);
gv.addPostPaintHandler(this);
}
public static Edge doJob(GraphModel g, Vertex v1, Vertex v2) {
Edge e = new Edge(v1, v2);
g.insertEdge(e);
return e;
}
protected int x1;
protected int y1;
protected int cx;
protected int cy;
protected Vertex curVertexUnderMouse = null;
/**
* paints incomplete edges for the user while he/she is adding the edge. (A preview)
*/
public void paint(Graphics g, Object component, Boolean drawExtras) {
if (!drawExtras)
return;
Graphics2D gg = (Graphics2D) g;
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Stroke stroke = gg.getStroke();
gg.setStroke(GStroke.dashed.stroke);
if (lastPos != null) {
Point viewPoint = GraphUtils.createViewPoint(this.g, lastPos);
gg.setColor(Color.DARK_GRAY);
if (curVertexUnderMouse == null)
gg.drawLine(x1, y1, x1 + viewPoint.x, y1 + viewPoint.y);
else if (v1.equals(curVertexUnderMouse) && exitedFromV1) {
Edge e = new Edge(v1, v1);
double zf = this.g.getZoomFactor();
// gg.setStroke(GStroke.strong.stroke);
gg.drawOval(
((int) (zf * (e.getLoopCenter().x - e.getLoopWidth()/2))),
((int) (zf * (e.getLoopCenter().y - e.getLoopWidth()/2))),
((int) (zf * (e.getLoopWidth()))),
((int) (zf * (e.getLoopWidth()))));
}
else {
gg.setStroke(GStroke.strong.stroke);
GPoint loc = curVertexUnderMouse.getLocation();
viewPoint = GraphUtils.createViewPoint(this.g, loc);
gg.drawLine(x1, y1, viewPoint.x, viewPoint.y);
}
}
gg.setStroke(stroke);
}
}