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    }