]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graphviz/src/org/simantics/graphviz/drawable/JViewer.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.graphviz / src / org / simantics / graphviz / drawable / JViewer.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.graphviz.drawable;\r
13 \r
14 import java.awt.Canvas;\r
15 import java.awt.Color;\r
16 import java.awt.Graphics;\r
17 import java.awt.Graphics2D;\r
18 import java.awt.Image;\r
19 import java.awt.Point;\r
20 import java.awt.RenderingHints;\r
21 import java.awt.event.ActionEvent;\r
22 import java.awt.event.ComponentAdapter;\r
23 import java.awt.event.ComponentEvent;\r
24 import java.awt.event.KeyAdapter;\r
25 import java.awt.event.KeyEvent;\r
26 import java.awt.event.MouseAdapter;\r
27 import java.awt.event.MouseEvent;\r
28 import java.awt.event.MouseWheelEvent;\r
29 import java.awt.event.MouseWheelListener;\r
30 import java.awt.event.WindowAdapter;\r
31 import java.awt.event.WindowEvent;\r
32 import java.awt.geom.AffineTransform;\r
33 import java.awt.geom.Rectangle2D;\r
34 import java.io.File;\r
35 import java.io.IOException;\r
36 \r
37 import javax.swing.AbstractAction;\r
38 import javax.swing.JFileChooser;\r
39 import javax.swing.JFrame;\r
40 import javax.swing.JMenu;\r
41 import javax.swing.JMenuBar;\r
42 import javax.swing.JMenuItem;\r
43 import javax.swing.JOptionPane;\r
44 import javax.swing.filechooser.FileFilter;\r
45 import javax.swing.filechooser.FileView;\r
46 \r
47 import org.simantics.graphviz.Graph;\r
48 import org.simantics.graphviz.Graphs;\r
49 \r
50 /**\r
51  * A stand alone frame that shows and makes it\r
52  * possible to navigate a given Drawable.\r
53  * \r
54  * @author Hannu Niemistö\r
55  */\r
56 public class JViewer extends JFrame {\r
57         private static final long serialVersionUID = 3022682167091092801L;\r
58         Drawable drawable;\r
59         ViewerCanvas canvas = new ViewerCanvas();\r
60         \r
61         class ViewerCanvas extends Canvas {\r
62                 private static final long serialVersionUID = -5330090168115281754L;\r
63                 AffineTransform transform;\r
64         Point prev;\r
65         Image im;\r
66                 \r
67         ViewerCanvas() {                \r
68                 setBackground(Color.WHITE);    \r
69                 addKeyListener(new KeyAdapter() {\r
70                         \r
71                         @Override\r
72                         public void keyPressed(KeyEvent e) {\r
73                                 if(e.getKeyChar()=='1') {\r
74                                         //System.out.println("a");\r
75                                         canvas.fit();\r
76                                         canvas.repaint();\r
77                                 }\r
78                                 else if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {\r
79                                         JViewer.this.dispose();\r
80                                 }\r
81                         }\r
82                         \r
83                 });\r
84                 addMouseListener(new MouseAdapter() {\r
85                         \r
86                         @Override\r
87                         public void mousePressed(MouseEvent e) {\r
88                                 prev = e.getPoint();\r
89                         }                       \r
90                 });\r
91                 addMouseMotionListener(new MouseAdapter() {\r
92                         @Override\r
93                         public void mouseDragged(MouseEvent e) {\r
94                                 Point cur = e.getPoint();\r
95                                 if (prev == null)\r
96                                     prev = cur;\r
97                                 double deltaX = cur.getX()-prev.getX();\r
98                                 double deltaY = cur.getY()-prev.getY();\r
99                                 transform.preConcatenate(AffineTransform.getTranslateInstance(deltaX, deltaY));                                         \r
100                                 repaint();\r
101                                 prev = cur;\r
102                         }\r
103                 });\r
104                 addMouseWheelListener(new MouseWheelListener() {\r
105 \r
106                                 @Override\r
107                                 public void mouseWheelMoved(MouseWheelEvent e) {\r
108                                         if(transform != null) {\r
109                                                 double scale = Math.exp(-0.1*e.getUnitsToScroll());\r
110                                                 Point p = e.getPoint();\r
111                                                 AffineTransform mod = new AffineTransform();\r
112                                                 mod.translate(p.getX(), p.getY());\r
113                                                 mod.scale(scale, scale);\r
114                                                 mod.translate(-p.getX(), -p.getY());\r
115                                                 transform.preConcatenate(mod);                                          \r
116                                                 repaint();\r
117                                         }\r
118                                 }\r
119                         \r
120                 });\r
121                 addComponentListener(new ComponentAdapter() {\r
122                         @Override\r
123                         public void componentResized(ComponentEvent e) {\r
124                                 im = createImage(getWidth(), getHeight());\r
125                                 repaint();\r
126                         }\r
127                 });\r
128         }\r
129                 \r
130         private void fit() {\r
131                 Rectangle2D bounds = drawable.getBounds();\r
132                 \r
133                 Rectangle2D container = getBounds();\r
134                 double scale = container == null ? 1 : Math.min(\r
135                                 container.getWidth() / bounds.getWidth(), \r
136                                 container.getHeight() / bounds.getHeight());\r
137                 \r
138                 transform = new AffineTransform(\r
139                                 scale, 0.0,\r
140                                 0.0, scale,\r
141                                 container.getX() + container.getWidth() * 0.5 - bounds.getCenterX() * scale,\r
142                                 container.getY() + container.getHeight() * 0.5 - bounds.getCenterY() * scale\r
143                                 );\r
144         }\r
145         \r
146         @Override\r
147         public void paint(Graphics _g) {\r
148                 if(im == null)\r
149                         im = createImage(getWidth(), getHeight());\r
150                 Graphics2D g = (Graphics2D)im.getGraphics();\r
151                 \r
152                 g.clearRect(0, 0, im.getWidth(null), im.getHeight(null));\r
153                 \r
154                 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
155                 g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);\r
156                 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);\r
157                                 \r
158                 if(transform == null)\r
159                         fit();\r
160                 g.setTransform(transform);\r
161                 \r
162                 drawable.draw(g, null);\r
163                 \r
164                 _g.drawImage(im, 0, 0, this);\r
165         }\r
166         \r
167         @Override\r
168         public void update(Graphics g) {\r
169                 paint(g);\r
170         }\r
171         \r
172     }\r
173         \r
174         public JViewer(Drawable _drawable) {\r
175                 this.drawable = _drawable;\r
176                 setTitle("Image viewer");\r
177                 setSize(1024, 768);\r
178             addWindowListener(new WindowAdapter(){\r
179                 public void windowClosing(WindowEvent we){\r
180                         dispose();\r
181                 }               \r
182                 @Override\r
183                 public void windowActivated(WindowEvent e) {\r
184                         repaint(0, 0, getWidth(), getHeight());             \r
185                 }\r
186                 @Override\r
187                 public void windowGainedFocus(WindowEvent e) {\r
188                     requestFocus();\r
189                 }\r
190             });\r
191             getContentPane().add(canvas);\r
192             \r
193             JMenuBar menuBar = new JMenuBar();\r
194             \r
195             JMenu menu = new JMenu("File");\r
196             menuBar.add(menu);\r
197             \r
198             JMenuItem saveItem = new JMenuItem(new SaveAsAction());\r
199             JMenuItem exitItem = new JMenuItem(new ExitAction());\r
200             menu.add(saveItem);\r
201             menu.addSeparator();\r
202             menu.add(exitItem);\r
203             setJMenuBar(menuBar);\r
204             \r
205             setVisible(true);\r
206         }\r
207         \r
208         public class ExitAction extends AbstractAction {\r
209 \r
210                 private static final long serialVersionUID = 5680421985865931443L;\r
211 \r
212                 public ExitAction() {\r
213                         super("Exit");\r
214                 }\r
215                 \r
216                 @Override\r
217                 public void actionPerformed(ActionEvent e) {\r
218                         JViewer.this.setVisible(false);\r
219                         JViewer.this.dispose();\r
220                 }\r
221         }\r
222         \r
223         public class SaveAsAction extends AbstractAction {\r
224                 \r
225                 private static final long serialVersionUID = 4627419396805081199L;\r
226 \r
227                 public SaveAsAction() {\r
228                         super("Save as");\r
229                 }\r
230                 \r
231                 @Override\r
232                 public void actionPerformed(ActionEvent e) {\r
233                         if (!(drawable instanceof GraphDrawable)) {\r
234                                 JOptionPane.showMessageDialog(JViewer.this, "File saving not supported", "Error",JOptionPane.ERROR_MESSAGE);\r
235                                 return;\r
236                         }\r
237                         GraphDrawable gdraw = (GraphDrawable)drawable;\r
238                         Graph graph = gdraw.getGraph();\r
239                         String algo = gdraw.getAlgorithm();\r
240                         JFileChooser chooser = new JFileChooser();\r
241                         chooser.addChoosableFileFilter(new DotImageFilter());\r
242                         chooser.setAcceptAllFileFilterUsed(false);\r
243                         chooser.setFileView(new DotImageFileView());\r
244                         int returnval = chooser.showSaveDialog(JViewer.this);\r
245                         if (returnval == JFileChooser.APPROVE_OPTION) {\r
246                                 try {\r
247                                         File file = chooser.getSelectedFile();\r
248                                 \r
249                                         String type = getExtension(file);\r
250                                         if (type == null)\r
251                                                 return;\r
252                                         Graphs.createImage(graph, algo, type, file);\r
253                                 } catch (IOException err) {\r
254                                         err.printStackTrace();\r
255                                         JOptionPane.showMessageDialog(JViewer.this, "File saving failed: " + err.getMessage(), "Error",JOptionPane.ERROR_MESSAGE);\r
256                                 }\r
257                         }\r
258                 }\r
259         }\r
260         \r
261         public static String getExtension(File file) {\r
262                 String filename = file.getName();\r
263                 int index = filename.lastIndexOf(".");\r
264                 if (index < 0)\r
265                         return null;\r
266                 return filename.substring(index+1).toLowerCase();\r
267         }\r
268         \r
269         public class DotImageFilter extends FileFilter {\r
270                 @Override\r
271                 public boolean accept(File f) {\r
272                         if (f.isDirectory())\r
273                                 return true;\r
274                         String ext = getExtension(f);\r
275                         if (ext == null)\r
276                                 return false;\r
277                         if (ext.equals("svg"))\r
278                                 return true;\r
279                         if (ext.equals("dot"))\r
280                                 return true;\r
281                         if (ext.equals("eps"))\r
282                                 return true;\r
283                         if (ext.equals("jpg"))\r
284                                 return true;\r
285                         if (ext.equals("jpeg"))\r
286                                 return true;\r
287                         if (ext.equals("pdf"))\r
288                                 return true;\r
289                         if (ext.equals("png"))\r
290                                 return true;\r
291                         if (ext.equals("ps"))\r
292                                 return true;\r
293                         return false;\r
294                 }\r
295                 \r
296                 @Override\r
297                 public String getDescription() {\r
298                         return "Image files";\r
299                 }\r
300         }\r
301         \r
302         public class DotImageFileView extends FileView {\r
303                 @Override\r
304                 public String getTypeDescription(File f) {\r
305                         String ext = getExtension(f);\r
306                         if (ext == null)\r
307                                 return null;\r
308                         if (ext.equals("svg"))\r
309                                 return "Scalable Vector Graphics Image";\r
310                         if (ext.equals("dot"))\r
311                                 return "DOT Image";\r
312                         if (ext.equals("eps"))\r
313                                 return "Encapsulated PostScript Image";\r
314                         if (ext.equals("jpg"))\r
315                                 return "JPG Image";\r
316                         if (ext.equals("jpeg"))\r
317                                 return "JPG Image";\r
318                         if (ext.equals("pdf"))\r
319                                 return "Portable Document Format Image";\r
320                         if (ext.equals("png"))\r
321                                 return "Portable Network Graphics Image";\r
322                         if (ext.equals("ps"))\r
323                                 return "PostScript Image";\r
324                         return null;\r
325                 }\r
326         }\r
327         \r
328 }\r