001    // GraphLab Project: http://graphlab.sharif.edu
002    // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
003    // Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
004    package graphlab.plugins.main.core.actions.edge;
005    
006    import graphlab.graph.GraphUtils;
007    import graphlab.graph.atributeset.GraphAttrSet;
008    import graphlab.graph.event.GraphEvent;
009    import graphlab.graph.event.VertexEvent;
010    import graphlab.graph.graph.*;
011    import graphlab.graph.old.AcceleratedRenderer;
012    import graphlab.graph.old.GStroke;
013    import graphlab.library.util.Pair;
014    import graphlab.platform.core.AbstractAction;
015    import graphlab.platform.core.BlackBoard;
016    import graphlab.plugins.commonplugin.undo.Undoable;
017    import graphlab.plugins.commonplugin.undo.UndoableActionOccuredData;
018    import graphlab.plugins.main.select.Select;
019    import graphlab.plugins.main.select.SelectPluginMethods;
020    
021    import java.awt.*;
022    import java.awt.event.MouseEvent;
023    
024    /**
025     * @author azin azadi
026     */
027    
028    public class AddEdge extends AbstractAction implements PaintHandler, Undoable {
029        //    private double lasty;
030        //    private double lastx;
031        private GraphPoint lastPos;
032        private SelectPluginMethods selMethods;
033    
034        /**
035         * constructor
036         *
037         * @param bb the blackboard of the action
038         */
039        public AddEdge(BlackBoard bb) {
040            super(bb);
041            selMethods = new SelectPluginMethods(bb);
042            listen4Event(VertexEvent.EVENT_KEY);
043    //        listen4Event(GraphEvent.name);
044    //        listen4Event(VertexDropData.event);
045    //        listen4Event(VertexSelectData.name);
046        }
047    
048        protected VertexModel v1, vc1;
049        protected GraphModel g;
050        protected AbstractGraphRenderer gv;
051        protected boolean isClick = false;
052        protected boolean isDrag = false;
053    
054        public void performAction(String eventName, Object value) {
055    // our old lovely Add Edge
056    //        if (name == VertexSelectData.name) {
057    //            VertexSelectData vsd = blackboard.getLog(VertexSelectData.name).getLast();
058    //            if (!isClick) {
059    //                vc1 = vsd.v;
060    //                v1=vc1;
061    //                startPainting();
062    //            } else {
063    //                Vertex v2=vsd.v;
064    //                Edge e = doJob(v2.g, v2, vc1);
065    //                addUndoData(e);
066    //                stopPainting();
067    //            }
068    //            isClick=true;
069    //            isDrag=false;
070    //        }
071            VertexEvent ve = blackboard.getData(VertexEvent.EVENT_KEY);
072    
073            if ((ve.modifiers & MouseEvent.SHIFT_DOWN_MASK) == MouseEvent.SHIFT_DOWN_MASK)
074                return;
075    
076            SubGraph sd = Select.getSelection(blackboard);
077            g = blackboard.getData(GraphAttrSet.name);
078            gv = blackboard.getData(AbstractGraphRenderer.EVENT_KEY);
079    
080    
081            if (eventName == VertexEvent.EVENT_KEY) {
082                if (ve.eventType == VertexEvent.DRAGGING_STARTED) {
083                    if (!sd.vertices.contains(ve.v)) {   //start if the vertex is not selected
084    //            VertexDragData vdrag = blackboard.get(VertexDragData.name);
085                        v1 = ve.v;
086                        startPainting();
087    //                    if (!selMethods.getSelectedVertices().contains(v1)) {
088    //                        //the vertex doesn't selected
089    //                    } else
090    //                        v1 = null;
091                    }
092                }
093                if (ve.eventType == VertexEvent.DROPPED) {
094                    if (v1 != null) {
095                        VertexModel v2 = ve.v;
096                        if (v2 != null && isDrag)   //!it was released on empty space
097                            if (!v1.equals(v2)) {
098                                EdgeModel e = doJob(g, v1, v2);
099                                addUndoData(e, g);
100                            }
101    //            unListenEvent(VertexMouseDraggingData.event);
102                    }
103                    stopPainting();
104                    v1 = null;
105                }
106    
107                if (ve.eventType == VertexEvent.DRAGGING) {
108                    lastPos = ve.mousePos;
109                    GraphPoint absPosOnGraph = GraphUtils.createGraphPoint(g, x1, y1);
110                    absPosOnGraph.add(lastPos);
111                    if (g.getVerticesCount() < 300) {
112                        Pair<VertexModel, Double> p = GraphControl.mindistv(g, absPosOnGraph);
113                        if (p.first != null)
114                            curVertexUnderMouse = GraphControl.isPointOnVertex(g, p.first, absPosOnGraph) ? p.first : null;
115                    }
116                    if (!(gv instanceof AcceleratedRenderer))
117                        gv.repaint();
118    
119                    isDrag = true;
120                    isClick = false;
121                }
122    
123                if (ve.eventType == VertexEvent.DOUBLECLICKED) {
124                    VertexModel v = ve.v;
125                    if (v != null) {
126                        EdgeModel e = doJob(g, v, v);
127                        addUndoData(e, g);
128                    }
129                }
130                if (ve.eventType == VertexEvent.RELEASED) { //mouse released on a blank area of graph
131                    v1 = null;
132                    stopPainting();
133                }
134            } else if (eventName == GraphEvent.EVENT_KEY) {
135    //                if (ge.eventType == GraphEvent.) {
136    //                    stopPainting();
137    //                }
138            }
139        }
140    
141        protected void stopPainting() {
142            gv.removePaintHandler(this);
143    //        g.view.repaint();
144        }
145    
146        protected void addUndoData(EdgeModel e, GraphModel g) {
147            UndoableActionOccuredData uaod = new UndoableActionOccuredData(this);
148            uaod.properties.put("AddedEdge", e);
149            uaod.properties.put("Graph", g);
150            blackboard.setData(UndoableActionOccuredData.EVENT_KEY, uaod);
151        }
152    
153        protected void startPainting() {
154            GraphPoint location = v1.getLocation();
155            Point viewPoint = GraphUtils.createViewPoint(g, location);
156            cx = v1.getCenter().x / 2;
157            x1 = viewPoint.x;
158            cy = v1.getCenter().y / 2;
159            y1 = viewPoint.y;
160    //        listen4Event(VertexMouseDraggingData.event);
161            gv.addPostPaintHandler(this);
162        }
163    
164        public static EdgeModel doJob(GraphModel g, VertexModel v1, VertexModel v2) {
165            EdgeModel e = new EdgeModel(v1, v2);
166            g.insertEdge(e);
167            return e;
168        }
169    
170        protected int x1;
171        protected int y1;
172        protected int cx;
173        protected int cy;
174    
175        protected VertexModel curVertexUnderMouse = null;
176    
177        public void paint(Graphics g, Object component, Boolean drawExtras) {
178            if (!drawExtras)
179                return;
180            Graphics2D gg = (Graphics2D) g;
181            gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
182            Stroke stroke = gg.getStroke();
183            gg.setStroke(GStroke.dashed.stroke);
184            if (lastPos != null) {
185                Point viewPoint = GraphUtils.createViewPoint(this.g, lastPos);
186                gg.setColor(Color.DARK_GRAY);
187                if (curVertexUnderMouse == null)
188                    gg.drawLine(x1, y1, x1 + viewPoint.x, y1 + viewPoint.y);
189                else {
190                    gg.setStroke(GStroke.strong.stroke);
191                    GraphPoint loc = curVertexUnderMouse.getLocation();
192                    viewPoint = GraphUtils.createViewPoint(this.g, loc);
193                    gg.drawLine(x1, y1, viewPoint.x, viewPoint.y);
194                }
195            }
196    //            }
197            gg.setStroke(stroke);
198        }
199    
200        public void undo(UndoableActionOccuredData uaod) {
201            EdgeModel e = (EdgeModel) uaod.properties.get("AddedEdge");
202            GraphModel g = (GraphModel) uaod.properties.get("Graph");
203            g.removeEdge(e);
204    
205        }
206    
207        public void redo(UndoableActionOccuredData uaod) {
208            EdgeModel e = (EdgeModel) uaod.properties.get("AddedEdge");
209            GraphModel g = (GraphModel) uaod.properties.get("Graph");
210            g.insertEdge(e);
211        }
212    }