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    
005    package graphlab.plugins.main.select;
006    
007    import graphlab.graph.graph.EdgeModel;
008    import graphlab.graph.graph.GraphModel;
009    import graphlab.graph.graph.VertexModel;
010    import graphlab.plugins.commonplugin.undo.Undoable;
011    import graphlab.plugins.commonplugin.undo.UndoableActionOccuredData;
012    import graphlab.plugins.main.GraphData;
013    import graphlab.plugins.main.extension.GraphActionExtension;
014    
015    import java.util.HashMap;
016    import java.util.HashSet;
017    import java.util.Vector;
018    
019    /**
020     * @author Azin Azadi
021     */
022    public class MakeSelectionComplementGraph implements GraphActionExtension, Undoable {
023        public String getName() {
024            return "Complement Selection";
025        }
026    
027        public String getDescription() {
028            return "Make the selected subgraph complement";
029        }
030    
031        public void action(GraphData gd) {
032            if (gd.select.isSelectionEmpty())
033                return;
034            HashSet<VertexModel> V = gd.select.getSelectedVertices();
035            //add undo data
036            UndoableActionOccuredData uaod = new UndoableActionOccuredData(this);
037            fillUndoEdges(uaod.properties, gd, "old edges");
038    
039            GraphModel G = gd.getGraph();
040            doEdgeOperation(G, V);
041    
042            fillUndoEdges(uaod.properties, gd, "new edges");
043            gd.core.addUndoData(uaod);
044        }
045    
046        protected void doEdgeOperation(GraphModel g, HashSet<VertexModel> v) {
047            boolean directed = g.isDirected();
048    
049            for (VertexModel v1 : v) {
050                for (VertexModel v2 : v) {
051                    if (!directed)
052                        if (v1.getId() < v2.getId())
053                            continue;
054                    if (g.isEdge(v1, v2)) {
055                        g.removeAllEdges(v1, v2);
056                    } else {
057                        g.insertEdge(new EdgeModel(v1, v2));
058                    }
059                }
060            }
061        }
062    
063        //--------------------- U N D O
064        public void undo(UndoableActionOccuredData uaod) {
065            doUndoremove(uaod.properties, "new edges");
066            doUndoadd(uaod.properties, "old edges");
067        }
068    
069        public void redo(UndoableActionOccuredData uaod) {
070            doUndoremove(uaod.properties, "old edges");
071            doUndoadd(uaod.properties, "new edges");
072        }
073    
074        public static Vector<EdgeModel> fillUndoEdges(HashMap<String, Object> properties, GraphData gd, String lbl) {
075            Vector<EdgeModel> edges = new Vector<EdgeModel>();
076            HashSet<VertexModel> V = gd.select.getSelectedVertices();
077            GraphModel g = gd.getGraph();
078            for (VertexModel v : V) {
079                for (VertexModel vv : V) {
080                    edges.add(g.getEdge(v, vv));
081                }
082            }
083            properties.put("graph", gd.getGraph());
084            properties.put(lbl, edges);
085            return edges;
086        }
087    
088        public static void doUndoadd(HashMap<String, Object> uaod, String lbl) {
089            Vector<EdgeModel> edges = (Vector<EdgeModel>) uaod.get(lbl);
090            GraphModel g = (GraphModel) uaod.get("graph");
091            g.insertEdges(edges);
092        }
093    
094        public static void doUndoremove(HashMap<String, Object> uaod, String lbl) {
095            Vector<EdgeModel> edges = (Vector<EdgeModel>) uaod.get(lbl);
096            GraphModel g = (GraphModel) uaod.get("graph");
097            for (EdgeModel e : edges)
098                g.removeEdge(e);
099        }
100    }