Java tutorial
/** * Copyright 2009 Jens Dietrich Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ package nz.ac.massey.cs.gql4jung.browser; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.GraphicsConfiguration; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.HeadlessException; import java.awt.Insets; import java.awt.Paint; import java.awt.Stroke; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.swing.*; import javax.swing.filechooser.FileFilter; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableModel; import org.apache.commons.collections15.Transformer; import org.apache.commons.lang.time.DurationFormatUtils; import nz.ac.massey.cs.gql4jung.Edge; import nz.ac.massey.cs.gql4jung.GQL; import nz.ac.massey.cs.gql4jung.Motif; import nz.ac.massey.cs.gql4jung.MotifInstance; import nz.ac.massey.cs.gql4jung.Path; import nz.ac.massey.cs.gql4jung.Vertex; import nz.ac.massey.cs.gql4jung.io.GraphMLReader; import nz.ac.massey.cs.gql4jung.io.QueryResultsExporter2CSV; import nz.ac.massey.cs.gql4jung.jmpl.GQLImpl; import nz.ac.massey.cs.gql4jung.util.QueryResults; import nz.ac.massey.cs.gql4jung.util.QueryResults.Cursor; import nz.ac.massey.cs.gql4jung.xml.XMLMotifReader; import edu.uci.ics.jung.algorithms.layout.FRLayout; import edu.uci.ics.jung.algorithms.layout.Layout; import edu.uci.ics.jung.graph.DirectedGraph; import edu.uci.ics.jung.graph.DirectedSparseGraph; import edu.uci.ics.jung.visualization.RenderContext; import edu.uci.ics.jung.visualization.VisualizationViewer; import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; /** * Stand alone user interface to run queries and visualise results. * The graph visualisation is based on JUNG. * @author Jens Dietrich */ public class ResultBrowser extends JFrame { // model private DirectedGraph<Vertex, Edge> data = null; private Motif query = null; private QueryResults results = new QueryResults(); private GQL engine = new GQLImpl(); private Thread queryThread = null; private long computationStarted = -1; // parts private JToolBar toolbar; private JLabel cursorField = null; private JLabel dataField = null; private JLabel queryField = null; private JLabel timeField = null; private JProgressBar statusField = null; private JPanel mainPanel = null; private JPopupMenu popup; private MouseAdapter popupListener; private JTable table = null; private JTabbedPane tabbedPane = null; private JPanel graphPane = null; private JMenuBar menuBar = null; // actions private AbstractAction actExit; private AbstractAction actLoadData; private AbstractAction actLoadQuery; private AbstractAction actRunQuery; private AbstractAction actCancelQuery; private AbstractAction actNextMinorInstance; private AbstractAction actPreviousMinorInstance; private AbstractAction actNextMajorInstance; private AbstractAction actPreviousMajorInstance; private AbstractAction actExport2CSV; private List<AbstractAction> actLoadBuiltInQueries = new ArrayList<AbstractAction>(); private enum Status { waiting, computing, finished, cancelled } private Status status = Status.waiting; public static void main(String[] args) { ResultBrowser browser = new ResultBrowser(); browser.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); browser.setLocation(100, 100); browser.setSize(800, 500); browser.setVisible(true); } public ResultBrowser() throws HeadlessException { super(); init(); } public ResultBrowser(GraphicsConfiguration gc) { super(gc); init(); } public ResultBrowser(String title, GraphicsConfiguration gc) { super(title, gc); init(); } public ResultBrowser(String title) throws HeadlessException { super(title); init(); } private void init() { this.setTitle("Architectural smells explorer"); mainPanel = new JPanel(new BorderLayout(5, 5)); this.tabbedPane = new JTabbedPane(); mainPanel.add(tabbedPane, BorderLayout.CENTER); // panel for graph graphPane = new JPanel(new GridLayout(1, 1)); this.tabbedPane.add("result as graph", graphPane); // panel for table this.table = new JTable(); JScrollPane sTable = new JScrollPane(table); addBorder(sTable); this.tabbedPane.add("result as table", sTable); this.setContentPane(mainPanel); // start listening to events QueryResults.QueryResultListener listener = new QueryResults.QueryResultListener() { @Override public void resultsChanged(QueryResults source) { if (results.getCursor().major == -1 && results.hasResults()) { actNextMajorInstance(); } updateStatus(); updateComputationTime(); } @Override public void progressMade(int progress, int total) { statusField.setMaximum(total); statusField.setValue(progress); updateComputationTime(); } }; this.results.addListener(listener); // graph initActions(); initPopupMenu(); initToolbar(); initMenubar(); initStatusBar(); // load sample data // TODO remove this.loadData(new File("exampledata/ant.jar.graphml")); this.loadQuery(new File("queries/awd.xml")); updateActions(); updateStatus(); } private void initMenubar() { menuBar = new JMenuBar(); this.setJMenuBar(menuBar); JMenu menu = new JMenu("File"); menu.setMnemonic(KeyEvent.VK_F); menu.add(actLoadData); menu.add(actLoadQuery); if (this.actLoadBuiltInQueries.size() > 0) { JMenu menu2 = new JMenu("Built-in queries"); for (Action act : actLoadBuiltInQueries) { menu2.add(act); } menu.add(menu2); } menu.addSeparator(); menu.add(actExport2CSV); menu.addSeparator(); menu.add(actExit); menuBar.add(menu); menu = new JMenu("Query"); menu.setMnemonic(KeyEvent.VK_Q); menu.add(actRunQuery); menu.add(actCancelQuery); menuBar.add(menu); menu = new JMenu("Explore"); menu.setMnemonic(KeyEvent.VK_X); menu.add(actPreviousMajorInstance); menu.add(actNextMajorInstance); menu.addSeparator(); menu.add(actPreviousMinorInstance); menu.add(actNextMinorInstance); menuBar.add(menu); } private void initStatusBar() { this.cursorField = new JLabel(); this.queryField = new JLabel(); this.dataField = new JLabel(); this.statusField = new JProgressBar(); statusField.setStringPainted(true); statusField.setBorderPainted(true); this.timeField = new JLabel(); Font font = new Font("monospaced", Font.PLAIN, this.cursorField.getFont().getSize()); this.cursorField.setFont(font); this.dataField.setFont(font); this.queryField.setFont(font); this.timeField.setFont(font); this.statusField.setFont(font); JPanel statusBar = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); int cols = 6; c.insets = new Insets(0, 3, 0, 3); c.gridx = 0; c.gridy = 0; c.fill = c.NONE; c.weightx = 0; c.anchor = c.EAST; c.gridwidth = 1; statusBar.add(new JLabel("data:", JLabel.RIGHT), c); c.gridx = 1; c.fill = c.HORIZONTAL; c.weightx = 1; c.anchor = c.WEST; c.gridwidth = cols - 1; statusBar.add(dataField, c); c.gridx = 0; c.gridy = 1; c.fill = c.NONE; c.weightx = 0; c.anchor = c.EAST; c.gridwidth = 1; statusBar.add(new JLabel("query:", JLabel.RIGHT), c); c.gridx = 1; c.fill = c.HORIZONTAL; c.weightx = 1; c.anchor = c.WEST; c.gridwidth = cols - 1; statusBar.add(queryField, c); c.gridx = 0; c.gridy = 2; c.fill = c.NONE; c.weightx = 0; c.anchor = c.EAST; c.gridwidth = 1; statusBar.add(new JLabel("status:", JLabel.RIGHT), c); c.gridx = 1; c.fill = c.HORIZONTAL; c.weightx = 1; c.anchor = c.WEST; statusBar.add(statusField, c); c.gridx = 2; c.gridy = 2; c.fill = c.NONE; c.weightx = 0; c.anchor = c.EAST; c.gridwidth = 1; statusBar.add(new JLabel("cursor:", JLabel.RIGHT), c); c.gridx = 3; c.fill = c.HORIZONTAL; c.weightx = 1; c.anchor = c.WEST; statusBar.add(cursorField, c); c.gridx = 4; c.gridy = 2; c.fill = c.NONE; c.weightx = 0; c.anchor = c.EAST; c.gridwidth = 1; statusBar.add(new JLabel("computation time:", JLabel.RIGHT), c); c.gridx = 5; c.fill = c.HORIZONTAL; c.weightx = 1; c.anchor = c.WEST; statusBar.add(timeField, c); mainPanel.add(statusBar, BorderLayout.SOUTH); statusBar.setBorder(BorderFactory.createEtchedBorder()); } private void initActions() { actExit = new AbstractAction("exit") { @Override public void actionPerformed(ActionEvent e) { dispose(); } }; actLoadData = new AbstractAction("load data", getIcon("Open16.gif")) { @Override public void actionPerformed(ActionEvent e) { actLoadData(); } }; actLoadData.putValue(Action.SHORT_DESCRIPTION, "load a program dependency graph from a graphml file"); actLoadQuery = new AbstractAction("load query", getIcon("Import16.gif")) { @Override public void actionPerformed(ActionEvent e) { actLoadQuery(); } }; actLoadQuery.putValue(Action.SHORT_DESCRIPTION, "load a query from a xml file"); actRunQuery = new AbstractAction("run query", getIcon("Play16.gif")) { @Override public void actionPerformed(ActionEvent e) { actRunQuery(); } }; actRunQuery.putValue(Action.SHORT_DESCRIPTION, "execute the query"); actCancelQuery = new AbstractAction("cancel", getIcon("Stop16.gif")) { @Override public void actionPerformed(ActionEvent e) { actCancelQuery(); } }; actCancelQuery.putValue(Action.SHORT_DESCRIPTION, "cancel the currently running query"); actExport2CSV = new AbstractAction("export to csv", getIcon("Export16.gif")) { @Override public void actionPerformed(ActionEvent e) { actExport2CSV(); } }; actExport2CSV.putValue(Action.SHORT_DESCRIPTION, "export the query results to a CSV (spreadsheet) file"); actPreviousMinorInstance = new AbstractAction("previous minor instance", getIcon("PreviousMinor16.gif")) { @Override public void actionPerformed(ActionEvent e) { actPreviousMinorInstance(); } }; actPreviousMinorInstance.putValue(Action.SHORT_DESCRIPTION, "show the previous variant of the selected instance"); actNextMinorInstance = new AbstractAction("next minor instance", getIcon("NextMinor16.gif")) { @Override public void actionPerformed(ActionEvent e) { actNextMinorInstance(); } }; actNextMinorInstance.putValue(Action.SHORT_DESCRIPTION, "show the next variant of the selected instance"); actPreviousMajorInstance = new AbstractAction("previous major instance", getIcon("PreviousMajor16.gif")) { @Override public void actionPerformed(ActionEvent e) { actPreviousMajorInstance(); } }; actPreviousMajorInstance.putValue(Action.SHORT_DESCRIPTION, "show the previous instance"); actNextMajorInstance = new AbstractAction("next major instance", getIcon("NextMajor16.gif")) { @Override public void actionPerformed(ActionEvent e) { actNextMajorInstance(); } }; actNextMajorInstance.putValue(Action.SHORT_DESCRIPTION, "show the next instance"); initBuiltInQueries(); } private void initBuiltInQueries() { initBuildInQuery("missing decoupling by abstraction", "queries/awd.xml"); initBuildInQuery("circular dependencies between packages", "queries/cd.xml"); initBuildInQuery("db 2 ui layer dependencies", "queries/db2ui.xml"); initBuildInQuery("multiple dependency clusters in same package", "queries/cns.xml"); } private void initBuildInQuery(String name, final String file) { final File f = new File(file); if (f.exists()) { AbstractAction act = new AbstractAction(name) { @Override public void actionPerformed(ActionEvent e) { loadQuery(f); } }; this.actLoadBuiltInQueries.add(act); log("added action to load query from file " + f); } else { log("cannot add action to load query from file " + f); } } private void initToolbar() { toolbar = new JToolBar(); toolbar.setFloatable(false); mainPanel.add(toolbar, BorderLayout.NORTH); toolbar.add(actLoadData); toolbar.add(actLoadQuery); toolbar.addSeparator(); toolbar.add(actRunQuery); toolbar.add(actCancelQuery); toolbar.addSeparator(); toolbar.add(actPreviousMajorInstance); toolbar.add(actNextMajorInstance); toolbar.addSeparator(); toolbar.add(actPreviousMinorInstance); toolbar.add(actNextMinorInstance); toolbar.addSeparator(); toolbar.add(actExport2CSV); } private void initPopupMenu() { popup = new JPopupMenu(); popup.add(this.actRunQuery); popup.add(this.actCancelQuery); popup.addSeparator(); popup.add(this.actLoadData); popup.add(this.actLoadQuery); popup.addSeparator(); popup.add(this.actNextMajorInstance); popup.add(this.actPreviousMajorInstance); popup.addSeparator(); popup.add(this.actNextMinorInstance); popup.add(this.actPreviousMinorInstance); popupListener = new MouseAdapter() { public void mousePressed(MouseEvent e) { showPopup(e); } public void mouseReleased(MouseEvent e) { showPopup(e); } private void showPopup(MouseEvent e) { if (e.isPopupTrigger()) { popup.show(e.getComponent(), e.getX(), e.getY()); } } }; this.mainPanel.addMouseListener(popupListener); } private Icon getIcon(String string) { return new ImageIcon("icons/" + string); } private void actCancelQuery() { this.engine.cancel(); this.queryThread = null; this.status = Status.cancelled; updateActions(); updateStatus(); this.computationStarted = -1; log("query cancelled"); } private void actPreviousMajorInstance() { Cursor cursor = this.results.previousMajorInstance(); this.selectAndDisplay(cursor); } private void actNextMajorInstance() { Cursor cursor = this.results.nextMajorInstance(); this.selectAndDisplay(cursor); } private void actPreviousMinorInstance() { Cursor cursor = this.results.previousMinorInstance(); this.selectAndDisplay(cursor); } private void actNextMinorInstance() { Cursor cursor = this.results.nextMinorInstance(); this.selectAndDisplay(cursor); } private void actExport2CSV() { JFileChooser fc = new JFileChooser(); int returnVal = fc.showOpenDialog(this); FileFilter filter = new FileFilter() { @Override public boolean accept(File f) { return f.getAbsolutePath().endsWith(".csv"); } @Override public String getDescription() { return "csv files"; } }; fc.setFileFilter(filter); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); QueryResultsExporter2CSV exporter = new QueryResultsExporter2CSV(); try { exporter.export(this.results, file); log("results exported to " + file.getAbsolutePath()); JOptionPane.showMessageDialog(this, "Results have been exported to\n" + file.getAbsolutePath()); } catch (IOException x) { this.handleException("Error exporting file", x); } } } private void selectAndDisplay(Cursor cursor) { this.updateActions(); this.updateStatus(); MotifInstance instance = results.getInstance(cursor); this.display(instance); } private void actRunQuery() { this.results.reset(); Runnable runnable = new Runnable() { @Override public void run() { computationStarted = System.currentTimeMillis(); engine.reset(); results.reset(); display(null); engine.query(data, query, results); queryThread = null; status = Status.finished; updateComputationTime(); updateStatus(); } }; this.queryThread = new Thread(runnable); this.status = Status.computing; updateStatus(); this.queryThread.start(); updateActions(); } private void actLoadQuery() { JFileChooser fc = new JFileChooser(); fc.setCurrentDirectory(new File(".")); fc.setDialogTitle("Load query"); int returnVal = fc.showOpenDialog(this); FileFilter filter = new FileFilter() { @Override public boolean accept(File f) { return f.getAbsolutePath().endsWith(".xml"); } @Override public String getDescription() { return "xml"; } }; fc.setFileFilter(filter); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); loadQuery(file); } updateActions(); updateStatus(); } private void log(String string) { System.out.println(string); } private void actLoadData() { JFileChooser fc = new JFileChooser(); fc.setCurrentDirectory(new File(".")); fc.setDialogTitle("Load graph"); int returnVal = fc.showOpenDialog(this); FileFilter filter = new FileFilter() { @Override public boolean accept(File f) { return f.getAbsolutePath().endsWith(".graphml"); } @Override public String getDescription() { return "graphml files"; } }; fc.setFileFilter(filter); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); loadData(file); } updateActions(); updateStatus(); } private void loadQuery(File file) { try { InputStream in = new FileInputStream(file); Motif motif = new XMLMotifReader().read(in); this.query = motif; this.computationStarted = -1; this.status = Status.waiting; this.queryField.setText(file.getAbsolutePath()); in.close(); log("Motif imported from " + file.getAbsolutePath()); } catch (Exception x) { handleException("Error loading query", x); } } private void loadData(File file) { try { Reader reader = new FileReader(file); GraphMLReader input = new GraphMLReader(reader); DirectedGraph<Vertex, Edge> g = input.readGraph(); reader.close(); this.data = g; this.status = Status.waiting; this.dataField.setText(file.getAbsolutePath()); log("Data imported from " + file.getAbsolutePath()); this.computationStarted = -1; } catch (Exception x) { handleException("Eddor loading data file", x); } } private void handleException(String string, Exception x) { System.err.println(string); x.printStackTrace(); } private void nyi() { JOptionPane.showMessageDialog(this, "this function is not yet implemented"); } private void updateActions() { boolean queryIsRunning = this.queryThread != null; this.actCancelQuery.setEnabled(queryIsRunning); this.actRunQuery.setEnabled(!queryIsRunning); this.actExport2CSV.setEnabled(!queryIsRunning && results.hasResults()); this.actNextMajorInstance.setEnabled(this.results.hasNextMajorInstance()); this.actNextMinorInstance.setEnabled(this.results.hasNextMinorInstance()); this.actPreviousMajorInstance.setEnabled(this.results.hasPreviousMajorInstance()); this.actPreviousMinorInstance.setEnabled(this.results.hasPreviousMinorInstance()); } private void updateComputationTime() { if (this.computationStarted == -1) { this.timeField.setText(""); } else { String dur = DurationFormatUtils.formatDuration(System.currentTimeMillis() - this.computationStarted, "H:m:s.S", true); this.timeField.setText(dur); } } private void updateStatus() { // log("update UI"); Cursor cursor = results.getCursor(); int majI = cursor.major + 1; int maxMajI = results.getNumberOfGroups(); StringBuffer b = new StringBuffer(); if (maxMajI > 0) { b.append("instance ").append(majI).append('/').append(maxMajI); if (majI > 0) { int minI = cursor.minor + 1; int maxMinI = results.getNumberOfInstances(majI - 1); b.append(", ").append("variant ").append(minI).append('/').append(maxMinI); } b.append(' '); } cursorField.setText(b.toString()); statusField.setString(this.status.toString()); if (this.status != Status.computing) statusField.setValue(0); //statusField.setIndeterminate(this.status==Status.computing); updateActions(); }; private void display(final MotifInstance instance) { /* Runnable runner = new Runnable() { public void run() { displayTable(instance); displayGraph(instance); } }; new Thread(runner).start();*/ if (this.tabbedPane.getSelectedIndex() == 0) { displayGraph(instance); displayTable(instance); } else { displayTable(instance); displayGraph(instance); } } private void displayTable(final MotifInstance instance) { final List<String> roles = (instance == null) ? new ArrayList<String>() : instance.getMotif().getRoles(); TableModel model = new AbstractTableModel() { public String getColumnName(int col) { switch (col) { case 0: return "role"; case 1: return "name"; case 2: return "namespace"; case 3: return "container"; case 4: return "is abstract"; case 5: return "type"; case 6: return "cluster"; default: return null; } } public int getRowCount() { return roles.size(); } public int getColumnCount() { return 7; } public Object getValueAt(int row, int col) { String role = roles.get(row); if (instance == null) return ""; Vertex v = instance.getVertex(role); Object cluster = "TODO"; if (cluster == null) cluster = "n/a"; switch (col) { case 0: return role; case 1: return v.getName(); case 2: return v.getNamespace(); case 3: return v.getContainer(); case 4: return v.isAbstract(); case 5: return v.getType(); case 6: return v.getCluster(); default: return null; } } public boolean isCellEditable(int row, int col) { return false; } public void setValueAt(Object value, int row, int col) { // nothing to do - table is read only } }; this.table.setModel(model); } private void displayGraph(final MotifInstance instance) { DirectedGraph<Vertex, Edge> g = instance == null ? new DirectedSparseGraph<Vertex, Edge>() : this.asGraph(instance); //SimpleGraphView sgv = new SimpleGraphView(); //We create our graph in here // The Layout<V, E> is parameterized by the vertex and edge types Layout<Vertex, Edge> layout = new FRLayout<Vertex, Edge>(g); layout.setSize(graphPane.getSize()); VisualizationViewer<Vertex, Edge> vv = new VisualizationViewer<Vertex, Edge>(layout); configureRenderer(vv.getRenderContext(), instance); vv.setPreferredSize(graphPane.getSize()); //Sets the viewing area size graphPane.removeAll(); graphPane.add(vv); graphPane.revalidate(); //vv.addMouseListener(popupListener); // Create a graph mouse and add it to the visualization component DefaultModalGraphMouse gm = new DefaultModalGraphMouse(); gm.setMode(edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode.PICKING); vv.setGraphMouse(gm); } private void configureRenderer(RenderContext context, final MotifInstance instance) { final Map<Vertex, String> revMap = new HashMap<Vertex, String>(); if (instance != null) { for (String role : instance.getMotif().getRoles()) { revMap.put(instance.getVertex(role), role); } } context.setVertexLabelTransformer(new Transformer<Vertex, String>() { @Override public String transform(Vertex v) { String role = revMap.get(v); StringBuffer b = new StringBuffer().append("<html>"); if (role != null) { b.append("<<").append(role == null ? "?" : role).append(">>").append("<br/>"); } b.append(v.getNamespace()).append('.').append(v.getName()).append("</html>"); return b.toString(); } }); context.setEdgeLabelTransformer(new Transformer<Edge, String>() { @Override public String transform(Edge e) { return "<<" + e.getType() + ">>"; } }); context.setVertexFillPaintTransformer(new Transformer<Vertex, Paint>() { @Override public Paint transform(Vertex v) { String t = v.getType(); if ("class".equals(t) && !v.isAbstract()) return Color.GREEN; else if ("class".equals(t) && v.isAbstract()) return Color.BLUE; else if ("interface".equals(t)) return new Color(255, 0, 255); // purble else return Color.WHITE; } }); final Stroke strokeUses = new BasicStroke(1); final Stroke strokeInherits = new BasicStroke(2); context.setEdgeStrokeTransformer(new Transformer<Edge, Stroke>() { public Stroke transform(Edge e) { if ("uses".equals(e.getType())) return strokeUses; else return strokeInherits; } }); context.setVertexIconTransformer(new Transformer<Vertex, Icon>() { @Override public Icon transform(Vertex v) { boolean hasRole = revMap.containsKey(v); if (v.isAbstract()) { return hasRole ? GraphRenderer.ICON_INTERFACE_C : GraphRenderer.ICON_INTERFACE_BW; } else { return hasRole ? GraphRenderer.ICON_CLASS_C : GraphRenderer.ICON_CLASS_BW; } } }); context.setVertexFontTransformer(new Transformer<Vertex, Font>() { @Override public Font transform(Vertex v) { boolean hasRole = revMap.containsKey(v); return hasRole ? GraphRenderer.CORE : GraphRenderer.NON_CORE; } }); context.setEdgeFontTransformer(new Transformer<Edge, Font>() { @Override public Font transform(Edge e) { return GraphRenderer.CORE; } }); } private DirectedGraph asGraph(MotifInstance instance) { DirectedGraph<Vertex, Edge> g = new DirectedSparseGraph<Vertex, Edge>(); Motif motif = instance.getMotif(); // vertices Set<Vertex> vertices = new HashSet<Vertex>(); for (String role : motif.getRoles()) { Vertex v = instance.getVertex(role); if (v == null) { g.addVertex(v); vertices.add(v); } } ; // edges for (String role : motif.getPathRoles()) { Path p = instance.getPath(role); if (p != null) { for (Edge e : p.getEdges()) { Vertex v1 = e.getStart(); Vertex v2 = e.getEnd(); if (!vertices.contains(v1)) vertices.add(v1); if (!vertices.contains(v2)) vertices.add(v2); g.addEdge(e, v1, v2); } } } return g; } @Override public void dispose() { try { this.actCancelQuery(); } catch (Exception x) { } super.dispose(); } private void addBorder(JComponent c) { c.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); } }