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 Point cur = e.getPoint();
103 double deltaX = cur.getX()-prev.getX();
104 double deltaY = cur.getY()-prev.getY();
105 transform.preConcatenate(AffineTransform.getTranslateInstance(deltaX, deltaY));
110 addMouseWheelListener(new MouseWheelListener() {
113 public void mouseWheelMoved(MouseWheelEvent e) {
114 if(transform != null) {
115 double scale = Math.exp(-0.1*e.getUnitsToScroll());
116 Point p = e.getPoint();
117 AffineTransform mod = new AffineTransform();
118 mod.translate(p.getX(), p.getY());
119 mod.scale(scale, scale);
120 mod.translate(-p.getX(), -p.getY());
121 transform.preConcatenate(mod);
127 addComponentListener(new ComponentAdapter() {
129 public void componentResized(ComponentEvent e) {
130 im = createImage(getWidth(), getHeight());
137 Rectangle2D bounds = drawable.getBounds();
139 Rectangle2D container = getBounds();
140 double scale = container == null ? 1 : Math.min(
141 container.getWidth() / bounds.getWidth(),
142 container.getHeight() / bounds.getHeight());
144 transform = new AffineTransform(
147 container.getX() + container.getWidth() * 0.5 - bounds.getCenterX() * scale,
148 container.getY() + container.getHeight() * 0.5 - bounds.getCenterY() * scale
153 public void paint(Graphics _g) {
155 im = createImage(getWidth(), getHeight());
156 Graphics2D g = (Graphics2D)im.getGraphics();
158 g.clearRect(0, 0, im.getWidth(null), im.getHeight(null));
160 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
161 g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
162 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
164 if(transform == null)
166 g.setTransform(transform);
168 drawable.draw(g, null);
170 _g.drawImage(im, 0, 0, this);
174 public void update(Graphics g) {
180 public JViewer(Drawable _drawable) {
181 this.drawable = _drawable;
182 setTitle("Image viewer");
184 addWindowListener(new WindowAdapter(){
185 public void windowClosing(WindowEvent we){
189 public void windowActivated(WindowEvent e) {
190 repaint(0, 0, getWidth(), getHeight());
193 public void windowGainedFocus(WindowEvent e) {
197 getContentPane().add(canvas);
199 JMenuBar menuBar = new JMenuBar();
201 JMenu menu = new JMenu("File");
204 JMenuItem saveItem = new JMenuItem(new SaveAsAction());
205 JMenuItem exitItem = new JMenuItem(new ExitAction());
209 setJMenuBar(menuBar);
214 public void updateDrawable(Drawable drawable) {
215 this.drawable = drawable;
220 public class ExitAction extends AbstractAction {
222 private static final long serialVersionUID = 5680421985865931443L;
224 public ExitAction() {
229 public void actionPerformed(ActionEvent e) {
230 JViewer.this.setVisible(false);
231 JViewer.this.dispose();
235 public class SaveAsAction extends AbstractAction {
237 private static final long serialVersionUID = 4627419396805081199L;
239 public SaveAsAction() {
244 public void actionPerformed(ActionEvent e) {
245 if (!(drawable instanceof GraphDrawable)) {
246 JOptionPane.showMessageDialog(JViewer.this, "File saving not supported", "Error",JOptionPane.ERROR_MESSAGE);
249 GraphDrawable gdraw = (GraphDrawable)drawable;
250 Graph graph = gdraw.getGraph();
251 String algo = gdraw.getAlgorithm();
252 JFileChooser chooser = new JFileChooser();
253 chooser.addChoosableFileFilter(new DotImageFilter());
254 chooser.setAcceptAllFileFilterUsed(false);
255 chooser.setFileView(new DotImageFileView());
256 int returnval = chooser.showSaveDialog(JViewer.this);
257 if (returnval == JFileChooser.APPROVE_OPTION) {
259 File file = chooser.getSelectedFile();
261 String type = getExtension(file);
264 Graphs.createImage(graph, algo, type, file);
265 } catch (IOException err) {
266 err.printStackTrace();
267 JOptionPane.showMessageDialog(JViewer.this, "File saving failed: " + err.getMessage(), "Error",JOptionPane.ERROR_MESSAGE);
273 public static String getExtension(File file) {
274 String filename = file.getName();
275 int index = filename.lastIndexOf(".");
278 return filename.substring(index+1).toLowerCase();
281 public class DotImageFilter extends FileFilter {
283 public boolean accept(File f) {
286 String ext = getExtension(f);
289 if (ext.equals("svg"))
291 if (ext.equals("dot"))
293 if (ext.equals("eps"))
295 if (ext.equals("jpg"))
297 if (ext.equals("jpeg"))
299 if (ext.equals("pdf"))
301 if (ext.equals("png"))
303 if (ext.equals("ps"))
309 public String getDescription() {
310 return "Image files";
314 public class DotImageFileView extends FileView {
316 public String getTypeDescription(File f) {
317 String ext = getExtension(f);
320 if (ext.equals("svg"))
321 return "Scalable Vector Graphics Image";
322 if (ext.equals("dot"))
324 if (ext.equals("eps"))
325 return "Encapsulated PostScript Image";
326 if (ext.equals("jpg"))
328 if (ext.equals("jpeg"))
330 if (ext.equals("pdf"))
331 return "Portable Document Format Image";
332 if (ext.equals("png"))
333 return "Portable Network Graphics Image";
334 if (ext.equals("ps"))
335 return "PostScript Image";
340 public static void getOrCreateViewer(String windowName, GraphDrawable graphDrawable) {
341 JViewer viewer = VIEWER_MAP.get(windowName);
343 viewer = new JViewer(graphDrawable);
344 viewer.setTitle(windowName);
345 viewer.windowName = windowName;
346 VIEWER_MAP.put(windowName, viewer);
350 viewer.updateDrawable(graphDrawable);
356 public void dispose() {
357 if(windowName != null)
358 VIEWER_MAP.remove(windowName);