1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.graphviz.drawable;
14 import java.awt.Canvas;
15 import java.awt.Color;
16 import java.awt.Graphics;
17 import java.awt.Graphics2D;
18 import java.awt.Image;
19 import java.awt.Point;
20 import java.awt.RenderingHints;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ComponentAdapter;
23 import java.awt.event.ComponentEvent;
24 import java.awt.event.KeyAdapter;
25 import java.awt.event.KeyEvent;
26 import java.awt.event.MouseAdapter;
27 import java.awt.event.MouseEvent;
28 import java.awt.event.MouseWheelEvent;
29 import java.awt.event.MouseWheelListener;
30 import java.awt.event.WindowAdapter;
31 import java.awt.event.WindowEvent;
32 import java.awt.geom.AffineTransform;
33 import java.awt.geom.Rectangle2D;
35 import java.io.IOException;
36 import java.util.HashMap;
38 import javax.swing.AbstractAction;
39 import javax.swing.JFileChooser;
40 import javax.swing.JFrame;
41 import javax.swing.JMenu;
42 import javax.swing.JMenuBar;
43 import javax.swing.JMenuItem;
44 import javax.swing.JOptionPane;
45 import javax.swing.SwingUtilities;
46 import javax.swing.filechooser.FileFilter;
47 import javax.swing.filechooser.FileView;
49 import org.simantics.graphviz.Graph;
50 import org.simantics.graphviz.Graphs;
53 * A stand alone frame that shows and makes it
54 * possible to navigate a given Drawable.
56 * @author Hannu Niemist�
58 public class JViewer extends JFrame {
59 private static final HashMap<String, JViewer> VIEWER_MAP = new HashMap<String, JViewer>();
61 private static final long serialVersionUID = 3022682167091092801L;
63 ViewerCanvas canvas = new ViewerCanvas();
65 private String windowName;
67 class ViewerCanvas extends Canvas {
68 private static final long serialVersionUID = -5330090168115281754L;
69 AffineTransform transform;
74 setBackground(Color.WHITE);
75 addKeyListener(new KeyAdapter() {
78 public void keyPressed(KeyEvent e) {
79 if(e.getKeyChar()=='1') {
80 //System.out.println("a");
84 else if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
85 JViewer.this.dispose();
90 addMouseListener(new MouseAdapter() {
93 public void mousePressed(MouseEvent e) {
97 addMouseMotionListener(new MouseAdapter() {
99 public void mouseDragged(MouseEvent e) {
100 if(transform == null)
102 Point cur = e.getPoint();
105 double deltaX = cur.getX()-prev.getX();
106 double deltaY = cur.getY()-prev.getY();
107 transform.preConcatenate(AffineTransform.getTranslateInstance(deltaX, deltaY));
112 addMouseWheelListener(new MouseWheelListener() {
115 public void mouseWheelMoved(MouseWheelEvent e) {
116 if(transform == null)
118 double scale = Math.exp(-0.1*e.getUnitsToScroll());
119 Point p = e.getPoint();
120 AffineTransform mod = new AffineTransform();
121 mod.translate(p.getX(), p.getY());
122 mod.scale(scale, scale);
123 mod.translate(-p.getX(), -p.getY());
124 transform.preConcatenate(mod);
129 addComponentListener(new ComponentAdapter() {
131 public void componentResized(ComponentEvent e) {
132 im = createImage(getWidth(), getHeight());
139 Rectangle2D bounds = drawable.getBounds();
140 Rectangle2D container = getBounds();
142 if(bounds == null || container == null)
145 double scale = container == null ? 1 : Math.min(
146 container.getWidth() / bounds.getWidth(),
147 container.getHeight() / bounds.getHeight());
149 transform = new AffineTransform(
152 container.getX() + container.getWidth() * 0.5 - bounds.getCenterX() * scale,
153 container.getY() + container.getHeight() * 0.5 - bounds.getCenterY() * scale
158 public void paint(Graphics _g) {
160 im = createImage(getWidth(), getHeight());
161 Graphics2D g = (Graphics2D)im.getGraphics();
163 g.clearRect(0, 0, im.getWidth(null), im.getHeight(null));
165 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
166 g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
167 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
169 if(transform == null) {
171 if(transform == null) {
172 g.setTransform(new AffineTransform());
173 g.setColor(Color.BLACK);
174 g.drawString("No data available yet", 20f, 20f);
178 g.setTransform(transform);
180 drawable.draw(g, null);
182 _g.drawImage(im, 0, 0, this);
186 public void update(Graphics g) {
192 public JViewer(Drawable _drawable) {
193 this.drawable = _drawable;
194 setTitle("Image viewer");
196 addWindowListener(new WindowAdapter(){
197 public void windowClosing(WindowEvent we){
201 public void windowActivated(WindowEvent e) {
202 repaint(0, 0, getWidth(), getHeight());
205 public void windowGainedFocus(WindowEvent e) {
209 getContentPane().add(canvas);
211 JMenuBar menuBar = new JMenuBar();
213 JMenu menu = new JMenu("File");
216 JMenuItem saveItem = new JMenuItem(new SaveAsAction());
217 JMenuItem exitItem = new JMenuItem(new ExitAction());
221 setJMenuBar(menuBar);
226 public void updateDrawable(Drawable drawable) {
227 this.drawable = drawable;
232 public class ExitAction extends AbstractAction {
234 private static final long serialVersionUID = 5680421985865931443L;
236 public ExitAction() {
241 public void actionPerformed(ActionEvent e) {
242 JViewer.this.setVisible(false);
243 JViewer.this.dispose();
247 public class SaveAsAction extends AbstractAction {
249 private static final long serialVersionUID = 4627419396805081199L;
251 public SaveAsAction() {
256 public void actionPerformed(ActionEvent e) {
257 if (!(drawable instanceof GraphDrawable)) {
258 JOptionPane.showMessageDialog(JViewer.this, "File saving not supported", "Error",JOptionPane.ERROR_MESSAGE);
261 GraphDrawable gdraw = (GraphDrawable)drawable;
262 Graph graph = gdraw.getGraph();
263 String algo = gdraw.getAlgorithm();
264 JFileChooser chooser = new JFileChooser();
265 chooser.addChoosableFileFilter(new DotImageFilter());
266 chooser.setAcceptAllFileFilterUsed(false);
267 chooser.setFileView(new DotImageFileView());
268 int returnval = chooser.showSaveDialog(JViewer.this);
269 if (returnval == JFileChooser.APPROVE_OPTION) {
271 File file = chooser.getSelectedFile();
273 String type = getExtension(file);
276 Graphs.createImage(graph, algo, type, file);
277 } catch (IOException err) {
278 err.printStackTrace();
279 JOptionPane.showMessageDialog(JViewer.this, "File saving failed: " + err.getMessage(), "Error",JOptionPane.ERROR_MESSAGE);
285 public static String getExtension(File file) {
286 String filename = file.getName();
287 int index = filename.lastIndexOf(".");
290 return filename.substring(index+1).toLowerCase();
293 public class DotImageFilter extends FileFilter {
295 public boolean accept(File f) {
298 String ext = getExtension(f);
301 if (ext.equals("svg"))
303 if (ext.equals("dot"))
305 if (ext.equals("eps"))
307 if (ext.equals("jpg"))
309 if (ext.equals("jpeg"))
311 if (ext.equals("pdf"))
313 if (ext.equals("png"))
315 if (ext.equals("ps"))
321 public String getDescription() {
322 return "Image files";
326 public class DotImageFileView extends FileView {
328 public String getTypeDescription(File f) {
329 String ext = getExtension(f);
332 if (ext.equals("svg"))
333 return "Scalable Vector Graphics Image";
334 if (ext.equals("dot"))
336 if (ext.equals("eps"))
337 return "Encapsulated PostScript Image";
338 if (ext.equals("jpg"))
340 if (ext.equals("jpeg"))
342 if (ext.equals("pdf"))
343 return "Portable Document Format Image";
344 if (ext.equals("png"))
345 return "Portable Network Graphics Image";
346 if (ext.equals("ps"))
347 return "PostScript Image";
352 public static void getOrCreateViewer(String windowName, GraphDrawable graphDrawable) {
353 JViewer viewer = VIEWER_MAP.get(windowName);
355 viewer = new JViewer(graphDrawable);
356 viewer.setTitle(windowName);
357 viewer.windowName = windowName;
358 VIEWER_MAP.put(windowName, viewer);
362 viewer.updateDrawable(graphDrawable);
368 public void dispose() {
369 if(windowName != null)
370 VIEWER_MAP.remove(windowName);