001 /* 002 * Copyright (C) 2008-2010 by Holger Arndt 003 * 004 * This file is part of the Universal Java Matrix Package (UJMP). 005 * See the NOTICE file distributed with this work for additional 006 * information regarding copyright ownership and licensing. 007 * 008 * UJMP is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation; either version 2 011 * of the License, or (at your option) any later version. 012 * 013 * UJMP is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public 019 * License along with UJMP; if not, write to the 020 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 021 * Boston, MA 02110-1301 USA 022 */ 023 024 package org.ujmp.jung; 025 026 import java.awt.Color; 027 import java.awt.Dimension; 028 import java.awt.Font; 029 import java.awt.FontMetrics; 030 import java.awt.Graphics; 031 import java.awt.Graphics2D; 032 import java.awt.event.ComponentEvent; 033 import java.awt.event.ComponentListener; 034 import java.awt.event.MouseEvent; 035 import java.awt.event.MouseListener; 036 import java.awt.image.BufferedImage; 037 import java.io.File; 038 import java.util.logging.Logger; 039 040 import javax.swing.JPopupMenu; 041 042 import org.ujmp.gui.interfaces.CanBeRepainted; 043 import org.ujmp.gui.interfaces.CanRenderGraph; 044 import org.ujmp.gui.io.ExportJPEG; 045 import org.ujmp.gui.io.ExportPDF; 046 import org.ujmp.gui.io.ExportPNG; 047 import org.ujmp.gui.util.GraphicsExecutor; 048 049 import edu.uci.ics.jung.exceptions.FatalException; 050 import edu.uci.ics.jung.graph.ArchetypeEdge; 051 import edu.uci.ics.jung.graph.ArchetypeVertex; 052 import edu.uci.ics.jung.graph.Graph; 053 import edu.uci.ics.jung.graph.decorators.EdgeShape; 054 import edu.uci.ics.jung.graph.decorators.EdgeStringer; 055 import edu.uci.ics.jung.graph.decorators.VertexStringer; 056 import edu.uci.ics.jung.graph.event.GraphEvent; 057 import edu.uci.ics.jung.graph.event.GraphEventListener; 058 import edu.uci.ics.jung.graph.event.GraphEventType; 059 import edu.uci.ics.jung.graph.impl.DirectedSparseGraph; 060 import edu.uci.ics.jung.visualization.DefaultVisualizationModel; 061 import edu.uci.ics.jung.visualization.FRLayout; 062 import edu.uci.ics.jung.visualization.ISOMLayout; 063 import edu.uci.ics.jung.visualization.Layout; 064 import edu.uci.ics.jung.visualization.LayoutMutable; 065 import edu.uci.ics.jung.visualization.PluggableRenderer; 066 import edu.uci.ics.jung.visualization.SpringLayout; 067 import edu.uci.ics.jung.visualization.VisualizationViewer; 068 import edu.uci.ics.jung.visualization.contrib.CircleLayout; 069 import edu.uci.ics.jung.visualization.contrib.KKLayout; 070 import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; 071 import edu.uci.ics.jung.visualization.control.ModalGraphMouse; 072 073 public abstract class JungGraphPanel extends VisualizationViewer implements MouseListener, ComponentListener, 074 GraphEventListener, CanBeRepainted, CanRenderGraph { 075 private static final long serialVersionUID = 5056858150031378990L; 076 077 protected static final Logger logger = Logger.getLogger(JungGraphPanel.class.getName()); 078 079 public static enum GraphLayout { 080 FRLayout, KKLayout, ISOMLayout, SpringLayout, CircleLayout 081 }; 082 083 public static enum Data { 084 JDMPObject, Object, Label, Column, RowColumn, Value, Inhibitory, Excitatory, Time, Matrix, Type, Reference 085 }; 086 087 protected Graph graph = new DirectedSparseGraph(); 088 089 private boolean showEdges = true; 090 091 private boolean showEdgeLabels = true; 092 093 private boolean showVertexLabels = true; 094 095 private BufferedImage bufferedImage = null; 096 097 public JungGraphPanel() { 098 super(new DefaultVisualizationModel(new FRLayout(new DirectedSparseGraph())), new PluggableRenderer(), 099 new Dimension(800, 600)); 100 101 addComponentListener(this); 102 103 setDoubleBuffered(true); 104 setPreferredSize(new Dimension(800, 600)); 105 106 addMouseListener(this); 107 setPickSupport(new DefaultShapePickSupport()); 108 109 addPostRenderPaintable(new VisualizationViewer.Paintable() { 110 int x; 111 112 int y; 113 114 Font font; 115 116 FontMetrics metrics; 117 118 int swidth; 119 120 int sheight; 121 122 public void paint(Graphics g) { 123 if (true) 124 return; 125 // TODO: make look good 126 Dimension d = getSize(); 127 if (font == null) { 128 font = new Font(g.getFont().getName(), Font.ITALIC, 10); 129 metrics = g.getFontMetrics(font); 130 // swidth = 131 // metrics.stringWidth(GlobalConfiguration.getInstance().getVersionLabel()); 132 sheight = metrics.getMaxAscent() + metrics.getMaxDescent(); 133 x = (d.width - swidth - 10); 134 y = (int) (d.height - sheight * 1.5); 135 } 136 g.setFont(font); 137 Color oldColor = g.getColor(); 138 g.setColor(Color.lightGray); 139 // g.drawString(GlobalConfiguration.getInstance().getVersionLabel(), 140 // x, y); 141 g.setColor(oldColor); 142 } 143 144 public boolean useTransform() { 145 return false; 146 } 147 }); 148 149 ((PluggableRenderer) getRenderer()).setEdgeShapeFunction(new EdgeShape.QuadCurve()); 150 151 ((PluggableRenderer) getRenderer()).setVertexStringer(new VertexStringer() { 152 public String getLabel(ArchetypeVertex v) { 153 if (isShowVertexLabels() && v.getUserDatum(Data.Label) != null) 154 return "" + v.getUserDatum(Data.Label); 155 return null; 156 } 157 }); 158 159 ((PluggableRenderer) getRenderer()).setEdgeStringer(new EdgeStringer() { 160 public String getLabel(ArchetypeEdge e) { 161 if (isShowEdgeLabels() && e.getUserDatum(Data.Label) != null) 162 return "" + e.getUserDatum(Data.Label); 163 return null; 164 } 165 }); 166 167 ModalGraphMouse graphMouse = new DefaultModalGraphMouse(); 168 graphMouse.setMode(ModalGraphMouse.Mode.PICKING); 169 setGraphMouse(graphMouse); 170 171 // this.stop(); 172 173 } 174 175 public void componentHidden(ComponentEvent e) { 176 } 177 178 public void componentMoved(ComponentEvent e) { 179 } 180 181 public void componentResized(ComponentEvent e) { 182 GraphicsExecutor.scheduleUpdate(this); 183 } 184 185 public void componentShown(ComponentEvent e) { 186 GraphicsExecutor.scheduleUpdate(this); 187 } 188 189 public void setGraph(Graph g) { 190 graph.removeListener(this, GraphEventType.ALL_SINGLE_EVENTS); 191 graph = g; 192 graph.addListener(this, GraphEventType.ALL_SINGLE_EVENTS); 193 setModel(new DefaultVisualizationModel(new FRLayout(graph))); 194 GraphicsExecutor.scheduleUpdate(this); 195 } 196 197 // change method to public to allow pdf export 198 199 public void renderGraph(Graphics2D g2d) { 200 super.renderGraph(g2d); 201 } 202 203 public final void repaintUI() { 204 if (getModel().getGraphLayout() instanceof LayoutMutable) { 205 ((LayoutMutable) getModel().getGraphLayout()).update(); 206 } 207 if (!isVisRunnerRunning()) { 208 try { 209 init(); 210 } catch (FatalException e) { 211 System.out.println("Fatal Error in JungGraphPanel"); 212 } 213 } 214 BufferedImage tempBufferedImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); 215 Graphics g = tempBufferedImage.getGraphics(); 216 super.paintComponent(g); 217 g.dispose(); 218 bufferedImage = tempBufferedImage; 219 } 220 221 222 public void paintComponent(Graphics g) { 223 if (ui != null) { 224 Graphics scratchGraphics = (g == null) ? null : g.create(); 225 try { 226 ui.update(scratchGraphics, this); 227 } finally { 228 scratchGraphics.dispose(); 229 } 230 } 231 232 if (bufferedImage != null) { 233 g.drawImage(bufferedImage, 0, 0, getWidth(), getHeight(), null); 234 } else { 235 g.setColor(Color.GRAY); 236 g.drawLine(0, 0, getWidth(), getHeight()); 237 g.drawLine(getWidth(), 0, 0, getHeight()); 238 GraphicsExecutor.scheduleUpdate(this); 239 } 240 } 241 242 public final boolean isShowEdges() { 243 return showEdges; 244 } 245 246 public final void setShowEdges(boolean showEdges) { 247 this.showEdges = showEdges; 248 } 249 250 public final boolean isShowEdgeLabels() { 251 return showEdgeLabels; 252 } 253 254 public final void setShowEdgeLabels(boolean showEdgeLabels) { 255 this.showEdgeLabels = showEdgeLabels; 256 } 257 258 public final boolean isShowVertexLabels() { 259 return showVertexLabels; 260 } 261 262 public final void setShowVertexLabels(boolean showVertexLabels) { 263 this.showVertexLabels = showVertexLabels; 264 } 265 266 public final void exportToPDF(File file) { 267 Color oldbg = getBackground(); 268 setBackground(Color.white); 269 ExportPDF.save(file, this); 270 this.setBackground(oldbg); 271 } 272 273 public final void exportToJPEG(File file) { 274 Color oldbg = this.getBackground(); 275 this.setBackground(Color.white); 276 ExportJPEG.save(file, this, 1600); 277 this.setBackground(oldbg); 278 } 279 280 public final void exportToPNG(File file) { 281 Color oldbg = this.getBackground(); 282 this.setBackground(Color.white); 283 ExportPNG.save(file, this, 1600); 284 this.setBackground(oldbg); 285 } 286 287 public final void mouseClicked(MouseEvent e) { 288 switch (e.getButton()) { 289 case MouseEvent.BUTTON1: 290 break; 291 case MouseEvent.BUTTON2: 292 break; 293 case MouseEvent.BUTTON3: 294 JPopupMenu popup = null; 295 popup = new JungGraphActions(this); 296 popup.show(e.getComponent(), e.getX(), e.getY()); 297 break; 298 } 299 } 300 301 public final void mousePressed(MouseEvent e) { 302 } 303 304 public final void mouseReleased(MouseEvent e) { 305 } 306 307 public final void mouseEntered(MouseEvent e) { 308 } 309 310 public final void mouseExited(MouseEvent e) { 311 } 312 313 public void switchLayout(GraphLayout type) { 314 stop(); 315 316 Layout layout = null; 317 318 switch (type) { 319 case KKLayout: 320 layout = new KKLayout(graph); 321 break; 322 case FRLayout: 323 layout = new FRLayout(graph); 324 break; 325 case ISOMLayout: 326 layout = new ISOMLayout(graph); 327 break; 328 case SpringLayout: 329 layout = new SpringLayout(graph); 330 break; 331 case CircleLayout: 332 layout = new CircleLayout(graph); 333 break; 334 } 335 336 setModel(new DefaultVisualizationModel(layout)); 337 338 restart(); 339 GraphicsExecutor.scheduleUpdate(this); 340 } 341 342 public void edgeAdded(GraphEvent event) { 343 GraphicsExecutor.scheduleUpdate(this); 344 } 345 346 public void edgeRemoved(GraphEvent event) { 347 GraphicsExecutor.scheduleUpdate(this); 348 } 349 350 public void vertexAdded(GraphEvent event) { 351 GraphicsExecutor.scheduleUpdate(this); 352 } 353 354 public void vertexRemoved(GraphEvent event) { 355 GraphicsExecutor.scheduleUpdate(this); 356 } 357 358 }